Daniel May
Daniel May

Reputation: 2262

Treating Rails model subclass at superclass level: simplified routing and single controller

I've currently got:

class Tutorial
  has_many :comments
end

class VideoTutorial < Tutorial
end

class Comments
  belongs_to :tutorial
end

routes.rb reads like:

resources :tutorials do
  resources :comments
end

I'd like to be able to refer to specific types of Tutorial (starting with VideoTutorial) like this:

/tutorials/1234
/tutorials/1234/comments/new
/tutorials/1234/comments/6374

Which means dealing with tutorials as Tutorial as much as possible, rather than VideoTutorial (or other subclasses as they come along).

I would like to have all calls going to a single controller and using straightforward routing as above.

PROBLEM: what is happening now

My forms seem to be matching routes polymorphically, matching the type of a specific Tutorial instance, e.g.

# @tutorial is a VideoTutorial
= form_for @tutorial do |f|  # undefined method 'video_tutorial_path'
...

Which is pretty cool but not what I'm looking for in this situation :)

I am currently making things work by generating those routes:

resources :tutorials do
  resources :comments
end

resources :video_tutorials, :controller => "tutorials" do
  resources :comments
end

I'm directing to the Tutorials controller as I'd like to avoid lots of controllers multiplying, when new Tutorial subclasses arise.

But this gets messy:

I'd like to treat all types of Tutorial as Tutorial in the above scenario.

What's a simpler, less messy approach?

UPDATE: as per @jdl's suggestion

Link to Tutorial show page:

  # original approach:
  = link_to 'Show', @tutorial

  # now:
  = link_to 'Show', tutorial_path(@tutorial)

form_for helper:

  # original approach:
  = form_for @tutorial do |f|

  # now:
  = form_for @tutorial, :as => :tutorial, :url => tutorial_path do |f|

form_for nested resources:

  # original approach:
  = form_for [@tutorial, @new_comment] do |f|

  # now:
  = form_for [@tutorial, @new_comment], :as => :tutorial, :url => tutorial_comments_path(@tutorial, @new_comment) do |f|

This works as intended now.

A bit more wordy :) Any further thoughts as to making it more elegant?

Upvotes: 1

Views: 991

Answers (1)

jdl
jdl

Reputation: 17790

Take a look at the :as parameter of form_for.

http://apidock.com/rails/ActionView/Helpers/FormHelper/form_for

Upvotes: 2

Related Questions