ROR Newb question - multiple models, one form / populating drop-downs from tables

Good Afternoon.

I am creating a time tracking application as learning exercise. Each Project has_many Worktracks, each Worktrack has_many tasks, each Proect has_many tasks through Worktracks.

Everything is great - model works, views work, controller functions.

Problem is, how can I have a single view incorporating Projects, Worktracks and Tasks, allowing for creating Worktracks within Projects (for example) - in one view.

I can do this in irb using '<<', but trying to translate this into Rails is proving problematic. Searching this forum, I found a Pragmatic book chapter, but the solution was complex and blew up my app - undoubtedly, I erred somewhere trying to implement it, but I cannot determine where, and at this point, my learning curve is flatlined.

Any suggestions for general approach would be welcomed - my ideal solution would be to be able to mix @project, @worktrack and @task all in the same structure.

As a side-issue, but related, I have a valid_values table that I am trying to use to populate drop-down menus within tasks, etc - but again, I can only populate via direct coding in the view, rather than passing in an array from database query. I know it can be done, but the 'how' is defeating me. I suspect the solution is simple, but non- obvious to me.

Many thanks in advance for suggestions, and I will accept flames in good cheer if accompanied by workable suggestions.

There are many approaches to this problem. Some involve setting up the code in the controller, others use a "presenter." Google presenter pattern for more info on that. The "build" method might be what you are looking for. This is created as you define your model relationships. If you use it, it sets the foreign key id properly.

#controller def new   @project =   @worktrack = end

def create   @product =[:product])   @worktrack =[:worktrack])

  if @project.valid? & @worktrack.valid?     Project.transaction do!!     end   else     render 'new'   end end

If you name the attributes properly in the view, this sort of scheme will work. The problem with it is that the controller will become bloated quickly as you add more complexity. For example if you add your tasks piece, it will require another instance variable, validation, save, etc. This is where a presenter model can help clean up the controller.

As for your second question. You are likely looking for a "collection_select" helper.

You could do something like this...

collection_select(:post, :author_id, Author.all, :id, :name_with_initial, {:prompt => true})

collection_select(:post(..this is the object), :author_id(...this is the method), Author.all(...this is the collection), :id(...this is the value), :name_with_initial(...this is the text displayed), {:prompt => true}(...this is an option))


Many Thanks, Andrew.

The drop down is actually simpler than you indicated - it is all string text that was validated on input. All I need to do is "select * from valid_values where dropdown_to_be_populated = 'status' " and populate the returned array of strings into the dropdown.

My confusion - where would I put the code to pull this information to make it available to the 'Tasks' view - and in that view, how can I tell the view to look at a table that is not 'Tasks', or if I pull the array in a controller (Tasks controller?) how to pass that to the view?

I realize this should be easy, as the PragProg book (Agile Web Dev) has sections on multiple-table applications, but their examples never mix two tables' data on one view except when defining a cart - and then, there is nothing directly on point.

Thanks again -


You can have a class method of ValidValues model (if that is what it is called) named something like strings_for_selection which returns the data for the dropdown box. Then in the view simply call ValidValues.strings_for_selection. This keeps all the knowledge of which strings are valid in the model.

Alternatively call the method in the controller so @strings_for_selection = ValidValues.strings_for_selection and then use this in the view. Not so good in my opinion as why should the controller be bothered with this?


I agree with Colin above. Make a model level method to return the data you wish to use in the view. Then within the view call ValidValues.method_you_make.

Like he said, another option is to put this code in the controller, but most of the time, the dropdown select menus have little to do with the rest of the controller function. So placing it in the controller (just to ensure proper MVC architecture) works but in my opinion gets to be a bit of overkill.