Reputation: 34643
Some pseudocode from my app:
User has many Products
User has many Projects
Project and Product belong to User
Furthermore:
Project has one Video
Video belongs to Project
I have a multi-step wizard built using the Wicked gem. In step one I create and save a Project. In step two I add a Video to that Project:
= form_for @project do |f|
= f.fields_for :video_attributes do |v|
= v.file_field :file
Everything works fine, but I'd like to add a Product to the Project's User during this same step. I'm a little confused as to how accepts nested attributes works for this sort of thing.
I imagine I need to do something like this in my wicked controller:
@user = current_user
# wicked makes us use :project_id as it hijacks :id
@project = @user.projects.find(params[:project_id])
@user.products.build
But where do I stick the 'nested attributes for' call? Do I need more than one call to accepts_nested_attributes_for? Would this work?
Make Project model accept nested attributes for User
Make User model accept nested attributes for Product
= form_for @product do |f|
= f.fields_for :user_attributes do |u|
= u.fields_for :product_attributes do |p|
= p.file_field :image
I can't try the code out till tomorrow, but i will sleep better knowing i can solve this when i get to it.
Upvotes: 0
Views: 376
Reputation: 18037
You certainly can extend nested attributes through several objects by nesting the fields_for
calls... But you can sometimes get into trouble if you jump back and forth between objects like it looks like you're headed towards here. I've had problems with circular save issues resulting from structures like that. For this reason, I recommend keeping the accepts_nested_attributes_for
as a one-way street. So, if a user accepts_nested_attributes_for projects then a project should not also accepts_nested_attributes_for users. Given that, your form has to be built based on the root object. I don't know your project but for mine that was the user. Basically, it's more likely the user would be the central relationship. Hope this helps.
Also, I'm not sure why your fields_for
calls are using <some object>_attributes
. Unless you're doing something special, those should be relation names like f.fields_for :video
. This way the fields_for
call loops through each object of that type in the collection.
Upvotes: 1