防止实例上的ActiveRecord save()

时间:2010-05-30 00:00:54

标签: ruby-on-rails ruby activerecord clone

我有一个ActiveRecord模型对象Foo;它代表一个标准的数据库行。

我希望能够显示此对象的实例的修改版本。我想重用这个类本身,因为它已经拥有了所有的钩子和放大器。我需要的方面。 (例如:我已经有一个显示适当属性的视图)。基本上我想克隆模型实例,修改它的一些属性,然后将它反馈给调用者(视图,测试等)。

希望这些属性修改重新回到数据库中。但是,我确实希望在克隆版本中包含id属性,因为它更容易处理路由助手。因此,我计划调用ActiveRecord::Base.clone(),手动设置克隆实例的ID,然后对新实例进行适当的属性更改。这让我很担心;

所以,我正在寻找锁定新实例,这样就不会伤害其他任何东西。我已经计划调用save()(基于这一理解,这可以阻止对对象的进一步修改,尽管documentation isn't terribly clear)。但是,我没有看到任何明显的方法来阻止save()。

实现这一目标的最佳方法是什么?

3 个答案:

答案 0 :(得分:20)

您可以使用ActiveRecord::Base#readonly!

model = MyModel.find 1
model.readonly!
model.save!

它将引发ActiveRecord :: ReadOnlyRecord

答案 1 :(得分:4)

可能有更惯用的方法,但一种方法是设置虚拟属性并在before_save回调中进行检查。克隆对象时,请设置虚拟属性 - 可能类似于is_clonetrue。然后为模型类定义before_save回调,如果设置了该属性,则阻止保存。

答案 2 :(得分:4)

freeze()似乎正在以一种丑陋的方式实现我想要的目标。

x = Factory.create(:my_model)
x.save!    # true
x.freeze
x.save!
TypeError: can't modify frozen hash

我猜测save()正在尝试更新创建/修改的属性,这会因为属性哈希被冻结而失败。

因此,冻结将阻止保存...但我更欣赏一种更可靠的方法,并提供更具体的错误消息。