一种类型的所有多态模型?

时间:2015-09-04 20:50:19

标签: ruby-on-rails rails-activerecord

所以,我有以下模型:

class Favorite < ActiveRecord::Base
  belongs_to :user
  belongs_to :favoritable, polymorphic: true
  # Table has a favoritable_id and favoritable_type
end

class Book < ActiveRecord::Base
  has_many :favorites, as: :favoritable
end

class Magazine < ActiveBoard::Base
  has_many :favorites, as: :favoritable
end

class User < ActiveRecord::Base
   has_many :favorites
end

当我打电话时:

user = User.find(1)
user.favorites

它按预期收回所有收藏的书籍和杂志(基本上它在数据库中的含有favoritable_id和favoritable_type列/属性的内容)。当我这样称呼时:

user = User.find(1)
user.favorites.books

我收到错误消息:

NoMethodError: undefined method 'books' ...

但是,请致电:

user = User.find(1)
user.favorites.first.favoritable

这很好用。

我不知道怎样才能在这种设置中获得所有喜欢的书籍模型?我做错了吗?

再次感谢。

2 个答案:

答案 0 :(得分:4)

这样做:

user.favorites.map {|f| f.favoritable}

或者,为了获得最喜欢的书籍,请执行以下操作:

user.favorites.select { |f| f.favoritable_type == 'book' }.map { |f| f.favoritable }

答案 1 :(得分:1)

您可以使用以下代码轻松定义UserBook以及Magazine之间的关系:

class User < ActiveRecord::Base
  has_many :favorites
  has_many :favorite_books, through: :favorites, source: :favoritable, source_type: 'Book'
  has_many :favorite_magazines, through: :favorites, source: :favoritable, source_type: 'Magazine'
end

现在您可以轻松查询用户的书籍和杂志:

 user.favorite_books
 user.favorite_magazines

Books查询生成以下SQL:

SELECT "books".* FROM "books"
INNER JOIN "favorites" ON "books"."id" = "favorites"."favoritable_id"
WHERE "favorites"."user_id" = ? AND
      "favorites"."favoritable_type" = ?
      [["user_id", 1], ["favoritable_type", "Book"]]

如您所见,选择Book的所有工作都在数据库中完成。哪个更有效率,然后将完整的收藏夹列表发送给客户端并在那里过滤它。

这种方法的另一个优点是它可以很好地扩展。例如,如果您想知道哪些Jules Verne的书籍受到特定用户的青睐,那么查询非常自然:

user.favorite_books.where('books.author = ?', 'Jules Verne')