引用所有依赖对象对象的集合

时间:2013-10-05 20:55:10

标签: ruby-on-rails activerecord has-many-through has-one

我有三个activerecord类:Klass,Reservation和Certificate Klass可以有很多预订,每个预订可以有一个证书

定义如下......

class Klass < ActiveRecord::Base
  has_many :reservations, dependent: :destroy, :autosave => true  
  has_many :certificates, through: :reservations
  attr_accessible :name

  def kill_certs
    begin
      p "In Kill_certs"
      self.certificates.destroy_all
      p "After Destroy"
    rescue Exception => e
      p "In RESCUE!"
      p e.message
    end  
  end

end

class Reservation < ActiveRecord::Base
  belongs_to :klass
  has_one :certificate, dependent: :destroy, autosave: true
  attr_accessible :klass_id, :name
end

class Certificate < ActiveRecord::Base
  belongs_to :reservation
  attr_accessible :name
end

我希望能够通过调用Klass#kill_certs(上图)来删除/销毁klass控制器中特定klass的所有证书

但是,我收到一条消息的例外:

"In RESCUE!"
"Cannot modify association 'Klass#certificates' because the source 
reflection class 'Certificate' is associated to 'Reservation' via :has_one."

我(还尝试将预订类更改为“has_many:certificates”,然后错误是...

"In RESCUE!"
"Cannot modify association 'Klass#certificates' because the source reflection
 class 'Certificate' is associated to 'Reservation' via :has_many."

奇怪的是,我可以从控制台执行Klass.first.certificates,并检索第一个类中的证书,但是我不能在没有创建错误的情况下执行Klass.first.certificates.delete_all。我错过了什么吗?

这是唯一的方法..

Klass.first.reservations.each do |res|
  res.certificate.destroy
end

感谢您的帮助。

1 个答案:

答案 0 :(得分:4)

RoR docs对此有明确的解释(仅对TLDR读取粗体):

  

从关联中删除

     

什么被删除?

     

这里有一个潜在的陷阱:has_and_belongs_to_many和   has_many:通过关联在连接表中有记录,以及   相关记录。所以当我们调用其中一种删除方法时,   究竟应该删除什么?

     

答案是假设关联上的删除是   关于删除所有者和相关联之间的链接   对象,而不一定是关联对象本身。   所以使用has_and_belongs_to_many和has_many:through,加入   记录将被删除,但相关记录将不会被删除。

     

如果您考虑一下,这是有道理的:如果您打电话   post.tags.delete(Tag.find_by(姓名:&#39;食物&#39;))你会想要'食物'   标签要从帖子中取消链接,而不是标签本身   从数据库中删除。

     

然而,有些例子表明这种策略没有意义。   例如,假设一个人有很多项目,每个项目都有   很多任务。如果我们删除了一个人的任务,我们可能会   不希望删除项目。在这种情况下,删除   方法实际上不会起作用:它只能在关联时使用   连接模型是belongs_to。在其他情况下,您是期望的   直接在相关记录或   :通过协会。

     

对于常规的has_many,没有区别   “关联记录”和“链接”,因此只有一个选择   什么被删除。

     

使用has_and_belongs_to_many和has_many:通过,如果你想   删除相关记录本身,你可以随时做一些事情   沿着person.tasks.each(&amp;:destroy)的路线。

所以你可以这样做:

self.certificates.each(&:destroy)