将子对象重新关联到另一个父对象 - Rails(2.3.11)删除has_many关联对象而不执行sql操作

时间:2011-05-17 14:14:12

标签: ruby-on-rails activerecord associations

鉴于以下定义

Foo
    has_many :bars, :dependent => :nullify, :autosave => false

Bar
    validates_presense_of :foo
    foo_id is not null # database constraint

我想将Bar对象重新关联到另一个Foo对象。我需要在内存中正确完成所有内容,这样我就可以在所有工作验证失败后呈现所有内容。

问题出在我做

之类的事情的时候
bar.foo.bars.delete(bar)
bar.foo = other_foo
other_foo.bars << bar

我遇到一个失败,在bar.foo.bars.delete(bar) sql更新执行会使我的bar的foo_id属性变为空。因此sql约束异常和失败。我反而需要它只是在内存中工作并在必要时验证失败。

编辑:

事情就是这一切都在一个事务中,所以我不关心数据库更新,我只是不希望它们触发数据库约束问题,但我希望我的约束存在并且不允许在db为我的Bar对象。当我的保存执行时,如果成功,我希望我的保存适当地重新关联所有内容。如果它失败了,我希望我的内存模型处于正确更新(但无效)的状态,这样我就可以使用更新失败的更新值和消息来呈现我的页面。

老实说,我的主要目标是出现以下情况:

之前:

foo1.bars => [bar1, bar2]
foo2.bars => [bar3]

后:

foo1.bars => [bar1]
foo2.bars => [bar3, bar2]

所以我的主要目标是解决这个问题(内存中所有适当对象的完全更新),如果它不涉及像我已经拥有的那样重新关联,我也会接受。

2 个答案:

答案 0 :(得分:1)

要删除父级(foo1)条形集合中的关联子元素(bar1)元素,您可以使用

foo1.bars.delete_if{|b| b.id == bar1.id}

这将从foo1的bars集合中删除bar1,但bar1将在数据库中保持不变,因为delete_if适用于构建HasManyAssociation的Enumerable。

答案 1 :(得分:0)

您可以覆盖删除方法或只创建before_destroy过滤器。 Rails documentation