Hello, I''m trying to solve a common task with many to many relationships. Here are my class definitions: class User < ActiveRecord::Base has_many :questionnaires has_many :forms, :through => :questionnaires end class Form < ActiveRecord::Base has_many :questionnaires has_many :users, :through => :questionnaires end class Questionnaire < ActiveRecord::Base belongs_to :user belongs_to :form end My problem is to include an extra date field named active_at to User new/edit form. When creating a user I need to check forms (via checkboxes) which it belongs to. I know it can be done by creating checkboxes with name like ''user[form_ids][]''. But I also need to enter a date field for each of checked relations which will be stored in the questionnaire join model. Any help is very appreciated Bodo -- 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.
On Wed, Feb 15, 2012 at 10:13 AM, Bodo Kist <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Hello, > > I''m trying to solve a common task with many to many relationships. > > Here are my class definitions: > > class User < ActiveRecord::Base > has_many :questionnaires > has_many :forms, :through => :questionnaires > end > > class Form < ActiveRecord::Base > has_many :questionnaires > has_many :users, :through => :questionnaires > end > > class Questionnaire < ActiveRecord::Base > belongs_to :user > belongs_to :form > end > > My problem is to include an extra date field named active_at to User > new/edit form. > > When creating a user I need to check forms (via checkboxes) which it > belongs to. I know it can be done by creating checkboxes with name like > ''user[form_ids][]''. But I also need to enter a date field for each of > checked relations which will be stored in the questionnaire join model. > > Any help is very appreciated >We recently had a long (and confusing) discussion about this https://groups.google.com/forum/#!topic/rubyonrails-talk/W-FTZNPNUeE/discussion Looking back at it, I would suggest take it step-by-step. Try first to understand how to get it to work on the model level, write unit tests for that and only after that, build your new/edit view code that will generate the params hash that will fill in the values. There is a good chance you will need to do some "manual" tweaking to completely build up the datastructure from the params hash. I mean a simple user = create(params[:user]) may require you defining some additional setter methods. Maybe, the core is that you will need to override the form_ids=(id,id,...) method on the User model (start with rails c> User.new.methods.grep(/form_ids=/)to see if it is defined. Assuming you use Rails 3.2.x you could start playing with (UNTESTED code, probably not optimal, just a hint): class Questionnaire < ActiveRecord::Base belongs_to :user, :inverse_of => :users belongs_to :form, :inverse_of => :forms # important for the save after build ! # google this line: "The last line ought to save the through record (a Taggable). This will only work if the :inverse_of is set:" end class User < ActiveRecord::Base has_many :questionnaires has_many :forms, :through => :questionnaires def form_ids=(form_id_array) super # will pass the argument to higher-up function and build the associated forms self.forms.each do |form| # I presume this will be populated by now qs = form.questionnaires qs = qs.select{|q| q.user == self} # filter only those that are this user raise "BOOOM" if qs.size > 1 # there can be only 1 (check it to be sure) q = qs.first q.active_at Time.now end end end Then check the result manually and with tests. Then save the user and check if all is still correct. Once you can set the active_at to Time.now, a next phase can start to set it to actual values, that are gotten from the form (probably need to make a non-standard input format that may be an array of hashes with in each entry the form_id and the date for that form_id ??). I hope this helps, but I keep finding this non-trivial ... If I overlook the obvious, standard solution, I would be glad to be corrected. Peter -- 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.
Thanks. I forgot to mention that one solution is discussed on http://stackoverflow.com/questions/9174513/rails-has-many-through-form-with-checkboxes-and-extra-field-in-the-join-model/9191867#9191867 When I try this approach I got an error message from inside the original routine below: Couldn''t find Questionnaire without an ID (In my case Product is User, Category is Form and Categorization is Questionnaire.) def initialized_categorizations # this is the key method [].tap do |o| Category.all.each do |category| if c = categorizations.find { |c| c.category_id == category.id } o << c.tap { |c| c.enable ||= true } else o << Categorization.new(category: category) end end end end ... My question is what the error line tries to do in detail. Anyway, I''m surprised that for this common problem there is still no reasonable solution available. Regards Bodo -- 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.
On Wed, Feb 15, 2012 at 11:55 AM, Bodo Kist <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Thanks. > > I forgot to mention that one solution is discussed on > > > http://stackoverflow.com/questions/9174513/rails-has-many-through-form-with-checkboxes-and-extra-field-in-the-join-model/9191867#9191867 > > When I try this approach I got an error message from inside the original > routine below: > > Couldn''t find Questionnaire without an ID > > (In my case Product is User, Category is Form and Categorization is > Questionnaire.) > > def initialized_categorizations # this is the key method > [].tap do |o| > Category.all.each do |category| > if c = categorizations.find { |c| c.category_id == category.id } > o << c.tap { |c| c.enable ||= true } > else > o << Categorization.new(category: category) > end > end > end > end > ... > > My question is what the error line tries to do in detail. >In that case, could you then send your particular implementation and the stack trace that you got. A wild guess is that there is a problem where looking for an ID (that is only generated when saving to the database; but at this time your questionaire object is still in the making in memory and does not have an id yet). That is why I used the "select" code in my proposal (checks in the array in memory using the belongs_to result == self) and not find (which would look for an entry in db, but we have not saved yet at that point). HTH, Peter -- 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.