I apologize in advance for my ignorance, but I''m stuck with a problem 
and after a couple of hours of looking for answers in the documentation 
and help, I''m still stuck so I was wondering if someone might have the 
answer.
I have tables Projects and Stages, each with an habtm relationship to 
each other, and a projects_stages table which contains projects_id, 
stages_id and a date field. (A project can have any number of stages, 
and completed stages are recorded in project_stages.)
On ../projects/edit  I display the completed steps for the project (all 
records in projects_stages which have project_id for the selected 
project). So far so good.
Now I want a drop-down field to select the next step and write a new 
record to the projects_stages field. So I put the following:
<%= collection_select(:project, :stages, Stage.find_all, :id, 
:description, {:include_blank => true}) %>
The select box populates correctly, but when saving I get an error that 
Stage expected but received String. The error page shows that the 
stage_id is being passed back to the controller, but in this instance 
what I need is to add a row to the project_stages table containing both 
the project_id and the stages_id. Does Rails ''magically'' do
this (like
it does with a has_many relationship) and I''m just using 
collection_select incorrectly, or is there some other way I''m supposed 
to do this?  I''m not sure what is the proper approach in this case.
Thanks.
-- 
Posted via http://www.ruby-forum.com/.
zero halo wrote:> <%= collection_select(:project, :stages, Stage.find_all, :id, > :description, {:include_blank => true}) %> > > The select box populates correctly, but when saving I get an error that > Stage expected but received String. The error page shows that theIf I understand you correctly, the user is selecting the step that they''ve just completed, to be added to the project.stages completed list. In this case I''d recommend you create an attr_accessor in your project model called newly_completed_stage_id, then use <%= collection_select(:project, :newly_completed_stage_id, Stage.find_all - @project.stages, :id, :description, {:include_blank => true}) %> and have a before_save method in Projects to add any new stage: stages.push_with_attributes( Stage.find(newly_completed_stage_id.to_i), :date_completed => Date.today ) unless newly_completed_stage_id.blank? -- We develop, watch us RoR, in numbers too big to ignore.
mrj wrote:> In this case I''d recommend you create an attr_accessor in your > project model called newly_completed_stage_id, then use > > <%= collection_select(:project, :newly_completed_stage_id, > Stage.find_all - @project.stages, :id, :description, {:include_blank => > true}) %> > > and have a before_save method in Projects to add any new stage: > > stages.push_with_attributes( > Stage.find(newly_completed_stage_id.to_i), :date_completed => Date.today > ) unless newly_completed_stage_id.blank? >Awesome, thanks! I must say, I have a hard time wrapping my head around some of the Rails behind-the-scenes magic, such as understanding exactly how push_with_attributes knows to add a new record to my project_stages join table, but hey, it works! I should have gotten it from reading the Agile book, but my brain''s a bit foggy these days. This might be helpful to post on the Rails wiki. I''ll attempt a write-up though I''m not sure I can explain it all like it should. I also liked the ''Stage.find_all - @project.stages'' little bit of code. I didn''t realize you could subtract one collection from another like that. Very cool. -- Posted via http://www.ruby-forum.com/.
zero halo wrote:> mrj wrote: >> stages.push_with_attributes( >>Stage.find(newly_completed_stage_id.to_i), :date_completed => Date.today >>) unless newly_completed_stage_id.blank? > > Awesome, thanks! I must say, I have a hard time wrapping my head around > some of the Rails behind-the-scenes magic, such as understanding exactly > how push_with_attributes knows to add a new record to my project_stages > join table, but hey, it works! I should have gotten it from reading the > Agile book, but my brain''s a bit foggy these days. This might be helpful > to post on the Rails wiki. I''ll attempt a write-up though I''m not sure I > can explain it all like it should.The job of push_with_attributes is to add an object to the list of objects in a HABTM association. To do this it must add a record to the join table, geting the project_id from the Project object on which stages is called, the stage_id from the first parameter Stage object, and the attributes associated with the join from the second parameter. The stage object itself is not saved because it is not a new record.> I also liked the ''Stage.find_all - @project.stages'' little bit of code. > I didn''t realize you could subtract one collection from another like > that. Very cool.That works because Rails cleverly uses an AR object''s id attribute for equality comparison. One other thing: find_all is depricated, use find(:all) instead. -- We develop, watch us RoR, in numbers too big to ignore.