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.