8

我很难让 updated_at 列更新具有通过 CasinoAmenity 提供的多种便利设施的赌场模型。赌场的 updated_at 列在添加设施时会正确更新,但在删除它们时不会。

这是我的(简化的)模型:

赌场.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

舒适度.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

4

2 回答 2

10

amenity_casino首先,您在模型的两个位置的末尾缺少一个“s” Casino

应该是这样的:

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

不过,这并不能解决这里的问题。参考this (some 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更新该模型的属性,则必须对模型执行相同的操作。

于 2013-01-30T02:51:51.167 回答
0

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

现在我知道这已得到解答,但仅供将来参考,而不是

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

您可以使用destroy_all将销毁所有join_model记录和touch关联的方法(如果您在示例中列出了该选项)并destroyjoin_model(在示例中)执行适当的回调(用于AmenityCasino

> Casino.find(5).amenities.destroy_all
于 2017-12-14T10:21:47.907 回答