删除has_many:通过关联不会更改模型的updated_at属性

时间:2013-01-30 01:51:12

标签: ruby-on-rails ruby-on-rails-3.2 rails-activerecord

我很难通过CasinoAmenity获取updated_at列以更新具有__设备的Casino模型。添加便利设施时,赌场的updated_at列会正确更新,但在删除时不会。

这是我的(简化)模型:

casino.rb

class Casino < ActiveRecord::Base
  has_many :amenity_casino, :dependent => :destroy
  has_many :amenities, :through => :amenity_casino
end

amenity_casino.rb

class AmenityCasino < ActiveRecord::Base
  belongs_to :casino, :touch => true
  belongs_to :amenity, :touch => true
end

amenity.rb

class Amenity < ActiveRecord::Base
  has_many :amenity_casinos, :dependent => :destroy
  has_many :casinos, :through => :amenity_casinos
end

现在到控制台。检查初始updated_at时间。

> Casino.find(5).updated_at
=> Wed, 30 Jan 2013 00:30:04 UTC +00:00

为赌场添加便利设施。

> Casino.find(5).amenities << Amenity.first
=> [#<Amenity id: 1, name: "asdf", weight: "", created_at: "2012-11-10 02:29:14", updated_at: "2013-01-30 01:29:14", description: "asdf">]

确认关联已保存到数据库

> Casino.find(5).amenities
=> [#<Amenity id: 1, name: "asdf", weight: "", created_at: "2012-11-10 02:29:14", updated_at: "2013-01-30 01:29:14", description: "asdf">]

我们可以看到该赌场的updated_at时间已经如预期的那样发生了变化。

> Casino.find(5).updated_at
=> Wed, 30 Jan 2013 01:29:14 UTC +00:00

现在让我们从赌场中删除这个便利设施。

> Casino.find(5).amenities = []
=> []

现在确保它能够很好地打击数据库

> Casino.find(5).amenities
=> []

现在让我们检查赌场的updated_at栏......

> Casino.find(5).updated_at
=> Wed, 30 Jan 2013 01:29:14 UTC +00:00

正如您所看到的,它与我们从赌场中移除舒适性之前的情况相同。我也尝试过在AmenityCasino上使用before_destroy过滤器来触摸赌场,但这似乎并没有成功。

我很想知道是否有人在这里有任何解决方案。如果重要,我正在使用ActiveAdmin管理所有内容。

Rails版本是3.2.11

2 个答案:

答案 0 :(得分:9)

首先,您在amenity_casino模型的两个位置Casino末尾错过了's'。

应该是这样的:

class Casino < ActiveRecord::Base
  has_many :amenity_casinos, :dependent => :destroy
  has_many :amenities, :through => :amenity_casinos
end
但是,这不会解决问题。参考this (somewhat old) SO answer,看起来问题是连接表条目被删除,没有被破坏,删除不会触发touch方法,因此updated_at不会更新。

要解决此问题,您可以为关联添加:after_remove选项,并在模型上传递proc touch

has_many :amenity_casinos, :dependent => :destroy
has_many :amenities, :through => :amenity_casinos,\
         :after_remove => proc { |a| a.touch }

我已经对此进行了测试,似乎有效:

Casino.find(5).updated_at
#=> Wed, 30 Jan 2013 03:21:29 UTC +00:00
Casino.find(5).amenities << Amenity.first
#=> [#<Amenity id: 1, name: nil, created_at: "2013-01-30 02:48:49", updated_at: "2013-01-30 03:25:23">]
Casino.find(5).amenities
#=> [#<Amenity id: 1, name: nil, created_at: "2013-01-30 02:48:49", updated_at: "2013-01-30 03:25:23">]
Casino.find(5).updated_at
#=> Wed, 30 Jan 2013 03:25:23 UTC +00:00
Casino.find(5).amenities = []
#=> []
Casino.find(5).updated_at
#=> Wed, 30 Jan 2013 03:27:33 UTC +00:00

您可以看到时间戳已更改。如果您希望在Amenity模型上更新updated_at属性,则必须对{{1}}模型执行相同的操作。

答案 1 :(得分:0)

在我说这个之前我必须注意到我不确定这在Rails 3.2中是否有效,但我确信它在Rails 4 +中有效

现在我知道这已被回答,但仅供将来参考,而不是

> Casino.find(5).amenities = []

您可以使用destroy_all方法来销毁所有join_model条记录和touch关联(如果您在示例中列出了该选项)并执行相应的回调destroy上的join_model的{​​{1}}(示例AmenityCasino

> Casino.find(5).amenities.destroy_all