我正试图找出一种方法来部分删除/销毁rails中的依赖模型。
代码看起来像这样:
class User < ActiveRecord::Base
has_many :subscriptions
has_many :photos, :dependent => :destroy
has_many :badges, :dependent => :destroy
before_destroy :partial_destroy
def partial_destroy
self.photos.destroy_all
self.badges.destroy_all
return false if self.subscriptions.any?
end
...
基本上,我想破坏照片和徽章,但如果用户有任何订阅,我想保留这些订阅,并且还防止用户被破坏。
我尝试使用.each { |obj| obj.destroy }
并使用delete
和delete_all
,但似乎并不重要。
当before_destroy
返回false时,看起来rails正在执行某种回滚。有没有办法摧毁部分家属而不是其他人?
答案 0 :(得分:1)
这是旧的,所以我希望你已经忘记了它,但我偶然发现了它。
我并不感到惊讶delete
和delete_all
没有用,因为那些bypass callbacks。
你完全正确Rails performs a rollback if any before_
callback returns false。由于Rails将整个回调链包装在一个事务中,因此您无法在链中执行数据库调用(如销毁)。我建议的是在回调中添加一个条件:
答案 1 :(得分:1)
我最终做了以下事情:
destroy
模型上覆盖User
(见下文)User
,而是销毁不需要的家属,并清空User
模型本身的任何字段,例如电子邮件。UserDeleter
类,它接管用户并执行所有清算操作,只是为了让事情更清洁/具有某种单一责任destroy
def destroy
run_callbacks(:destroy) do
UserDeleter.new(self).delete
end
end
class UserDeleter
def initialize(user)
@user = user
end
def delete
delete_photos
delete_badges
clear_personal_data
# ...
end
private
def delete_photos
@user.photos.destroy_all
end
def clear_personal_data
@user.update_attributes!(
:email => deleted_email,
:nickname => '<deleted>')
end
def deleted_email
"deleted@#{random_string}.com"
end
def random_string(length = 20)
SecureRandom.hex(length)[0..length]
end
#...
end