Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • Form Helpers in Rails Part-4 (Building Complex Forms)

    • 0
    • 1
    • 1
    • 1
    • 0
    • 0
    • 0
    • 0
    • 180
    Comment on it

    Hi friends,
    In my previous blog, we talked about customization of form helpers and how to create forms for external resources through form helpers in Form Helpers in Rails Part-3. Now we will switch to discuss on how to build complex forms in rails.
    In some apps, there is complex associations between models and because of some requirements there form structures also need to be complex. For that we can't rely on basic forms that we have looked at so far. Suppose while creating a Car model you might want to add different models associated with car in the same form and for later it should be available to add, edit or remove them. Thus for these requirements your models, views and controllers should be like:

    Configuring Controller :
    Active records in rails provide accepts_nested_attributes_for, that creates an addresses_attributes= on model, that allows to create, update or destroy the models of the car.

    class Car < ActiveRecord::Base
      has_many :models
      accepts_nested_attributes_for :models
    end
     
    class Model < ActiveRecord::Base
      belongs_to :car
    end
    


    Creating Nested Forms:
    Nesting in forms can be done as:

    <%= form_for @car do |f| %>
      Models:
      <ul>
        <%= f.fields_for :models do |models_form| %>
          <li>
            <%= models_form.label :number %>
            <%= models_form.text_field :number %>
     
            <%= models_form.label :color %>
            <%= models_form.text_field :color %>
            ...
          </li>
        <% end %>
      </ul>
    <% end %>
    


    One thing to be noted is that fields_for in nested form runs for each associated models of car. So if no model is present, it renders nothing. So the common practice is to build one or more empty children of the controller, so that at least one set of field is shown to the user. This can be done as:

    def new
      @car = Car.new
      2.times { @car.models.build}
    end
    


    The submitted parameters of the nested forms would be like:

    {
      'car' => {
        'name' => 'Swift',
        'models_attributes' => {
          '0' => {
            'number' => 'evi2',
            'color' => 'grey'
          },
          '1' => {
            'number' => 'deZire',
            'color' => 'white'
          }
        }
      }
    }
    


    If the associated object is already exists, fields_for generates a hidden input with the id of the existing record. You can disable this by passing include_id: false to fields_for.

    Controller Changes:
    In controller you need to white-list the parameters before saving them into the model.

    def create
      @car = Car.new(car_params)
    end
     
    private
      def car_params
        params.require(:car).permit(:name, models_attributes: [:id, :number, :color])
      end
    


    You can allow user to delete the associated records and also can prevent user to save empty records. Both these can be done as done in the following example:

    #In Model
    class Car < ActiveRecord::Base
      has_many :models
      accepts_nested_attributes_for :models, allow_destroy: true,
            reject_if: lambda {|attributes| attributes['number'].blank?}
    
    end
    
    #In Form
    <%= form_for @car do |f| %>
      Models:
      <ul>
        <%= f.fields_for :models do |models_form| %>
          <li>
            <%= models_form.check_box :_destroy%>
            <%= models_form.label :number %>
            <%= models_form.text_field :number %>
            ...
          </li>
        <% end %>
      </ul>
    <% end %>
    

 0 Comment(s)

Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: