Rails:设置关联对象与设置关联ID

时间:2013-05-20 11:47:04

标签: ruby-on-rails rails-activerecord

我正在关注“使用Rails进行敏捷Web开发”一书并尝试将产品价格复制到LineItem。在LineItem上覆盖setter似乎是合适的选择。但是,正如在Rails中经常出现的那样,有两个生成的setter使得练习变得非常重要:

  def product_id=(product_id)
    product = Product.find(product_id)
    write_attribute(:price, product.price)
    write_attribute(:product_id, product_id)
  end

  def product=(product)
    self.product_id = product.id #wtf? why isn't this the default?
  end

此代码按预期工作,无论我是设置对象还是它的id,在这两种情况下都会复制价格。是什么让我想知道:

为什么这个代表不工作而不必覆盖“product =(..)”?奇怪的是,没有删除“自我”它将无法工作,显然它不会委托给“product_id =()”......

2 个答案:

答案 0 :(得分:1)

使用默认实现调用product=将不会调用product_id=。它只是像您在重写的write_attribute方法中那样使用product_id=

答案 1 :(得分:-1)

您的模型不是最佳

我不确定你要做什么,或者你为什么要这样做,但在我看来,至少你的部分问题是你的模型关系是错误的 - 或者至少次优的。

这样看:

  1. 产品应该有价格。这在逻辑上是产品的属性。
  2. LineItem实际上是产品及其属性的表示,也可能是其他一些相关数据。
  3. 我意识到你正在学习一些教程,所以也许本教程试图提出一些具体的观点。但是,在实际应用程序中,规范化数据库不应该从模型到模型或对象到对象复制数据;价格应该只有一个居住地,应该从其他表中引用(而不是复制)。

    模型注意事项

    如果您遵循我的建议,则产品具有ID,LineItem具有对product_id字段中存储的产品的引用,您可以通过LineItem.product.price访问价格,或者如果您不知道,则设置委派我想违反这个常见用例的Demeter法。

    这可能对您的教程没有帮助,但使用ActiveRecord关系对我来说比将值从一个表复制到另一个表更有意义。 YMMV。