[英]How can i make rails models belongs_to using multiple foreign key
recently I have a migration that adds a user_id
column to the watch_events tables.最近我有一个迁移,将
user_id
列添加到 watch_events 表中。 and thus I want to change the watch_event models to handle belongs_to but with multiple approach因此我想改变 watch_event 模型来处理 belongs_to 但有多种方法
create_table 'users', force: :cascade do |t|
t.integer 'id'
t.integer 'customer_id'
end
create_table 'watch_events', force: :cascade do |t|
t.integer 'customer_id'
t.integer 'user_id'
end
previously之前
class WatchEvent < ApplicationRecord
belongs_to :user, foreign_key: :customer_id, primary_key: :customer_id
end
what I want:我想要的是:
watch_event.customer_id
is present, i want to use belongs_to:user, foreign_key: :customer_id, primary_key: :customer_id
watch_event.customer_id
存在,我想使用belongs_to:user, foreign_key: :customer_id, primary_key: :customer_id
watch_event.customer_id
is not present, i want to use normal belongs_to:user
watch_event.customer_id
不存在,我想使用普通的belongs_to:user
how can I achieve this on the watch_event model?如何在 watch_event model 上实现这一点?
If I understand your question correctly, then what you are looking for is a Polymorphic association .如果我正确理解您的问题,那么您正在寻找的是一个多态关联。
If you see the code below, what it basically does is create two columns in the watch_events
table, watcher_type
and watcher_id
.如果您看到下面的代码,它的基本作用是在
watch_events
表中创建两列watcher_type
和watcher_id
。 And the belongs_to:watcher
then uses the watcher_type
column to identify which model it should associate to,然后,
belongs_to:watcher
使用watcher_type
列来识别它应该关联到哪个 model,
create_table 'watch_events', force: :cascade do |t|
t.references 'watcher', polymorphic: true, null: false
end
class WatchEvent < ApplicationRecord
belongs_to :watcher, polymorphic: true
end
I do not think that Rails supports 'fallback foreign keys' on associations.我不认为 Rails 支持关联的“后备外键”。 However, you can write a simple wrapper for your problem.
但是,您可以为您的问题编写一个简单的包装器。 First, relate your
WatchEvent
class twice to the user model, using your two keys and two 'internal' association names ( :user_1
and :user_2
).首先,使用您的两个键和两个“内部”关联名称(
:user_1
和:user_2
)将您的WatchEvent
class 与用户 model 关联两次。 Then, add a 'virtual association reader' ( user
) and a 'virtual association setter' ( user=(new_user)
):然后,添加一个“虚拟关联阅读器”(
user
)和一个“虚拟关联设置器”( user=(new_user)
):
class WatchEvent < ApplicationRecord
belongs_to :user_1,
class_name: 'User',
foreign_key: :customer_id
belongs_to :user_2,
class_name: 'User',
foreign_key: :user_id
def user
user_1 || user_2
end
def user=(new_user)
self.user_1 = new_user
end
end
With this solution, the requirements "use customer_id
to find user" and "use user_id
as fallback foreign key if customer_id
is nil
or doesn't yield a result" is satisfied.使用此解决方案,满足“使用
customer_id
查找用户”和“如果customer_id
为nil
或不产生结果,则使用user_id
作为备用外键”的要求。 It happens in the association reader method user
.它发生在关联阅读器方法
user
中。 When there is a reader method, you'll need a setter method, which is user=()
.当有 reader 方法时,您将需要一个 setter 方法,即
user=()
。 Feel free to design the setter's internals as required, mine is just a suggestion.随意根据需要设计二传手的内部结构,我的只是一个建议。
BTW: You may need to re-add the declaration of the foreign primary_key
.顺便说一句:您可能需要重新添加外部
primary_key
的声明。 I omitted that for clarity.为了清楚起见,我省略了这一点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.