Rails关联定义具有"幻数"

时间:2014-12-03 20:00:15

标签: ruby-on-rails ruby ruby-on-rails-3

我是初学者/中级Rails开发人员,我继承了一个大型的Rails项目。在挖掘代码库时,我发现我们的一个模型具有依赖于硬编码ID的关联定义:

class Account < ActiveRecord::Base
  has_many :customer_rels, :class_name => 'EntityAccountRel', :conditions => 'entity_account_rels.entity_type_id=1'
  has_many :vendor_rels, :class_name => 'EntityAccountRel', :conditions => 'entity_account_rels.entity_type_id=2'

  has_many :customers, :through => :customer_rels, :source => :entity
  has_many :vendors, :through => :vendor_rels, :source => :entity

客户和供应商都是实体,与Account(通过EntityAccountRel)有关系。它们通过entity_type_id彼此区分,entity_type_id是指EntityType,这是一个模型,其少数成员足够静态,让我们通过硬编码的id引用它们。我认识到这是一种不好的做法,但我想知道重构的“最佳”方式:

1)重新定义关联定义以使用如下的子查询:

has_many :customer_rels, :class_name => 'EntityAccountRel', :conditions => 'entity_account_rels.entity_type_id=(select id from entity_type where name="Customer")'

这对我来说是最明显的解决方案,但也看起来非常不优雅,也可能效率低下

2)在EntityAccountRel上定义范围,如下所示:

scope :customer, joins(:entity_type).where('entity_type.code="CUST"')

然后以某种方式将其与关联定义联系起来:

has_many :customer_rels, :class_name => 'EntityAccountRel', :scope => :customer

这不起作用,(未知密钥:范围(ArgumentError))但似乎如果我知道如何正确定义关联,可能会支持它

3)在EntityAccountRel上建立一个继承关系,不需要entity_type_id(也可能是EntityType):

class CustomerAccountRel < EntityAccountRel

这将简化我的关联定义,但它似乎是一个具有深远影响的主要重构。另外,我被告知谨慎使用继承,因为它可能使代码难以理解。

这些是我提出的所有选项,但我认为我遗漏了一些明显的东西。

1 个答案:

答案 0 :(得分:0)

EntityType#id似乎被认为是静态的并且与代码行为密切相关,因此您可以将它们命名为常量:

class EntityType
  CUSTOMER = 1
  VENDOR = 2
end

然后用常数替换幻数。这很快,并为您提供了良好的回报,因为您可以轻松地在代码的其他部分引用它。我会在模型层中保留对这些常量的所有引用。