gpt4 book ai didi

ruby-on-rails - 如何使用 Ruby 元编程向 Rails 模型添加回调?

转载 作者:数据小太阳 更新时间:2023-10-29 06:50:13 26 4
gpt4 key购买 nike

我写了一个简单的 Cacheable 模块,它使得在父模型中缓存聚合字段变得简单。该模块要求父对象为需要在父级缓存的每个字段实现 cacheable 方法和 calc_ 方法。

module Cacheable
def cache!(fields, *objects)
objects.each do |object|
if object.cacheable?
calc(fields, objects)
save!(objects)
end
end
end

def calc(fields, objects)
fields.each { |field| objects.each(&:"calc_#{field}") }
end

def save!(objects)
objects.each(&:save!)
end
end

我想向包含此模块的 ActiveRecord 模型添加回调。此方法要求模型实现需要缓存的父模型和字段名称的哈希。

def cachebacks(klass, parents)
[:after_save, :after_destroy].each do |callback|
self.send(callback, proc { cache!(CACHEABLE[klass], self.send(parents)) })
end
end

如果我使用以下方法手动添加两个回调,这种方法非常有效:

after_save proc { cache!(CACHEABLE[Quote], *quotes.all) }
after_destroy proc { cache!(CACHEABLE[Quote], *quotes.all) }

但是,当我尝试使用 cachebacks 方法将这些添加到回调中时,我收到以下错误。

cachebacks(Quote, "*quotes.all")

NoMethodError: undefined method `cachebacks' for #<Class:0x007fe7be3f2ae8>

如何将这些回调动态添加到类中?

最佳答案

这看起来是 ActiveSupport::Concern 的一个好案例.您可以稍微调整您的 cachebacks 方法,将其添加为包含类的类方法:

module Cacheable
extend ActiveSupport::Concern

module ClassMethods
def cachebacks(&block)
klass = self
[:after_save, :after_destroy].each do |callback|
self.send(callback, proc { cache!(CACHEABLE[klass], *klass.instance_eval(&block)) })
end
end
end

def cache!(fields, *objects)
# ...
end

# ...
end

使用方法:

class Example < ActiveRecord::Base
include Cacheable
cachebacks { all }
end

您传递给 cachebacks 的 block 将在调用它的类的上下文中执行。在此示例中,{ all } 等效于调用 Example.all 并将结果传递到您的 cache! 方法。


为了回答您在评论中的问题,Concern 封装了一个通用模式并在 Rails 中建立了一个约定。语法稍微优雅一些​​:

included do
# behaviors
end

# instead of

def self.included(base)
base.class_eval do
# behaviors
end
end

它还利用另一个约定来自动并正确地包含类和实例方法。如果您在名为 ClassMethodsInstanceMethods 的模块中命名这些方法(尽管如您所见,InstanceMethods 是可选的),那么您就完成了.

最后,它处理模块依赖性。该文档为此提供了一个很好的示例,但从本质上讲,它避免了包含类除了它实际感兴趣的模块之外还必须显式包含依赖模块。

关于ruby-on-rails - 如何使用 Ruby 元编程向 Rails 模型添加回调?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12084234/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com