我有一个模型,我正在我的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表一样。
答案 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
关系,您可以通过product
或product_id
设置该关系来更改它,它只会查找一次产品,如果更改则会再次查找。< / p>