On Wed, Feb 15, 2012 at 10:13 AM, Bodo Kist <[email protected]> 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 [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en.

Reply via email to