← Back to Upcase

Rails partial renders three times


(Chris Kuffo) #1

I have a weird situation.

In my users controller I have an if else statement that renders a
partial (i created for errors) based on if my sign up form passes
validation. For instance if someone forgets to put in their name or
enter an email address the message will appear at the top of the form.
Everything was working correctly up until i decided i would rather my
signup form appear on my home page and i would display it as a partial.
Now that the form is in a partial i still receive the validation error
but it shows three times instead of just once. When the sign up form was
on its on page it only displayed once. Why would rails render the
partial I created to show errors three times just because i made the
sign up into a partial?

Any help would be greatly appreciated.


(Derek Prior) #2

It’s tough to say without any code or logs. Can you show your controller and view code? What does your development log say?


(Chris Kuffo) #3

My home page calls this signup partial with this code

<div class="col-lg-6">
          <%= render "users/signup" %>
        </div>

This is the signup form code

<%= form_tag('/users', remote: true) do |f| %>
<div class="form-group">
  <div class="row fm-space">
    <div class="col-lg-6">
      <%= text_field_tag :first_name, '', :name => "user[first_name]", :class => 'form-control', :placeholder => 'FIRST NAME' %>
    </div>
    <div class="col-lg-6">
      <%= text_field_tag :last_name, '', :name => "user[last_name]", :class => 'form-control', :placeholder => 'LAST NAME'  %>
    </div>
  </div>
</div>

<div class="form-group">
  <div class="row fm-space">
    <div class="col-lg-12">
      <%= email_field_tag :email, '', :name => "user[email]", :class => 'form-control', :placeholder => 'EMAIL'  %>
    </div>
  </div>
</div>

<div class="form-group">
  <div class="row fm-space">
    <div class="col-lg-12">
      <%= password_field_tag :password, '', :name => "user[password]", :class => 'form-control', :placeholder => 'PASSWORD'  %>
    </div>
  </div>
</div>

<div class="form-group">
  <div class="row fm-space">
    <div class="col-lg-12">
    <%= password_field_tag :password_confirmation, '', :name => "user[password_confirmation]" , :class => 'form-control', :placeholder => 'PASSWORD CONFIRMATION' %>
    </div>
  </div>
</div>

<div class="checkbox">
    <label>
      <input type="checkbox"><span>I AGREE TO THE <a href="#">TERMS OF SERVICE</a></span>
    </label>
</div>

<!-- Button trigger modal and submit form -->
<button type="submit" class="btn btn-primary btn-lg btn-block">SIGN UP</button>   
<% end %>

My user_controller looks like this

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      session[:user_id] = @user.id
      
      if request.xhr?
        render partial: "questionnaire", object: @user, as: 'user'
      else
        # TODO: error handling if users created without AJAX form submission
        redirect_to @user
      end

    else
      # If @user is not valid, the new user form will be rendered with errors
      render partial: "layouts/errors", object: @user, as: 'object'
    end
  end

  def update
    # TODO: the 2nd part of new user signup will effectively update our existing, basic user
    @user = User.find_by(session[:user_id])
    binding.pry
    # flash[:notice] = "Thank you for signing up!"
  end

  private

  def user_params
    params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :company)
  end
end

The partial error page that gets called when the form doesn’t validate correctly

<div class="row">
  <% if object.errors.any? %>
    <div class="alert alert-warning alert-dismissable col-md-6">
      <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
      <strong>Form is invalid!</strong>
      <ul>
        <% object.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>
</div>

Everything worked fine when the signup form wasn’t a partial and was on its on page. Only one error message would display. Now that the form is a partial on my home page i get three copy of the same error message.


(Derek Prior) #4

Why are you using form_tag rather than form_for @user? Is this an XHR request? If so, did you know about remote: true for the form_for helper?

It’s also curious that the partial you’re rendering is in layouts. It’s not actually a layout, right?

If this is XHR, can you show the JS that is performing the request and the JavaScript that is handling the response?


(Chris Kuffo) #5

Here is the javascript

// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

$(document).ready(function(){

  $('form').submit(function() {
      var valuesToSubmit = $(this).serialize();
      $.ajax({
        url: $(this).attr('action'), //sumbits it to the given url of the form
        type: "POST",
        dataType: "HTML",
        data: valuesToSubmit,
        success: function(data) {
          // Attach the data HTML to the DOM body
          $('div.container').prepend(data);
          $('#myModal').modal('show');
        },
        // If something went wrong... meaning the controller/app doesn't return HTML data type, basically, I think?
        error: function(responseObject) {
          // TODO: put some real code here...
          alert("Woops, try again!");
        }
      });
      return false; // prevents normal behavior, i.e. AJAX only
  });

});

(Chris Kuffo) #6

Hi Derek - thank you for all your help so far.

When I try

<%= form_for(@user, remote: true) do |f| %>

The form fails - I get an error

First argument in form cannot contain nil or be empty.

(Luís Ferreira) #7

@chriskuffo That’s because the @user is nil. You need to instantiate on the controller action that renders the form.


(Chris Kuffo) #8

Thanks zamith - Ill look into that.