Jim Burgess
2010-Dec-29 19:33 UTC
Help needed understanding "fields_for" and resultant controller code
Hi, I''m trying to understand some code in a book I''m reading and was hoping someone could tell me if I have understood it correctly. There are two models, an employee model and a department model. A department has_many :employees and an employee belongs_to :department. Here''s a snippet of code from the form to edit an existing employee: <% fields_for( @employee.department) do |department_f| %> <p> <%= department_f.label :name,"Department name" %><br /> <%= department_f.text_field :name %> </p> <% end %> The form is submitted to the update action of ''employees_controller.rb'', where there is the following code: if @employee.update_attributes(params[:employee]) && @employee.department.update_attributes(params[:department]) ... employee successfully updated ... end My question is about the line "@employee.department.update_attributes(params[:department])" Is it correct to say that this code updates the attributes (in this case "name") of the Department object that is linked (via the "has_many" and "belongs_to" relationship) to the Employee object currently being edited? -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Philip Hallstrom
2010-Dec-29 19:41 UTC
Re: Help needed understanding "fields_for" and resultant controller code
On Dec 29, 2010, at 11:33 AM, Jim Burgess wrote:> Hi, > > I''m trying to understand some code in a book I''m reading and was hoping > someone could tell me if I have understood it correctly. > > There are two models, an employee model and a department model. A > department has_many :employees and an employee belongs_to :department. > > Here''s a snippet of code from the form to edit an existing employee: > > <% fields_for( @employee.department) do |department_f| %> > <p> > <%= department_f.label :name,"Department name" %><br /> > <%= department_f.text_field :name %> > </p> > <% end %> > > The form is submitted to the update action of ''employees_controller.rb'', > where there is the following code: > > if @employee.update_attributes(params[:employee]) && > @employee.department.update_attributes(params[:department]) > ... employee successfully updated ... > end > > My question is about the line > "@employee.department.update_attributes(params[:department])" > > Is it correct to say that this code updates the attributes (in this case > "name") of the Department object that is linked (via the "has_many" and > "belongs_to" relationship) to the Employee object currently being > edited?Yes. And it only does this if the update to @employee was successful first. -philip -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Jim Burgess
2010-Dec-29 20:11 UTC
Re: Help needed understanding "fields_for" and resultant controller code
Thanks for the answer Philip. It is good to get confirmation that I have understood things correctly.> Yes. And it only does this if the update to @employee was successful > first.Is the order particularly significant in this case (i.e. that it attempts to update @employee first)? Obviously it would be bad to update one record and not the other, but won''t rails throw an error and re-render the ''edit'' view if validation for either @employee or @employee.department fails? -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Philip Hallstrom
2010-Dec-29 20:30 UTC
Re: Re: Help needed understanding "fields_for" and resultant controller code
> Thanks for the answer Philip. It is good to get confirmation > that I have understood things correctly. > >> Yes. And it only does this if the update to @employee was successful >> first. > > Is the order particularly significant in this case (i.e. that it > attempts to update @employee first)?No technical reason (as this is an update, not a create), but logically it would make sense that you''d want to update them in that order.> Obviously it would be bad to update one record and not the other, but > won''t rails throw an error and re-render the ''edit'' view if validation > for either @employee or @employee.department fails?Nope. update_attributes simply returns true/false depending on whether or not it succeeded. There are ways to make it raise an error, but your code isn''t doing that. -philip -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Bente Pieck
2010-Dec-29 20:50 UTC
Re: Re: Help needed understanding "fields_for" and resultant controller code
On 29/12/10 21:11, Jim Burgess wrote:> Thanks for the answer Philip. It is good to get confirmation > that I have understood things correctly. > >> Yes. And it only does this if the update to @employee was successful >> first. > Is the order particularly significant in this case (i.e. that it > attempts to update @employee first)? > > Obviously it would be bad to update one record and not the other, but > won''t rails throw an error and re-render the ''edit'' view if validation > for either @employee or @employee.department fails? >You should use accepts_nested_attributes_for :department in your employee model. than you can just do: <% form_for @employee do |form| %> ... <% form.fields_for @employee.department do|department_fields| %> <p> <%= department_fields.label :name,"Department name" %><br /> <%= department_fields.text_field :name %> </p> <% end %> ... <% end %> and with: if @employee.update_attributes(params[:employee]) do something else render :edit end And I hope you will get, what you want to get. -- best regards Bente Pieck -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Jim Burgess
2010-Dec-29 20:57 UTC
Re: Re: Help needed understanding "fields_for" and resultant controller code
> No technical reason (as this is an update, not a create), but logically > it would make sense that you''d want to update them in that order.Cool. That was exactly the conclusion I''d drawn.>> won''t rails throw an error and re-render the ''edit'' view if validation >> for either @employee or @employee.department fails?> Nope. update_attributes simply returns true/false depending on whether > or not it succeeded. There are ways to make it raise an error, but your > code isn''t doing that.Yeah, sorry, I guess I didn''t include enough code with my original question. I''m (the book is) using the scaffold generator to create both ''employee'' and ''department'' resources. The complete update method attempts to update the attributes of @employee and @employee.department. If this doesn''t work (as validation has failed, for example) it re-renders the action ''edit''. def update @employee = Employee.find(params[:id]) respond_to do |format| if @employee.update_attributes(params[:employee]) && @employee.department.update_attributes(params[:department]) format.html { redirect_to(@employee, :notice => ''Employee was successfully updated.'') } format.xml { head :ok } else @departments = Department.find(:all) format.html { render :action => "edit" } format.xml { render :xml => @employee.errors, :status => :unprocessable_entity } end end end Thanks very much for your help. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Jim Burgess
2010-Dec-29 21:25 UTC
Re: Re: Help needed understanding "fields_for" and resultant controller code
Hi Bente, Thanks for your reply.> You should use > accepts_nested_attributes_for :department > in your employee model.The code you provided needed a minor tweak: <% form.fields_for @employee.department do|department_fields| %> was throwing an ActiveRecord::AssociationTypeMismatch - Department(#77492292) expected, got HashWithIndifferentAccess(#37082688) After a bit of googling I changed it to: <% form.fields_for :department do|department_fields| %> and everything worked fine. Thank you once again. P.S. In case it helps anyone else, this is described very well here: http://guides.rubyonrails.org/2_3_release_notes.html#nested-object-forms -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Philip Hallstrom
2010-Dec-29 23:48 UTC
Re: Re: Re: Help needed understanding "fields_for" and resultant controller code
On Dec 29, 2010, at 12:57 PM, Jim Burgess wrote:>> No technical reason (as this is an update, not a create), but logically >> it would make sense that you''d want to update them in that order. > > Cool. That was exactly the conclusion I''d drawn. > >>> won''t rails throw an error and re-render the ''edit'' view if validation >>> for either @employee or @employee.department fails? > >> Nope. update_attributes simply returns true/false depending on whether >> or not it succeeded. There are ways to make it raise an error, but your >> code isn''t doing that. > > Yeah, sorry, I guess I didn''t include enough code with my original > question. > I''m (the book is) using the scaffold generator to create both ''employee'' > and ''department'' resources. The complete update method attempts to > update the attributes of @employee and @employee.department. If this > doesn''t work (as validation has failed, for example) it re-renders the > action ''edit''. > > def update > @employee = Employee.find(params[:id]) > respond_to do |format| > if @employee.update_attributes(params[:employee]) && > @employee.department.update_attributes(params[:department]) > format.html { redirect_to(@employee, :notice => ''Employee was > successfully updated.'') } > format.xml { head :ok } > else > @departments = Department.find(:all) > format.html { render :action => "edit" } > format.xml { render :xml => @employee.errors, :status => > :unprocessable_entity } > end > end > endStill... the code above is not "throwing an error". It''s just processing an if/else flow. Look at update_attributes! to see what I''m talking about. http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_attributes%21 I only bring it up because Rails/Ruby *can* throw errors and raise exceptions (which are themselves different) so it can get confusing if you play loose with the terminology :-) -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.