Controller/View Organization (Newbie Question)


#1

Good afternoon all…

First, let me apologize for asking a potentially dumb question. I’m
new to both Ruby and Rails, but I do have a long background in OO
programming and web development.

My question is about how to structure controllers for the various
models which I will need in my application. My data will look
something like this:

Dog

  • (has_many) TrainingSessions
  • (has_many) Tests
  • (has_many) Behaviors

So, obviously, the “Dog” object is the central object on which users
will be working when they visit the application. I have a Controller
for the Dog object whose “show” view will display an overview of the
data and link to other views for adding/editing/deleting data
relating to the Dog.

My question is about the accepted or “best practice” way to lay out
these auxiliary views. I’ve thought of a few ways to do this:

  1. Make a controller for each of the auxiliary objects
    (TrainingSessionsController, TestsController, etc), each with a view
    to show information only relating to the current Dog in question. So
    for example, the overview URL “/dogs/show/1” might link to a detail
    page at “/training_sessions/list?dog_id=1” … This seems ugly to me,
    as I will need to keep passing around parameters in the URL wherever
    I go to make sure we’re still working on the right dog. For example,
    I’ll need to remember to pass ?dog_id=… to “/training_sessions/new”
    so that dog_id in the training_sessions table can be set correctly. A
    lot of extra code and work.

  2. Do the same as #1 (one Controller per table) but use a session
    variable to pass around the dog_id. This would reduce repetition but
    strikes me as less than robust. (?)

  3. Do the same as #1, but use routing to make the URLs for the
    auxiliary table methods look something like: “/dog/1/
    training_sessions/list”. As I understand it, the linking helpers
    would then maintain the dog ID at the beginning of the URL unless I
    specifically overrode it. (Though I haven’t actually TRIED this yet,
    so I could be wrong)

  4. Use only ONE controller (for Dog) and implement all auxiliary data
    operations (CRUD) as sets of views/methods on DogsController. Then,
    to get around the problem of having to have two IDs at once – one
    for the dog and one into the auxiliary table – maybe set up routing
    to allow /dogs/3/show_training_session/4 or /dogs/
    show_training_session/3/4 or something along those lines. This seems
    “clean” but I can also see this class getting way too big and
    unwieldy with all of these methods.

The biggest possibility of all is that I am missing some glorious way
Rails has for handling this sort of situation, and someone can set me
straight with a link to a web page or API doc :wink: Either way, I would
be extremely grateful for any input you might have.

Thank you!
Justin Streufert
removed_email_address@domain.invalid


#2

On Mar 17, 2006, at 9:30 AM, Justin Streufert wrote:

My question is about the accepted or “best practice” way to lay out
these auxiliary views. I’ve thought of a few ways to do this:

snip…

  1. Do the same as #1, but use routing to make the URLs for the
    auxiliary table methods look something like: “/dog/1/
    training_sessions/list”. As I understand it, the linking helpers
    would then maintain the dog ID at the beginning of the URL unless I
    specifically overrode it. (Though I haven’t actually TRIED this
    yet, so I could be wrong)

snip…

  1. Use only ONE controller (for Dog) and implement all auxiliary
    data operations (CRUD) as sets of views/methods on DogsController.
    Then, to get around the problem of having to have two IDs at once
    – one for the dog and one into the auxiliary table – maybe set up
    routing to allow /dogs/3/show_training_session/4 or /dogs/
    show_training_session/3/4 or something along those lines. This
    seems “clean” but I can also see this class getting way too big and
    unwieldy with all of these methods.

I’d use a combination of 3 and 4.

Set up routing with an additional:

map.connect ‘:controller/:action/:id/:id2’

And just split the controllers where logical, but do NOT use one per
table as the
scaffolding suggests (unless you decide that makes sense). I’m not
bagging on the
scaffolding, but it’s generated by a script, not by a decision maker.

For instance, and potentially contrived:

I could see a:

dogs_controller.rb
dog.rb

training_controller.rb
training_sessions.rb

diagnostics_controller.rb
test.rb
behavior.rb


– Tom M.


#3

Thanks very much for your answer, Tom!
I ended up doing exactly what you said, except that I used these routes:

map.connect ‘:controller/:id/:action/:sub_id’, :requirements =>
{ :id => /\d+/ }
map.connect ‘:controller/:id/:action’, :requirements => { :id => /
\d+/ }
map.connect ‘:controller/:action’

…which, due to the hierarchical nature of the URL generator (as I
just learned in Agile Web D. with Rails ;)) seems to result
in more natural linking.

Thanks again!! I’m now well on my way.
Justin