2014-12-03 37 views
0

我是一名初学者/中级Rails开发人员,我继承了一个大型的Rails项目。虽然挖通过代码库,我发现我们的模型中的一个具有依赖于硬编码的ID关联的定义:Rails关联定义有“幻数”

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 

客户和供应商都是实体,具有关系到帐户(通过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 

这不起作用,(未知键(S):范围(引发ArgumentError)),但看起来也许会有对它的支持,如果我知道如何正确定义的关联

3)成立于EntityAccountRel继承关系,避免了entity_type_id的需求(可能的EntityType以及):

class CustomerAccountRel < EntityAccountRel 

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

这些都是我提出的所有选项,但我想我错过了一些明显的东西。

+0

要考虑的最明显的一点就是投资回报率是否是真正值得的。数据库播种解决了这个问题,就像在init中加载它们一样,如果除了ID之外还有别的东西可以使用,比如字符串。 – 2014-12-03 20:03:28

+0

您做出的投资回报率好点 - 最终,它可能不值得,但我已经得到了一些休息时间,我想发展自己的设计能力,以及推动这一项目。 – 2014-12-03 20:09:47

+0

“最佳”解决方案实际上取决于我可能不知道的东西。效率将更多地通过指数化​​来确定。如果担心的只是完整性和效率,我可能会考虑在应用程序启动过程中将枚举值定义为枚举或常量中的命名值。 – 2014-12-03 22:25:40

回答

0

EntityType#id似乎被认为是静态的,并密切相关的代码的行为,所以你可以给他们的名字为常量:

class EntityType 
    CUSTOMER = 1 
    VENDOR = 2 
end 

,然后刚刚替补通过不断的幻数。这很快,并给你一个很好的回报,因为你可以很容易地在代码的其他部分引用它。我会在模型层中保留对这些常量的所有引用。

+0

这也可以动态地在启动时为了去除脆岬的一个来源,如果有一个与每个值相关联的有用的人类可读的字符串。 – 2014-12-03 22:38:39