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

RFC*_*337 7 ruby-on-rails ruby-on-rails-3.2 rails-activerecord

我很难获得updated_at专栏来更新赌场模型,通过CasinoAmenity提供has_many设施.添加便利设施时,赌场的updated_at列会正确更新,但在删除时则不会.

这是我的(简化)模型:

casino.rb

class Casino < ActiveRecord::Base
  has_many :amenity_casino, :dependent => :destroy
  has_many :amenities, :through => :amenity_casino
end
Run Code Online (Sandbox Code Playgroud)

amenity_casino.rb

class AmenityCasino < ActiveRecord::Base
  belongs_to :casino, :touch => true
  belongs_to :amenity, :touch => true
end
Run Code Online (Sandbox Code Playgroud)

amenity.rb

class Amenity < ActiveRecord::Base
  has_many :amenity_casinos, :dependent => :destroy
  has_many :casinos, :through => :amenity_casinos
end
Run Code Online (Sandbox Code Playgroud)

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

> Casino.find(5).updated_at
=> Wed, 30 Jan 2013 00:30:04 UTC +00:00
Run Code Online (Sandbox Code Playgroud)

为赌场添加便利设施.

> 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">]
Run Code Online (Sandbox Code Playgroud)

确认关联已保存到数据库中

> 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">]
Run Code Online (Sandbox Code Playgroud)

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

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

现在让我们从赌场中移除这种舒适性.

> Casino.find(5).amenities = []
=> []
Run Code Online (Sandbox Code Playgroud)

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

> Casino.find(5).amenities
=> []
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Rails版本是3.2.11

Chr*_*erg 9

首先,你amenity_casinoCasino模型的两个地方的末尾错过了一个's' .

应该是这样的:

class Casino < ActiveRecord::Base
  has_many :amenity_casinos, :dependent => :destroy
  has_many :amenities, :through => :amenity_casinos
end
Run Code Online (Sandbox Code Playgroud)

但这并不能解决问题.参考这个(有些陈旧的)SO答案,看起来问题是连接表条目被删除,没有被破坏,并且删除不会触发该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 }
Run Code Online (Sandbox Code Playgroud)

我测试了这个,它似乎工作:

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
Run Code Online (Sandbox Code Playgroud)

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