I have a has_many relationship between two entities, Feeds and Posts. I also have specific types of posts, Videos and Photos. This is structured in the database using single table inheritance.
Right now I have my Feed model specifying a has_many relationship between Feeds and Posts (including the subtypes)
class Feed < ActiveRecord::Base
has_many :posts
has_many :photos
has_many :videos
Is there a better, more conventional way to specify this? Or is what I have as simple as it can get?
In Single-Table Inheritance (STI), many subclasses inherit from one superclass with all the data in the same table in the database. The superclass has a “type” column to determine which subclass an object belongs to. In a polymorphic association, one model “belongs to” several other models using a single association.
Single-table inheritance (STI) is the practice of storing multiple types of values in the same table, where each record includes a field indicating its type, and the table includes a column for every field of all the types it stores.
They essentially do the same thing, the only difference is what side of the relationship you are on. If a User has a Profile , then in the User class you'd have has_one :profile and in the Profile class you'd have belongs_to :user . To determine who "has" the other object, look at where the foreign key is.
Rails offers two different ways to declare a many-to-many relationship between models. The first way is to use has_and_belongs_to_many, which allows you to make the association directly: The second way to declare a many-to-many relationship is to use has_many :through.
If i understand you correctly you have Posts and posts can be either video or photo. as Jaryl said what you have is probably the easiest to understand/handle however if you wanted to get fancy you could use single table inheritance or polymophic associations.
STI - example (from Agile Web Development with Rails 3rd Edition)
create_table :people, :force => true do |t|
t.string :type
#common attributes
t.string :name
t.string :email
#attributes for type=Customer
t.decimal :balance, :precision => 10, :scale => 2
#attributes for type=Employee
t.integer :reports_to
t.integer :dept
#attributes for type=Manager
#none
end
class Person < ActiveRecord::Base
end
class Customer < Person
end
class Employee < Person
belongs_to :boss, :class_name => "Manager", :foreign_key => :reports_to
end
class Manager < Person
end
So if you create a customer
Customer.create(:name => 'John Doe', :email => '[email protected]', :balance => 78.29)
you can then find it via person
x = Person.find_by_name('John Doe')
x.class #=> Customer
x.email #=> [email protected]
x.balance #=> 78.29
x.some_customer_class_method # will work because the Person.find method returned a Customer object
So you could have
class Post < ActiveRecord::Base
end
class Photo < Post
end
class Video < Post
end
and then you could find them all by Post.all but you would get back Photo and Video objects (and post objects if you have posts that are not photo or video)
don't forget the string :type in your db table
This is pretty much the simplest you can do.
Well, if photos could be treated the same as videos, then perhaps you could do away with STI and use named scopes to provide accessors to different types of content.
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