Search code examples
ruby-on-rails-3ruby-on-rails-3.1rails-models

How do I Create a Rails Model from a Subset of Table Records


I am trying to create several models that all pull from the same table. How do I limit the table records in each model? And before you tell me to change my data structure, this is a reporting application that is pulling from a preexisting backing DB over which I have no control.

My table looks something like:

Vehicle_Table
id vehicle_type name
--------------------
1  Car          Foo
2  Car          Bar
3  Motorcycle   Baz
4  Car          Barf

And I want to build models for Car and Motorcycle like:

class Car < ActiveRecord::Base
  set_table_name 'Vehicle_Table'

end

and

class Motorcycle < ActiveRecord::Base
  set_table_name 'Vehicle_Table'

end

But I have no idea how to say, "Hey Active Record, I only want records where vehicle_type = motorcycle in the motorcycle model."

I'm sure this is friggin' obvious, but all of my Google searches return ways to FIND subsets in a model rather than RESTRICT a model to a specific subset of records.


Solution

  • This is called Single Table Inheritance (STI).

    If you had a column named type in your table, it would likely work automatically. But you can change this column name that Rails uses to tell types apart.

    http://api.rubyonrails.org/classes/ActiveRecord/Base.html

    Single table inheritance

    Active Record allows inheritance by storing the name of the class in a column that by default is named “type” (can be changed by overwriting Base.inheritance_column). This means that an inheritance looking like this:

    class Company < ActiveRecord::Base; end
    class Firm < Company; end
    class Client < Company; end
    class PriorityClient < Client; end
    

    When you do Firm.create(:name => "37signals"), this record will be saved in the companies table with type = “Firm”. You can then fetch this row again using Company.where(:name => '37signals').first and it will return a Firm object.

    So, try this code

    class Car < ActiveRecord::Base
      set_table_name 'Vehicle_Table'
      self.inheritance_column = :vehicle_type
    end