class Assembly < ActiveRecord::Base
has_and_belongs_to_many :parts
end
class Part < ActiveRecord::Base
has_and_belongs_to_many :assemblies
end
在控制台中:
part1 = Part.new
assembly1 = Assembly.new
assembly1.parts << part1
part1.delete
Parts.all
=> []
检查assembly1.parts
表示仍有关系。(!)
删除记录后如何实现?
另外,如何防止删除与程序集关联的部件?
使用Rails 3.0.7。
答案 0 :(得分:3)
你在这里所做的一切都是从内存中完成的(没有任何内容存储在数据库中)。
ActiveRecord delete
方法将从数据库中删除一个对象,但它不会在内存中寻找可能已经引用该对象的其他对象。我想如果你做assembly1.parts.delete(part1)
可能会做你期望的事情。
如果您已将对象保存到数据库:
part1 = Part.create
assembly1 = Assembly.create(:parts => [part1])
assembly1.parts
# => [part1]
part1.delete
assembly1.parts
# => [part1]
assembly1.reload
assembly1.parts
# => []
请注意,即使它在数据库part1.delete
中也不一定会从汇编对象中删除它,直到您刷新内存中集合或使用我之前提到的方法删除它assembly1.parts.delete(part1)
< / p>
更新
我认为通常不应使用delete()
方法。您应该几乎总是使用destroy()
。 delete()
将触发对数据库的删除并忽略所有回调,我相信模型中的:dependent => :destroy
- 样式声明。如果您使用destroy()
方法,则可以在模型中声明before_destroy
回调:
class MyClass
has_and_belongs_to_many :foos
before_destroy :allow_destroy
def allow_destroy
foos.empty?
end
end
如果它是装配的一部分,那么你应该要求不要销毁它。您无法阻止delete()
执行,因为它会忽略回调:ActiveRecord::Relation#delete documentation
答案 1 :(得分:0)
您需要将:dependent => :destroy
添加到控制器。
答案 2 :(得分:0)
您可以通过在referential integrity中添加foreign key来防止数据库中的myobject.delete
。
建议您查看Adding foreign key to a rails model
在我的项目中,这并没有阻止myobject.destroy
。我认为这是因为它确实使用awesome nested set gem尝试为您处理级联破坏。
防止myobject.destroy
我发现How do I 'validate' on destroy in rails晚餐会有所帮助
我最终使用了before_destroy
并在迁移中使用add_foreign_key
添加了一些参照完整性。
如果使用myobject.delete
或使用myobject.destroy
,这将防止删除。
myobject
具有许多自身并属于其中一种。 act_as_nested_set
就是这样。
模型
class Myobject
before_destroy :allow_destroy
# ^ this has to be above act_as_nested_set
acts_as_nested_set
def allow_destroy
return true if self.descendants.blank?
# the error is optional.
self.errors.add('Cannot_delete', 'myobject still has children')
throw(:abort)
end
end
迁移
class AddForignKeyToMyobject < ActiveRecord::Migration
def change
add_foreign_key :myobject, :myobject, column: :parent_id
end
end