Rails的ActiveRecord的3.2:如何跳过子模型before_delete回调? [英] Rails ActiveRecord 3.2: How to skip before_delete callback in child model?

查看:125
本文介绍了Rails的ActiveRecord的3.2:如何跳过子模型before_delete回调?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在工作中的Rails 3.2.16。在我的应用程序,一个账户HAS_MANY用户。一个账户必须始终具有管理用户,所以你不能消灭他们。这需要的是护理:

I'm working in Rails 3.2.16. In my app, an account has_many users. An account must always have admin users, so you can't destroy them. This takes care of that:

class Account < ActiveRecord::Base
  has_many :users, :dependent => :destroy
end

class User < ActiveRecord::Base
  before_destroy :check_if_admin

  def check_if_admin
    false if self.is_admin
  end
end

不过,当你摧毁整个帐户,该管理员应,以及销毁。相反,当我打电话 @ account.destroy 从控制器,用户#before_delete 回调prevents管理员用户被破坏。

However, when you destroy the whole account, the admins should be destroyed as well. Instead, when I call @account.destroy from the controller, the User#before_delete callback prevents the admin users from being destroyed.

我知道我可以叫 @ account.delete 跳过回调,但我的理解是,:依赖=&GT; :摧毁本身就是一个回调,这样只会删除该帐户,而不是用户

I know I could call @account.delete to skip callbacks, but my understanding is that the :dependent => :destroy is itself a callback, so that would only delete the account, not the users.

有没有办法回调里面知道我从哪里来,如:

Is there a way inside the callback to know where I came from, e.g.

def check_if_admin
  return if [I'm doing an Account dependent delete]
  false if self.is_admin
end

还是我不得不手动删除用户销毁荷兰国际集团的帐户?

or do I have to manually delete the users before destroying the account?

推荐答案

通过这个答案的帮助下,我找到了该溶液中。我们的想法是暂时关闭特定的子回调,而破坏了父母。请注意,我不得不添加:prePEND =&GT; :得到真正选项我定制的回调重新加入连锁的前

With the help of this answer, I found this solution. The idea is to temporarily turn off the specific child callback while destroying the parent. Note that I had to add the :prepend => :true option to get my custom callback re-added to the front of the chain.

class Account < ActiveRecord::Base
  before_destroy :disable_user_check_if_admin
  before_destroy :enable_user_check_if_admin

  has_many :users, :dependent => :destroy

  def disable_user_check_if_admin
    User.skip_callback(:destroy, :before, :check_if_admin)
  end

  def enable_user_check_if_admin
    User.set_callback(:destroy, :before, :check_if_admin), :prepend => :true
  end
end

class User < ActiveRecord::Base
  before_destroy :check_if_admin
  has_many :contacts, :dependent => :restrict

  def check_if_admin
    false if self.is_admin
  end
end

没有:prePEND =&GT; :真正的,我遇到了麻烦,因为我的用户模型还的has_many:联系人:依赖=&GT; :限制。问题是, skip_callback 实际删除回调和 set_callback 再增加了回调的在年底回调链的。使用:prePEND =&GT; :真正的,我可以插入我的自定义 before_destroy:check_if_admin 回调在链的最前端。请参阅文档和源$ C ​​$ C <一个href="http://api.rubyonrails.org/v3.2.16/classes/ActiveSupport/Callbacks/ClassMethods.html#method-i-set_callback"相对=nofollow>这里。

Without :prepend => :true, I ran into trouble because my User model also has_many :contacts, :dependent => :restrict. The problem is that, skip_callback actually deletes the callback and set_callback re-adds the callback at the end of the callback chain. Using :prepend => :true, I was able to insert my custom before_destroy :check_if_admin callback at the front of the chain. See docs and source code here.

替代解决方案(未使用)

虽然我打回调序列中,我尝试了不同的解决方案,离开回调完好。从这个答案借用,我用了一个访问的帐户,让我检查时,它被删除:

While I was fighting the callback sequence, I tried a different solution that leaves the callbacks intact. Borrowing from this answer, I used an accessor on Account to let me check when it is being deleted:

class Account < ActiveRecord::Base
  before_destroy :disable_user_check_if_admin
  before_destroy :enable_user_check_if_admin

  has_many :users, :dependent => :destroy
  attr_accessor :destroying

  def disable_user_check_if_admin
    self.destroying = true
  end

  def enable_user_check_if_admin
    self.destroying = false
  end
end

class User < ActiveRecord::Base
  before_destroy :check_if_admin
  has_many :contacts, :dependent => :restrict 

  def check_if_admin
    return if self.account.destroying
    false if self.is_admin
  end
end

该做的工作,但它并没有闻的权利被设置和检查这样的一个标志,所以我又回到了跳跃/​​套回调使用:prePEND =&GT; :真正的

This did work but it doesn't "smell" right to be setting and checking a flag like this, so I went back to the skip/set callback using :prepend => :true.

这篇关于Rails的ActiveRecord的3.2:如何跳过子模型before_delete回调?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆