Rails Rails 中,怎么才能删除关联对象集合时 不自动 commit ??

rogerluo410 · 2015年12月30日 · 最后由 rogerluo410 回复于 2015年12月31日 · 1711 次阅读
Parent: 
has_many :children, dependent: :destroy

Child
belongs_to :parent  

new_arr = [ 1 ,3 , 5]
parent.children = parent.children.where(id: new_arr)  #剔除掉id不等于1,3,5的元素

现在的问题是, 在做 collection= 操作后, rails 自动 saving 且 commit 了这个事务。 但是,我希望它不 commit , 并且不使用 parent.transaction do ... end 显式事务控制的代码。

相关问题: http://stackoverflow.com/questions/22927284/how-to-delete-some-associations-from-an-activerecord-object-without-saving ---- 这个帖子中用 reject!好像没效果 https://github.com/rails/rails/issues/6994 --这个 issue 用 before_save 处理不知道是否可行

有什么好的办法吗?

http://stackoverflow.com/questions/11353582/delete-associated-records-when-model-is-saved 和这个作者相同的问题。

诶人遇到这种情况吗。。。

parent.children = parent.children.where(id: new_arr)  #剔除掉id不等于1,3,5的元素

假设这行代码真的执行了而没保存,后面你打算如何使用?

#2 楼 @qinfanpeng

parent.save 的时候去 commit, 就是不想有事务嵌套,用 rails save 时隐式 commit。。。

你在自己的 transaction 里面写个ChildClass.where(id: new_arr).delete_all不就完了么。

autosave 设置成 false 可以么

#5 楼 @ywjno

不行, parent.save 时 也不会持久化 children 了。。。

#4 楼 @billy

你好, 你指的 “自己的 transaction” 是什么?

#6 楼 @rogerluo410 那你只能手动控制连接的 autosave 了

我觉得你第二个链接里的办法不错啊。override Rail 的 association methods,然后注册一个 before save

很遗憾,你这个情况必须把自己的存储逻辑用 transaction 包裹起来,没办法用 save 触发的隐式 transaction 。

相比这个需求,我更好奇 LZ 为什么要排斥自己写 transaction 呢?只调一个 save 本身就是非常理想化的情况。稍微复杂点的逻辑都需要自己写 transaction ,框架没办法帮你智能地界定 transaction 的边界的。

因为 children 的从属关系不是保存在主对象里的,而是保存在子对象里。 从 children 里剔除,只能经由 delete 这种方法。 否则你就得用事务。

accept_nested_attributes_for :children, allow_destroy: true

parent.children_attributes = [
  {:id => 1, "_destroy" => true},
  {:id => 2}
]

parent.save的时候才会触发children id=1的 删除 操作。 

#12 楼 @yakjuly

谢谢, 你的方法可行!!

#10 楼 @darkbaby123 #8 楼 @ywjno #11 楼 @msg7086 #2 楼 @qinfanpeng #9 楼 @adamshen 12 楼这位大兄弟的方法可行, 仅供各位参考, 谢谢大家热情的回复

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册