从外键获取 Rails 关联?

4
我希望能够通过给定的外键名称和模型类,获取相应的关联信息(以了解它可以被解析为哪个模型)。
例如:
# model: product.rb
class Product < ActiveRecord::Base
  belongs_to :category
end

# resolution:
association = Product.get_association('category_id')

所以我需要这个get_association函数。

目前我已知:

  1. 从Product.reflections可以获取反射/关联列表
  2. 对于一个反射,我可以获取外键
  3. 我可以建立这个外键的映射,以获取关联

然而,我想问是否有一种简单的方法可以直接调用?

更新: 我实际需要的是

我正在使用audit实现一个审计日志视图。 然而,当我尝试输出审计日志时,我所能得到的类似于:

supplier_id: changed from '1' to '0'

我希望能够用供应商的实际名称替换数字,因此我认为如果给定supplier_id,我应该能够获取Supplier模型。

另外,由于我使用了like:

belongs_to :reporter, class_name: 'User'

因此,我不能仅从给定的关键字猜测类名。

嘿,你实际上需要什么?那个解释有点混淆。请详细说明更多细节。 - Bharat soni
@Bharatsoni 用例已更新 :) - songyy
@songyy,你找到解决方案了吗? - Fivell
1个回答

3
您正在寻找"reflect_on_association"的相关信息,可以查看这个链接:reflect_on_association。如果您的模型如下所示:Product.reflect_on_association(:category),那么请注意:不要在此处使用reflect*。简而言之,记录类名并使用".find"。
class Employee
  belongs_to :manager, foreign_key: :manager_id
end

class Manager
  has_many :subordinates, foreign_key: :manager_id, class_name: 'Employee'
end

日志文件记录了如下信息:manager_id: changed from '1' to '2',被更改的模型是Employee,因为它包含有manager_id这个字段。但是在你提出的问题的示例日志中,无法确定是哪个模型发生了更改,因为可能不止一个模型包含有manager_id这个字段,所以并不能得出一个明确的答案。但是在这种简单的情况下,我们知道相关的模型是Manager,并且日志中的数字可以替换为名称:Manager.find(1)Manager.find(2)。这里不需要任何反射魔术。


再来看这个案例:

class Employee
  belongs_to :manager, foreign_key: :department_id, class_name: 'Manager'
end

class Responsibility
  belongs_to :manager, foreign_key: :organizer_id, class_name: 'Manager'
  belongs_to :department, foreign_key: :department_id, class_name: 'Department'
end

class Manager
  has_many :subordinates, foreign_key: :organizer_id, class_name: 'Employee'
  has_many :obligations, foreign_key: :organizer_id, class_name: 'Responsibility'
end

class Department
  has_many :obligations, foreign_key: :department_id, class_name: 'Responsibility'
end

如果你的日志只包含 department_id: 从 '1' 变为 '2',你就不知道公司具体发生了什么变化。

为了解决这个问题,你需要记录相关模型类的类名(而不是已更改模型的类名)。如果你有类名,你就不需要进行反射,就像第一个简单案例中一样,只需要使用 .find 方法即可。


3
谢谢提供信息。但是似乎我只能调用 Product.reflect_on_association(:category);调用 Product.reflect_on_association(:category_id) 将返回 nil - songyy
你是对的。我已经在答案中修复了它。如果你只有包含“_id”部分的字符串,你可以使用.sub!(/_id$/, '')来删除它。 - Martin Schmidt
1
嗯,但有时候外键可能不是 [association_name]_id,因为我可以像这样设置外键:has_many :subordinates, class_name: "Employee", foreign_key: "manager_id" - songyy
我编辑了我的回答,再次。 - Martin Schmidt
谢谢 :) 我实际上在我的代码中使用了你的方法。而且我在表单中显示了类名 :) - songyy
你使用.reflect_on_association还是.find?我认为你应该选择.find。我认为.reflect_on_association可能会在早晚某个时候出现错误。 - Martin Schmidt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接