1

I have read a number of posts about this and I'm still confused. I'm relatively new to Rails. I'm on Rails 3.2.8 and Ruby 1.9.3.

I have a form where I want to create a record for 2 different tables. It's a many-to-many relationship (logbooks can have multiple aircraft and aircraft will appear in multiple logbooks).

Here's my code:

# ----- Models ----- #
class Logbook < ActiveRecord::Base
  has_and_belongs_to_many :aircrafts
  accepts_nested_attributes_for :aircrafts
end

class Aircraft < ActiveRecord::Base
  belongs_to :logbook
end

# ----- Logbooks Controller ----- #
def my_method
  @logbook = Logbook.new 
  @aircraft = Aircraft.new
end

# ----- View ----- #
<%= form_for @logbook, validate: true, remote: true do |f| %>
  <%= f.label :flight_date, "Flight Date" %>
  <%= f.text_field :flight_date %>  
  ...

  <%= f.fields_for :aircrafts, validate: true, remote: true do |a| %>
    <%= a.label :aircraft_id, "Aircraft ID" %>
    <%= a.text_field :aircraft_id %>
    ...
  <% end %>
<% end %>

The logbook fields are rendering fine, but the aircraft fields don't render.

Any ideas?

2 Answers 2

2

Try changing the controller to:

def my_method
  @logbook = Logbook.new 
  @aircraft = @logbook.aircrafts.build
end

Because @aircraft need belongs_to a Logbook, so the nested_form will know how to build the form.

Note: if you will not use the variable @aircraft you don't need to declare it, just use @logbook.aircrafts.build on controller

Sign up to request clarification or add additional context in comments.

3 Comments

OP, definitely use the aircrafts.build like shows here, as supposed to the << Aircraft.new that I did. Not sure why i didn't refer to the build. I think i had a brain lapse.
Thanks for your response. So if I adjust my controller like you indicated, does this f.fields_for :aircrafts need to change to this f.fields_for @aircraft?
No that way, you can specify @aircraft as second parameter in fields_for, see more on ActionView::Helpers::FormHelper#fields_for
0

If i recall correctly, the fields_for will generate based off the number of objects in the has many that exist for the parent. Since your @logbook doesn't have any aircrafts, no fields appear. Try changing the action:

def my_method
  @logbook = Logbook.new
  @logbook.aircrafts << Aircraft.new
end

Now, if you need to make something in the UI to add more than one logbook, you need to create an add button. You can just increment the amount of aircraft records you build based off that:

<%= form_tag new_logbook_path, :method => :get do %>
  <%= hidden_field_tag "amount", @amount %>
  <%= submit_tag "Add" %>
<% end %>

Then the action would be:

def my_method
  @amount = params[:amount] || 1
  @logbook = Logbook.new
  @amount.times { @logbook.aircrafts << Aircraft.new }
end

4 Comments

I would also advise caution with the "remote: true" part of the aircrafts forms. Since the entire form will be a remote form based on the declaration that it is remote when the original form is created, I'm not sure that is needed again, and I would try seeing if it works without it. Also, and this is a minor quibble, but "aircrafts" is not grammatically correct. When you work with others, your code should be readable. "Airplanes" would be better.
Yup a good point. Sometimes it's best to remove JS/ajax stuff and make sure it works without it before pursuing nice UI stuff.
Thanks for your help. I chose "aircrafts" because my app isn't limited to airplanes (also includes gliders, helicopters, balloons, etc.). The requirements I'm up against refer to everything as an aircraft, so I went with that. Using "aircrafts" has bothered me, but Rails wants a plural word. :)
Well as far as english goes, an aircraft would be a general name for the types you mentioned. So singular it works. A model should generally represent a single object. Yeah it generally depends on singular name for the model, plural for the table. You can customize that stuff, but it can often cause more headache than it is worth.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.