问题描述
我有两个类 Product
和 user
,它们与多态类型具有 has_many
关系.
I have two classes Product
and user
which have a has_many
relationship with a polymorphic type as such.
class User < ActiveRecord::Base
has_many :pictures, as: :imageable
end
class Product < ActiveRecord::Base
has_many :pictures, as: :imageable
end
class Picture < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
end
我还想为 profile_picture
的用户模型添加一个新属性,以便 @user.profile_picture
将返回一个图片对象.如何做到这一点?特别是向用户添加外键的迁移.
I want to also add a new property to the user models of profile_picture
so @user.profile_picture
will return a picture object. how can this be achieved? In particular the migration to add the foreign key to users.
我已经更新了用户模型
has_one :profile_picture, class_name: "Picture", foreign_key: "profile_picture_id"
并添加了以下迁移
add_column :users, :profile_picture_id, :integer
但是,如果有人可以解释我到底做错了什么,我似乎无法设置个人资料图片,我们将不胜感激.谢谢!
however i dont appear to be able to set the profile picture if someone could explain what exactly i am doing wrong it would be appreciated. thanks!
推荐答案
当正确使用关联时,没有直接方法可以实现这一点.
There is no direct way to achieve this when using associations properly.
数据结构错误.您正在尝试以两种不同的方式将同一个模型关联起来.问题是:这两种方式相互干扰.
The data structure is wrong. You are trying to associate one and the same model in two different ways. And the problem is: these two ways interfere with each other.
您正在有效地尝试使用相同类型存储不同类型的对象.直接的方法(在另一个答案中建议)会让您无法确定哪些只是 User
的图片,以及其中哪些是他的 profile_picture
.因此,任何可能的解决方案都需要添加一种方法来区分 profile_picture
.
You are effectively trying to store different types of objects using the same type. A direct way (suggested in another answer) would leave you with no way to determine which are simply User
's pictures and what is his profile_picture
among them. So any possible solution would require adding a way to distinguish a profile_picture
.
就在昨天,我写了一个关于如何使用单表继承".它实际上很适合这里,您需要两个相似的数据结构以不同的方式运行.要使其发挥作用,您需要做两件事:
Just yesterday I wrote an example on how to use "single table inheritance". It actually fits well here, you need two similar data constructs to behave in different ways. To make it work, you will need two things:
向
pictures
表添加 STI 支持:rails g 迁移 AddTypeToPictures type:string:index
...并确保您添加了一个string
类型的type
列,上面有一个索引.
Add STI support to
pictures
table:rails g migration AddTypeToPictures type:string:index
...and make sure you add atype
column of typestring
with an index on it.
rails g 模型 ProfilePicture --no-migration --parent=Picture
该类将创建为空,但会继承 Picture
的所有内容,因此在许多情况下它应该保持为空.
rails g model ProfilePicture --no-migration --parent=Picture
This class will be created empty, but will inherit everything from Picture
, so it should stay empty in many cases.
那么一个简单的关联应该适用于任何类:
Then just a simple association should work on any class:
has_one :profile_picture, as: :imageable
假设我们将其添加到 User
.那么查找用户
头像的搜索条件是:
Let's assume we added this to User
. Then the search criteria to find a User
's profile picture will be:
type
是"ProfilePicture"
imageable_type
是用户"
imageable_id
等于相关用户的id
type
is"ProfilePicture"
imageable_type
is"User"
imageable_id
is equal toid
of the user in question
搜索变得很麻烦,对吧?嗯,这应该可行,但我不推荐所有这些,它有影响和替代方案:
Searches have become cumbersome, right? Well, this should work, but I don't recommend all this, it has implications and alternatives:
- 无论您决定将哪个数据库列添加到
ProfilePicture
,即使没有使用,也必须将其添加到Picture
:它们存储在相同的表.
解决方案:使ProfilePicture
成为一个成熟的模型:为它创建一个表,使其继承ActiveRecord::Base
. - 获取用户的个人资料图片需要使用三个(哇!)不同条件的额外数据库查询.
解决方案(推荐):将个人资料图片放入相应的模型中,就像对Picture
所做的一样:这根本不需要额外的查询来获取个人资料图片.
- Whatever database column you decide to add to
ProfilePicture
, it will have to be added toPicture
even if it's not used: they are stored in the same table.
Solution: makingProfilePicture
a full-fledged model: make a table for it, make it inheritActiveRecord::Base
. - Fetching a user's profile picture will require an extra database query with three (wow!) different criteria.
Solution (recommended): placing a profile picture inside a corresponding model the same way it's done forPicture
: this will require no extra queries to fetch a profile picture at all.
这篇关于Ruby on Rails 命名模型的类属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!