我有一个ActiveRecord模型Media
,它应该能够存储有关不同类型媒体(Media::Book
,Media::Movie
,Media::Music
)的类似结构化信息。但是,每个子类都有独特的方法。
# TABLE medias
# string :title
# string :description
# integer :media_type
class Media < ActiveRecord::Base
end
class Media
class Book < Media
def reviews
GoogleBooks.search(name).get_reviews
end
end
class Movie < Media
def reviews
IMDB.search_movies(name).reviews
end
end
class Music < Media
def reviews
Lastfm.search(name).comments
end
def music_video
Youtube.search(name).first.embed_html
end
end
end
如果我使用Media::Book.new("Harry Potter").reviews
,这会有效,但我希望能够使用
Media.find("Harry Potter")
=> Media::Book
和
Media.find("Harry Potter").reviews
我知道我应该使用media_type
来实现这一点,但我不确定是否有更好的方法来覆盖每个ActiveRecord数据库接口方法(User.medias
,{{1} },find
,find_by_etc
,where
,order
,limit
)并替换每个返回值。
答案 0 :(得分:7)
您可以使用ActiveRecords单表继承功能。 它使用模型表上的另一列(默认为名为“type”的列)来确定每条记录的模型类型。
只需将一个字符串类型列添加到medias表中,当Rails在数据库模式中找到该列时,它将为您提供魔力。
如果您将AR添加到media_type
列中,那么您也可以使用set_inheritance_column
类方法更改用于单表继承的列。
class Media < ActiveRecord::Base
set_inheritance_column :media_type
end
然后,您将在此列中找到具有完整命名空间类名的相应对象的类名。 (例如:“Media :: Book”)也就是说,您不想手动更改类型列(或您使用的任何列)的内容。 ActiveRecord会自行处理它。
查看http://api.rubyonrails.org/classes/ActiveRecord/Base.html并在该页面中搜索“单表继承”以获取更多信息
编辑: 刚刚意识到你的media_type列是一个整数。因此将它用于STI是行不通的。只需坚持使用字符串类型列,让AR为您完成剩下的工作。