I want to have popup menus and check boxes in my forms to let users select associated objects. In the form I''m working on, the object "belongs_to" another type of object which is selected from a popup menu. The id of the chosen object(s) for association is passed back in the parameter hash, but when rails creates a new object from this parameter hash, I get a AssociationTypeMismatch. This error seems to be complaining that rails expected an actual association object but it instead got a string with the object''s id. I''m not sure why rails would be expecting the actual associated object to be in the param hash arriving from the form, but I''m still relatively new and am probably doing something wrong. Is there a way to instruct rails to expect an id in the param hash of a form rather than the actual associated object? I think I could make this work by overriding the ActiveRecord::Base update_attributes or attributes= methods, but I''m betting this problem has been worked out already since this is such a generic issue. -- Posted via http://www.ruby-forum.com/.
Additional Info: I have a class owner which has_many :item, and a class item which belongs_to :owner On the form, I have <%= select ''item'', ''owner'', Owner.find(:all).map{|c| [c.name,c.id]} %> -- Posted via http://www.ruby-forum.com/.
OK, I''ve stumbled upon a solution to the belongs_to case mentioned above. The answer: use owner_id instead of owner in the form. I still can''t seem to find the canonical rails way of processing has_and_belongs_to_many associations as represented by a group of check boxes yet. Is there a "built in" way to do this easily in rails? -- Posted via http://www.ruby-forum.com/.
For HABTM, something like the following should work: <!-- View --> <%= check_box_tag "relationships", "some_id", "checked_or_not" %> <%= check_box_tag "relationships", "some_other_id", "checked_or_not" %> <%= check_box_tag "relationships", "some_other_other_id", "checked_or_not" %> <!-- controller --> def update ... @my_object.habtm_relationship_ids = params[:relationships] ... end That should do it. You''ll need to come up with some logic to check/uncheck boxes when the form loads up. How this works is that the multiple checkboxs all named the same passes an array of id''s for your other relationship. Then setting the ids field on the object does all the associating for the relationships. Probably a bit confusing, but I hope this helps. -Nick
Thanks for responding. Using the relationship_ids=array avenue, I''m trying to make this more DRY by adding it into ActiveRecord::Base so associations will be handled automatically like other attributes during calls to "new" or "update_attributes". The lines starting with * are the lines I''ve added. It works great on updates of existing records, but for reasons still unclear to me it captures some but not all check boxes when creating a new object. Am I barking up the wrong tree here? class ActiveRecord::Base def attributes=(attributes) return if attributes.nil? * self.class.reflect_on_all_associations.each do |a| * if(attributes[a.name]) * self.send(Inflector.singularize(a.name.to_s)+"_ids=",attributes[a.name.to_s].map {|x| x.to_i}) * attributes.delete(a.name.to_s) * end * end attributes.stringify_keys! multi_parameter_attributes = [] remove_attributes_protected_from_mass_assignment(attributes).each do |k, v| k.include?("(") ? multi_parameter_attributes << [ k, v ] : send(k + "=", v) end assign_multiparameter_attributes(multi_parameter_attributes) end end -- Posted via http://www.ruby-forum.com/.
What other ''automatic'' feautres are looking for? Setting the array ids will take care of everything for you. (ie deleting records that are no long associated and the like). You shouldn''t need to do anything else. Setup some test cases and take a look for yourself. -Nick On 4/2/06, RailsNewbie <jsorenson@bellsouth.net> wrote:> Thanks for responding. Using the relationship_ids=array avenue, I''m > trying to make this more DRY by adding it into ActiveRecord::Base so > associations will be handled automatically like other attributes during > calls to "new" or "update_attributes". The lines starting with * are > the lines I''ve added. It works great on updates of existing records, > but for reasons still unclear to me it captures some but not all check > boxes when creating a new object. Am I barking up the wrong tree here? > > class ActiveRecord::Base > > def attributes=(attributes) > return if attributes.nil? > > * self.class.reflect_on_all_associations.each do |a| > * if(attributes[a.name]) > * > self.send(Inflector.singularize(a.name.to_s)+"_ids=",attributes[a.name.to_s].map > {|x| x.to_i}) > * attributes.delete(a.name.to_s) > * end > * end > > attributes.stringify_keys! > multi_parameter_attributes = [] > remove_attributes_protected_from_mass_assignment(attributes).each > do |k, v| > k.include?("(") ? multi_parameter_attributes << [ k, v ] : > send(k + "=", v) > end > assign_multiparameter_attributes(multi_parameter_attributes) > end > > end > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
RailsNewbie
2006-Apr-02 18:16 UTC
[Rails] Re: Re: Re: Any way around AssociationTypeMismatch?
Automatic in the sense that you can just say @newobj=TheClass.new(param[:theclass]) or @obj.update_attributes(param[:theclass]) without having to explicitly hand code for all the associations that the object has. So, in short: @obj.update_attributes(param[:theclass]) instead of @obj.update_attributes(param[:theclass]) @obj.attribute1_ids=param[:theclass][attribute1] @obj.attribute2_ids=param[:theclass][attribute2] @obj.attribute3_ids=param[:theclass][attribute3] @obj.attribute4_ids=param[:theclass][attribute4] @obj.attribute5_ids=param[:theclass][attribute5] etc.. Just like the "new" or "update_attributes" function allows us to avoid typing things such as: @obj.name=param[:theclass][:name] @obj.address=param[:theclass][:address] @obj.phone=param[:theclass][:phone] etc... -- Posted via http://www.ruby-forum.com/.
That lets me be up and running with existing scaffolding code (rails, ajax_scaffold) without having to hand tweak each individual controller new/update function to handle associations. I will just have to add the check boxes and popup to the views code to handle associations. Ideally, the scaffolding code would do that for me too so I can be even more lazy than I already am. -- Posted via http://www.ruby-forum.com/.