我有一个游戏化应用程序有四种类型的点,所有这些类型的总和是用户的总点数,我希望能够sum
和scope
上该列,所以我认为我应该把它作为数据库中的一列。
scope :points_rank, -> { order(points: :desc) }
我使用before_save
添加所有四种point
类型并将其存储在points
中,但现在我正在使用对这些类型执行increment
的gem of points,因此当它更新这些值时,before_save
不会被调用,因此不会按预期更新points
值。
使用的是正确的ActiveRecord 回调而不是before_save
,或者我可以做些什么来保持列的更新。
答案 0 :(得分:1)
请尝试使用after_touch
回调。
after_touch
回调。
因此,每当点类型发生变化时,都应更新points
。
答案 1 :(得分:0)
首先,counter_culture
似乎是一种增强rails counter_cache功能的方法......
用于缓存关联上的所属对象的数量。例如,
comments_count
类中具有多个Post
实例的Comment
列将缓存每个帖子的现有注释数。
根据你的问题,可能可能不是你想要的。
好的,我明白了。您在User
模型中使用 points 来创建“缓存”列,该列可用于更广泛的应用程序功能。好的,这很酷......
-
然后,您的设置会看起来喜欢这个(您手动设置counter_cache
列,现在gem处理它):
#app/models/user.rb
class User < ActiveRecord::Base
counter_cache :points
end
#app/models/point.rb
class Point < ActiveRecord::Base
belongs_to :user, counter_cache: true
end
问题是当你更新 points 模型时,你需要能够更新用户模型中的“缓存”列,现在没有任何回调
使用正确的ActiveRecord回调代替before_save
是什么
我假设您在User
模型上调用 before_save (IE添加相关数据并放入 points 列?
如果是这样,你应该尝试在Point
模型上使用回调,可能是这样的:
#app/models/user.rb
class User < ActiveRecord::Base
has_many :points
end
#app/models/point.rb
class Point < ActiveRecord::Base
belongs_to :user, inverse_of: :points
after_commit :update_user
private
def update_user
if user?
user.update(points: x + y + z)
end
end
end
-
<强> Oberservers 强>
如果您遇到实际问题,可以查看ActiveRecord observers。
以下是我写的关于它的答案:Ruby On Rails Updating Heroku Dynamic Routes
这是否会在没有任何回调的情况下触发是另一回事,但我可以所说的是,它可以为您提供您可能无法访问的功能:
#config/application.rb (can be placed into dev or prod files if required)
config.active_record.observers = :point_observer
#app/models/point_observer.rb
class PointObserver < ActiveRecord::Observer
def before_save(point)
#logic here
end
end
测试这个的一个好方法是使用不同的方法(你必须使用rails-observers gem)。 IE:
#app/models/point_observer.rb
class PointObserver < ActiveRecord::Observer
def initialize(point)
#if this fires, happy days
end
end