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.
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
Commented above but had limited editing abilities. I came across this exact problem and found the second half of the solution elsewhere. STI will allow you to get a subset of a table based on a column in the table but it will key off of the class name to find the records for that class. For example:
class Company < ActiveRecord::Base; end
class Client < Company; end
This will look at the table named Company for records that have the value 'Client' in a column named 'Type'.
You can override the column that STI checks by doing
class Company < ActiveRecord::Base
self.inheritance_column = :company_type
end
But it still looks for that column to contain 'Client'. You can override what value it looks for by doing this:
class Client < Company
def self.sti_name
1
end
end
This will now look at the company_type column for rows with a value of 1.
For Rails-4.2 this is nearly identical but does not need a class method:
private
self.inheritance_column = :company_type
def sti_name
1
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With