问题
I am trying to create a form where I can edit all of the items in a collection individually in a single view. I used Railscast #198 ( http://railscasts.com/episodes/198-edit-multiple-individually ) as a general guide but did not include the checkboxes since I want to just edit every item in the collection at once (not select which ones to edit). With what I currently have, the form displays correctly but I get this type of error upon submit:
ArgumentError in ProceduresController#update_procedures
wrong number of arguments (0 for 2).
Parameters:
{"utf8"=>"✓",
"_method"=>"put",
"authenticity_token"=>"i9kB+uGlguerjxl0VHy1dRyMY5HrZQdILVuM79Df4Z4=",
"procedures"=>{"1"=>{"description"=>"Example1"},
"2"=>{"description"=>"Example2"}},
"commit"=>"Submit",
"comp_id"=>"1"}
Please tell me what I am missing here:
In my controller:
def edit_procedures
@comp = Comp.find(params[:comp_id])
@procedures = @comp.procedures.all
end
def update_procedures
@comp = Comp.find(params[:comp_id])
@procedures = @comp.procedures.update.(params[:procedures].keys,
params[:procedures].values).reject { |p| p.errors.empty? }
end
In my routes:
resources :comps do
resources :procedures do
collection do
get 'edit_procedures'
put 'update_procedures'
end
end
end
In my view:
<%= form_tag update_procedures_comp_procedures_path(@comp), :method => :put do %>
<% for procedure in @procedures %>
<%= fields_for "procedures[]", procedure do |f| %>
<% if params[:field].blank? || params[:field] == "description" %>
<%= f.label :description %>
<%= f.text_field :description %>
<% end %>
<% end %>
<% end %>
<p><%= submit_tag "Submit" %></p>
<% end %>
I also tried changing the 'edit_procedures' method from GET to POST, but then I got this error: Unknown action, The action 'show' could not be found for ProceduresController.
Thanks for the help.
回答1:
UPDATE:
Actually, this solution I just figured out is much better. I just changed the form to this (in addition to changes to controller listed below):
<%= form_for @comp, :url => 'update_procedures', :method => :put do |f| %>
<%= f.fields_for :procedures do |g| %>
<%= g.text_field :description %>
<% end %>
<%= f.submit "Update procedures" %>
<% end %>
ORIGINAL ANSWER:
No one answered this and I struggled for a day to figure it out myself, so I'm going to share how I solved it:
In my view, I changed 3 things 1. added a hidden field that adds the procedure id to the hash, 2. added the "comp" object to the beginning of the hash, and 3. changed "procedures" to "procedures_attributes" (so that the generated hash looks exactly like the hash generated by a form_for fields_for nested form with nested attributes)
So the form ended up looking like:
<%= form_tag update_procedures_comp_procedures_path(@comp), :method => :put do %>
<% for procedure in @procedures %>
<%= fields_for 'comp[procedures_attributes]', procedure do |f| %>
<% if params[:field].blank? || params[:field] == "description" %>
<%= f.label :description %><br />
<%= f.text_field :description %>
<%= f.hidden_field :id, :value => procedure.id %>
<% end %>
<% end %>
<% end %>
<p><%= submit_tag "Submit" %></p>
<% end %>
Then in my procedures controller, rather than updating the procedure object, it updates the comp object using nested attributes to update the underlying procedure attributes:
def update_procedures
@comp = Comp.find(params[:comp_id])
if @comp.update_attributes(params[:comp])
redirect_to(new_comp_procedure_path(@comp))
else
render 'edit_procedures'
end
This seems to work, but if there is a more straightforward way of accomplishing this, please let me (and anyone else who reads this) know. Thanks.
回答2:
I know I'm six years late, but it looks like it was a simple typo inside your #update_procedures
method:
# this...
@procedures = @comp.procedures.update.(params[:procedures].keys,
params[:procedures].values).reject { |p| p.errors.empty? }
# should be this...
@procedures = @comp.procedures.update(params[:procedures].keys,
params[:procedures].values).reject { |p| p.errors.empty? }
(removed the dot after the call to #update
)
I'm sure you've been losing sleep over this for years, so cry no longer, your hero has arrived.
来源:https://stackoverflow.com/questions/13245182/editing-nested-collection-through-1-form-in-rails