我如何使用多个外键制作 rails 模型 belongs_to
How can i make rails models belongs_to using multiple foreign key
最近我有一个迁移,将 user_id
列添加到 watch_events 表。因此我想更改 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
之前
class WatchEvent < ApplicationRecord
belongs_to :user, foreign_key: :customer_id, primary_key: :customer_id
end
我想要的:
- 如果
watch_event.customer_id
存在,我想使用 belongs_to :user, foreign_key: :customer_id, primary_key: :customer_id
- 如果
watch_event.customer_id
不存在,我想使用正常 belongs_to :user
如何在 watch_event 模型上实现这一点?
如果我没有正确理解你的问题,那么你正在寻找的是 Polymorphic association。
如果您看到下面的代码,它基本上所做的就是在 watch_events
、table、watcher_type
和 watcher_id
中创建两列。 belongs_to :watcher
然后使用 watcher_type
列来确定它应该关联到哪个模型,
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
我认为 Rails 不支持 'fallback foreign keys' 关联。但是,您可以为您的问题编写一个简单的包装器。首先,使用你的两个键和两个 'internal' 关联名称(:user_1
和 :user_2
)将你的 WatchEvent
class 与用户模型关联两次。然后,添加一个 'virtual association reader' (user
) 和一个 'virtual association setter' (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
使用此解决方案,要求“使用 customer_id
查找用户”和“如果 customer_id
为 nil
或不为 nil
,则使用 user_id
作为后备外键产生结果”是满意的。它发生在关联 reader 方法 user
中。当有 reader 方法时,您将需要一个 setter 方法,即 user=()
。随意根据需要设计 setter 的内部结构,我的只是一个建议。
顺便说一句:您可能需要重新添加国外的声明primary_key
。为了清楚起见,我省略了它。
最近我有一个迁移,将 user_id
列添加到 watch_events 表。因此我想更改 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
之前
class WatchEvent < ApplicationRecord
belongs_to :user, foreign_key: :customer_id, primary_key: :customer_id
end
我想要的:
- 如果
watch_event.customer_id
存在,我想使用belongs_to :user, foreign_key: :customer_id, primary_key: :customer_id
- 如果
watch_event.customer_id
不存在,我想使用正常belongs_to :user
如何在 watch_event 模型上实现这一点?
如果我没有正确理解你的问题,那么你正在寻找的是 Polymorphic association。
如果您看到下面的代码,它基本上所做的就是在 watch_events
、table、watcher_type
和 watcher_id
中创建两列。 belongs_to :watcher
然后使用 watcher_type
列来确定它应该关联到哪个模型,
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
我认为 Rails 不支持 'fallback foreign keys' 关联。但是,您可以为您的问题编写一个简单的包装器。首先,使用你的两个键和两个 'internal' 关联名称(:user_1
和 :user_2
)将你的 WatchEvent
class 与用户模型关联两次。然后,添加一个 'virtual association reader' (user
) 和一个 'virtual association setter' (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
使用此解决方案,要求“使用 customer_id
查找用户”和“如果 customer_id
为 nil
或不为 nil
,则使用 user_id
作为后备外键产生结果”是满意的。它发生在关联 reader 方法 user
中。当有 reader 方法时,您将需要一个 setter 方法,即 user=()
。随意根据需要设计 setter 的内部结构,我的只是一个建议。
顺便说一句:您可能需要重新添加国外的声明primary_key
。为了清楚起见,我省略了它。