所以,我有以下模型:
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
这很好用。
我不知道怎样才能在这种设置中获得所有喜欢的书籍模型?我做错了吗?
再次感谢。
答案 0 :(得分:4)
这样做:
user.favorites.map {|f| f.favoritable}
或者,为了获得最喜欢的书籍,请执行以下操作:
user.favorites.select { |f| f.favoritable_type == 'book' }.map { |f| f.favoritable }
答案 1 :(得分:1)
您可以使用以下代码轻松定义User
和Book
以及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')