HOWTO Create a simple parent-child form in Rails 3.1

I’m finding Rails quite difficult conceptually. People tell me one day the light will dawn and it will all seem perfectly natural. At the moment though it seems like there’s 1000 ways to achieve any given objective, but only one right one. If you choose one of the other 999 then you’re in a world of manual coding as a result.

I couldn’t find a really basic example of nested forms: a parent record with an arbitrary number of child records. Here’s my attempt to create the simplest possible parent-child forms, with the minimum configuration and the maximum convention. Rails experts: I’d love to reduce this even further – please give me any suggestions for doing so.

The resulting forms can be cloned directly fromĀ https://github.com/moo-li/Simple-parent-child-forms-in-Rails-3.1, but here’s how to create them yourself:

  1. At the command prompt, create a new Rails application:
    rails new myapp (where myapp is the application name). If you want HTML5
    goodness then rails new myapp -m https://github.com/russfrisch/h5bp-rails/raw/master/h5bp.rb.
  2. cd myapp
  3. rails g scaffold Mom name:string
  4. rails g model Kid name:string mom:references
  5. Add the following lines to app/models/mom.rb
    has_many :kids, :dependent => :destroy
    accepts_nested_attributes_for :kids, :allow_destroy => :true
  6. rake db:migrate
  7. In config/routes.rb, change resources :momsto
    resources :moms do
      resources :kids
    end
  8. rails g controller Kids
  9. Add the following methods to app/controllers/kids_controller.rb
    def create
      @mom = Mom.find(params[:mom_id])
      @kid = @mom.kids.create(params[:kid])
      redirect_to mom_path(@mom)
    end
    
    def destroy
      @mom = Mom.find(params[:mom_id])
      @kid = @mom.kids.find(params[:id])
      @kid.destroy
      redirect_to mom_path(@mom)
    end
  10. Add the following lines to app/views/moms/show.html.erb before the line
    containing <%= link_to 'Edit', edit_mom_path(@mom) %> |

    <h2>Kids</h2>
    <%= render @mom.kids %>
    
    <h3>Add kid</h3>
    <%= render 'kids/form' %>
  11. Create a file app/views/kids/_kid.html.erbwith the following code:
    <p>
      <strong>Kid:</strong>
      <%= kid.name %>
      <%= link_to 'Remove', [kid.mom, kid], :confirm => 'Really remove kid?', :method => :delete %>
    </p>
  12. Create a file app/views/kids/_form.html.erbwith the following code:
    <%= form_for([@mom, @mom.kids.build]) do |f| %>
      <div class="field">
        <%= f.label :name %> <%= f.text_field :name %>
      </div>
    
      <div class="actions">
        <%= f.submit %>
      </div>
    <% end %>
  13. rails s
  14. Point your browser to http://localhost:3000/moms.

14 thoughts on “HOWTO Create a simple parent-child form in Rails 3.1

  1. Very helpful post! I have been looking all over the net for this and fortunately I found yours. Keep up the good work. Thank you soooooooooooooo much!

    • Never mind, I was being over zealous with parent_id ( validates :parent_id, :presence => true ) will give you a headache if you try and do a nested create

  2. Hello, this is very good example!
    I’m trying to do the child edit but i have a : No route matches [POST] “/moms/1/kids/1/edit”

    My code is there :

    i add this line in _kid.html.erb : :edit %>

    and this line in my kid controller :
    def edit
    @kid = @mom.kids.find(params[:id])
    end

    Can you help me ?

    Thanks!

Leave a Reply