如何将ActiveRecord属性重新映射到外键中,并且中断时间最短?

时间:2011-12-29 23:46:15

标签: ruby-on-rails ruby activerecord

我有一个模型,我正在我的Rails应用程序中构建产品的价格:

class Price < ActiveRecord::Base
  validates_presence_of :country_code, :product, :amount
  validates_uniqueness_of :product, :scope => [:country_code]
end

适当地,DB模型如下:

create_table :prices do |t|
  t.string :country_code
  t.integer :product_id
  t.integer :amount
end

复杂的是,目前,Product不是一个真正的ActiveRecord模型 - 它是一个包含大量常量和辅助方法的单个ID属性(item_code)的Struct。在未来的sprint中有计划将其重新正确地重构到数据库中,但是现在,我们的大多数应用程序代码都使用Product,好像它已经来自数据库,理想情况下,我想将一次更改隔离一次对于只在DB中具有直接关系的模型,产品就成了一个合适的表。

然后,问题是当底层数据库中没有实际的其他表时,干净地处理模型中的外键关系。为了在逻辑上解决这个问题,我在Price中添加了以下验证:

validates_inclusion_of :product, :in => Product.all

其中Product.all是一种模拟来自表的这些对象而不是实际的ActiveRecord类的方法。

所有这些共同导致了一个问题,据我所知,因为没有Product表,ActiveRecord没有创建:产品访问者(而是直接使用:product_id)。但是,如果我依赖于:product_id,那么一旦Product成为实际的ActiveRecord类,我就会更难迁移。

是否有一种简单的方法可以将:product属性“alia”到:product_id字段,以便代码在Product(甚至是Price模型)中被隔离,以便出于所有意图和目的:产品是否自动映射,就好像数据库表中存在关系一样?显然,理想的解决方案是某些方法或别名指令,可以在将来某个日期删除,突然一切都会像product_id一直指向products表一样。

1 个答案:

答案 0 :(得分:0)

如果您只想伪造字段,就好像您在Price模型中设置了has_one关系一样,您可以在价格模型中自己定义方法。由于您没有举例说明如何从Product Struct中进行选择,因此如果您尝试为ActiveModel重新实现它,则下面是一个代码示例。

def product
    if self.product_id
        if !@product or @product.id != self.product_id
            @product = Product.find(self.product_id)
        else
            @product
        end
    end
end

def product=(product)
    @product = product
    self.product_id = product._id
end

这将复制has_one关系,您可以通过productproduct_id设置该关系来更改它,它只会查找一次产品,如果更改则会再次查找。< / p>