Inheritance and routing of single tables in Ruby on Rails 3.0

I'm having trouble routing to play beautifully with Single Table Inheritance in my Ruby on Rails application. I am using Ruby 1.9.2 and Rails 3.0.6. This is under development, so the back-end is SQLite3, in case that matters.

Let's say I have two products: widgets and sprockets . My application tracks error numbers and supports tickets for both products, but the errors themselves and support tickets are stored on other systems. There are two separate teams that work on these two products.

I implemented one-page inheritance for two types of error records, because the rules for checking error numbers in widgets and the number of star errors are different (the two teams use different error tracking systems), and there is a chance that I will have to add additional products that behave to the application differently. Using STI gives me the flexibility to implement additional methods and properties as needed.

The widget team only cares about widget information, and the star team only cares about chain information. There is a third team, which should be able to view information about both widgets and chains. The widget team will access the application using the /widgets path, and the asterisk team will access the application using the /sprockets . I installed this in routes.rb using namespaces:

 resources :bugs namespace "widgets" do resources :bugs end namespace "sprockets" do resources :bugs end 

I installed the following models that work as expected when I run irb and use WidgetBug.create() or SprocketBug.create() :

bug.rb

 class Bug < ActiveRecord::Base end 

widget_bug.rb

 class WidgetBug < Bug # Some validation rules end 

sprocket_bug.rb

 class SprocketBug < Bug # Some different validation rules end 

I used scaffolding to create a controller and view for the error object, and then modified the controller to try to generalize it so that it can be used with both widget errors and asterisk errors. For example, the index method looks like this:

  def index # The scaffold code lists all bugs, which is not what we want # @bugs = Bug.all # Only return bugs of the subclass we're looking for @bugs = eval("#{params[:controller].classify}.all") respond_to do |format| format.html # index.html.erb format.xml { render :xml => @bugs } end end 

Then I used create() to populate the database with several errors of each type. Unfortunately, when I browse /widgets/bugs , errors appear for both products. After some debugging, I decided that calling classify returns Widgets::Bugs or Sprockets::Bugs , so when I call everything on it, it seems to work against the superclass, rather than working with the subclass.

I looked at the routing documentation and did quite a lot of searches on Google, but I still don't understand how I can change the routing or controller to make this work correctly. Any help would be greatly appreciated.

+4
source share
2 answers

Checkout: STI, one controller

Routes

 resources :widgets, :controller => "bugs", :type => "Widget" resources :sprockets, :controller => "bugs", :type => "Sprocket" # And I don't know if you need this resources :bugs, :type => "Bug" 

controller

 def index @bugs = params[:type].constantize.all end 

UPD

 namespace "widgets" do resources :bugs, :type => "Widget" end namespace "sprockets" do resources :bugs, :type => "Sprocket" end 
+4
source

I wrote a blog post about STI in Rails 3, which discusses some common mistakes and working correctly around, including the issue you mention. http://www.christopherbloom.com/2012/02/01/notes-on-sti-in-rails-3-0/

-1
source

All Articles