【问题标题】:Re-Associating a child object to another parent -- Rails (2.3.11) delete has_many associated object without sql operationRe-Associating a child object to another parent -- Rails (2.3.11) delete has_many associated object without sql operation
【发布时间】:2011-05-17 14:14:11
【问题描述】:

给出以下定义

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]

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

【问题讨论】:

    标签: ruby-on-rails activerecord associations


    【解决方案1】:

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

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

    这将从 foo1 的 bar 集合中删除 bar1,但 bar1 在数据库中将保持不变,因为 delete_if 在构建 HasManyAssociation 的 Enumerable 上工作。

    【讨论】:

    • 查看我的问题的修正。
    • mmhhh 那么我的解决方案应该可以工作,您将栏重新分配(但不保存)给新的 foo,然后在旧的 foo 上调用 hide_bar(bar)。在您看来,您只需使用foo1.visible_bars 而不是foo1.bars。但是您需要将状态保存在表单中的某个位置,否则它将在下一次请求时丢失。如果您想保持新状态,您可能需要添加一个额外的列,例如“temporary_foo_id”,默认设置为 null,如果验证失败,将设置为现有的 foo_id。
    • 是的,如果需要,我可以这样处理...有没有更好的方法来重新关联子对象?我不能成为第一个需要重新关联的人。奇怪的是 :nullify 文档表明没有在子对象上调用 .save 。我认为这意味着没有请求数据库更新。
    • 确定另一个可能有效的解决方案是使用以下内容:foo1.bars.delete_if{|b| b.id == bar1.id},因为它应该适用于 Enumerable 而不是 DB 关联。 编辑它有效! :)
    • 你能发布另一个答案吗?我接受那个,因为它有效!!!!你刚刚让我很开心。
    【解决方案2】:

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

    【讨论】:

    • 我不想触发破坏。这就是为什么我有 :dependent => :nullify
    猜你喜欢
    • 1970-01-01
    • 2022-12-27
    • 2022-12-01
    • 2016-03-22
    • 2022-12-02
    • 2023-03-10
    • 1970-01-01
    • 2022-12-01
    • 1970-01-01
    相关资源
    最近更新 更多