4

我有一个 ActiveRecord 模型Media,它应该能够存储有关不同类型媒体(、、、)的类似结构Media::BookMedia::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, find, find_by_etc, where, order, limit, all)并替换它们的每个返回值更好的方法。

4

1 回答 1

8

您可以为此使用 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 为您完成其余的工作。

于 2011-07-06T15:43:33.497 回答