我有一个继承自ActiveRecord :: Base的Commentable类和一个继承自Commentables的Event类。
我已经覆盖了这两个类中的destroy方法,而Event.distroy调用了super。然而,一些意外的事情发生了。具体而言,将删除事件的has_and_belongs_to_many关联。我认为这是因为一些模块被包含在Commentables和Event类之间,但不确定是否有办法阻止它。
以下是简化代码:
class Commentable < ActiveRecord::Base
has_many :comments
def destroy
comments.destroy_all
self.deleted = true
self.save!
end
end
class Event < Commentable
has_and_belongs_to_many :practitioners, :foreign_key => "commentable_id"
def destroy
#some Event specific code
super
end
end
我不想从数据库中删除行,只需设置“已删除”标志。我也不想删除任何关联。但是,在Event.destroy和Commentable.destroy之间的某处,其他一些rails代码会破坏has_and_belongs_to_many表中的记录。
知道为什么会这样,以及如何阻止它?
答案 0 :(得分:5)
您实际上不必覆盖Commentable
模型上的destroy,只需添加一个返回before_destroy
的{{1}}回调来实际取消销毁调用。例如:
false
class Commentable < ActiveRecord::Base
# ... some code ...
before_destroy { |record|
comments.destroy_all
self.deleted = true
self.save!
false
}
# ... some code ...
end
模型也是如此;只需添加回调而不覆盖destroy方法本身。
有关可用回调的更多内容为here。
答案 1 :(得分:0)
如果返回false
,Rails 5不会停止回调链。我们必须改为使用throw(:abort)
。
before_destroy :destroy_validation
def destroy_validation
if condition
errors.add(:base, "item cannot be destroyed because of the reason...")
throw(:abort)
end
end
在Rails 5之前,从false
和before_ callback
中的任何ActiveModel or ActiveModel::Validations, ActiveRecord
返回ActiveSupport
导致回调链停止。
我们可以通过将配置更改为true
来关闭此默认行为。但是,当false
从回调返回时,Rails将显示弃用警告。
新的Rails 5应用程序附带了一个名为callback_terminator.rb
的初始化程序。
ActiveSupport.halt_callback_chains_on_return_false = false
默认情况下,该值设置为false
。
=> DEPRECATION WARNING: Returning `false` in Active Record and Active Model callbacks will not implicitly halt a callback chain in the next release of Rails. To explicitly halt the callback chain, please use `throw :abort` instead.
ActiveRecord::RecordNotSaved: Failed to save the record
这是一个受欢迎的更改,将有助于防止回调意外中断。