我们正在尝试添加多个可接受的对象,用户可以在其中收藏许多不同的对象,但不确定如何使其工作。
以下是收藏夹型号:
class Favorite < ActiveRecord::Base
# belongs_to :imageable, polymorphic: true
belongs_to :user
belongs_to :category
belongs_to :business
belongs_to :ad_channel
belongs_to :location
belongs_to :offer
end
用户模型:
class User < ActiveRecord::Base
has_many :favorites, as: :favoritable
end
可以收藏的一些示例模型:
class Category < ActiveRecord::Base
has_many :sub_categories
has_many :ad_channels
has_many :offers
belongs_to :favoritable, polymorphic: true
end
我不确定这是否设置正确,这是我们首先需要一些反馈。
其次,我们如何为用户“喜欢”某些东西?
这是我们迄今为止尝试过的失败:
@user.favorites << Category.find(1)
编辑:这还需要一个收藏数据库表来记录事物吗?这对我们来说是一个非常新的概念。
答案 0 :(得分:15)
您的Favorite
模型如下所示:
class Favorite < ActiveRecord::Base
belongs_to :favoritable, polymorphic: true
belongs_to :user, inverse_of: :favorites
end
然后,您的User
模型将如下所示:
class User < ActiveRecord::Base
has_many :favorites, inverse_of: :user
end
然后,可以收藏的模型应如下所示:
class Category < ActiveRecord::Base
has_many :favorites, as: :favoritable
end
是的,您的数据库中需要一个favorites
表。
所以,这应该允许你做这样的事情:
@user.favorites << Favorite.new(favoritabe: Category.find(1)) # add favorite for user
请注意,您需要将Favorite
的实例添加到@user.favorites
,而不是favoritable
模型的实例。 favoritable
模型是Favorite
。
但是,实际上,在Rails中执行此操作的首选方法是:
@user.favorites.build(favoritable: Category.find(1))
如果您只想查找某种类型的收藏,可以执行以下操作:
@user.favorites.where(favoritable_type: 'Category') # get favorited categories for user
Favorite.where(favoritable_type: 'Category') # get all favorited categories
如果您经常这样做,我认为将范围添加到多态模型非常简洁:
class Favorite < ActiveRecord::Base
scope :categories, -> { where(favoritable_type: 'Category') }
end
这允许你这样做:
@user.favorites.categories
从中可以获得与@user.favorites.where(favoritable_type: 'Category')
相同的结果。
我猜你可能也想让用户只能一次收藏一个项目,这样当你做@user.favorites.categories
之类的事情时,你就不会得到重复的类别。以下是您在Favorite
模型上设置的方法:
class Favorite < ActiveRecord::Base
belongs_to :favoritable, polymorphic: true
belongs_to :user, inverse_of: :favorites
validates :user_id, uniqueness: {
scope: [:favoritable_id, :favoritable_type],
message: 'can only favorite an item once'
}
end
这使得收藏夹必须具有user_id
,favoritable_id
和favoritable_type
的唯一组合。由于favoritable_id
和favoritable_type
被合并以获得优惠项,因此这相当于指定所有收藏夹必须具有user_id
和favoritable
的唯一组合。或者,用简单的英语,“用户只能喜欢一次”。
出于性能原因,当您具有多态关系时,您需要_id
和_type
列上的数据库索引。如果您使用带有多态选项的Rails生成器,我认为它会为您执行此操作。否则,你必须自己做。
如果您不确定,请查看您的db/schema.rb
文件。如果您在favorites
表的架构之后有以下内容,那么您已全部设置:
add_index :favorites, :favoritable_id
add_index :favorites, :favoritable_type
否则,将这些行放入迁移并运行那个坏孩子。
当你遇到它时,你应该确保所有外键都有索引。在此示例中,这将是user_id
表上的favorites
列。同样,如果您不确定,请检查您的架构文件。
关于数据库索引的最后一件事:如果 要添加上面一节中概述的唯一性约束,则应该为数据库添加唯一索引。你会这样做:
add_index :favorites, [:favoritable_id, :favoritable_type], unique: true
这将强制执行数据库级别的唯一性约束,如果您有多个应用服务器都使用单个数据库,这通常只是正确的处理方式。