【问题标题】:Referencing all of a collection of dependent objects objects引用所有依赖对象的集合
【发布时间】:2013-10-05 20:55:09
【问题描述】:

我有三个 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

感谢您的帮助。

【问题讨论】:

  • 如果在kill_certs 方法中调用certificates.each(&amp;:destroy) 而不是destroy_all 会发生什么?

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


【解决方案1】:

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

从关联中删除

什么会被删除?

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

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

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

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

与常规的 has_many 没有区别 “关联记录”和“链接”,所以只有一种选择 什么被删除。

使用 has_and_belongs_to_many 和 has_many :through,如果你想 自己删除关联记录,总能做点什么 按照 person.tasks.each(&:destroy).

所以你可以这样做:

self.certificates.each(&:destroy)

【讨论】:

  • 感谢您提供非常完整的答案以及文档链接!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-18
  • 1970-01-01
相关资源
最近更新 更多