Nested forms with multiple models


#1

Hey guys, I need your help again!

I have a form in which I want to nest multiple models. Kind of like “a
project has many tasks” but rather “a flight has one flight time per
flight type”.

So it’s three models - Flight, FlightType and FlightTime. Flight ->
FlightTime <- FlightType

What I want to do is to loop through the FlightTypes in the add/edit
Flight form, and present a text box whose value then will be stored
as :hours in a FlightTime along with a :flight_id and :flight_type_id
value. I hope I’ve made myself clear.

This is the code I have in my flight_form view currently:

http://pastie.org/312947

Now this works perfectly when adding FlightTimes as I’m using a
FlightTime.new, but the issue I have is that I also want to be able to
edit the values. When I try to use this form for editing, all the
values in the boxes are emptied and anything I put in them are added
as new FlightTimes (obviously). There can only be one FlightTime per
FlightType per Flight, so to speak.

So, anyone up for the task to help me out?

Thanks,
Alex


#2

one suggestion: don’t put business logic in your views. replace
“FlightTime.new” with “@flight_time” and let your controller figure
out if it should be a new or existing record.


#3

On Nov 13, 12:40 am, jemminger removed_email_address@domain.invalid wrote:

one suggestion: don’t put business logic in your views. replace
“FlightTime.new” with “@flight_time” and let your controller figure
out if it should be a new or existing record.

On Nov 12, 7:32 am, Alex J. removed_email_address@domain.invalid wrote:

Now this works perfectly when adding FlightTimes as I’m using a
FlightTime.new, but the issue I have is that I also want to be able to
edit the values. When I try to use this form for editing, all the
values in the boxes are emptied and anything I put in them are added
as new FlightTimes (obviously). There can only be one FlightTime per
FlightType per Flight, so to speak.

As per jemminger, if you want your action and template to both create
new objects and edit existing ones you need to put this logic into the
action in the controller.

So you might have:
if params[:id]
@foo=Foo.find(params[:id])
else
@foo=Foo.new
end

In your view, you can then get rails to put whatever values are
currently in @foo into your fields:
form_for :foo , :url … do |f|
f.text_field :field1

end

or:
fields_for :foo do |f|
f.text_field :field1

end

and rails will automagic in @foo.field1 as the value in that text
field because you specified ‘:foo’.
(Sorry, can’t get my head around your models)

I was thinking that if you have an array of objects eg foo has_many
bars and you want to edit all those bars, then in the view you could
loop thru the array with an index eg:

@foo.bars.each_with_index do |bar,idx|
fields_for “bars[#{idx}]” , bar do |b|
b.text_field :field1

end

end

Which, on submission, will generate
params[‘bars’][‘0’][‘field1’] =>
etc
Not sure if that’s good but I think it works.
You could skip the whole ‘with_index’ thing if it’s just has_one.

You’ll also need to embed id value for each record into a hidden field
in your form if you’re editing an existing item so that you can find
it and update it instead of creating a new object when the form is
submitted.
There are security implications here - people can post a random id
instead - so you need to think that through carefully.


Daniel B.