Editing nested collection through 1 form in Rails

痞子三分冷 提交于 2019-12-11 05:56:12

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!