Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 辅助方法的Rails实现_Ruby On Rails_Ruby - Fatal编程技术网

Ruby on rails 辅助方法的Rails实现

Ruby on rails 辅助方法的Rails实现,ruby-on-rails,ruby,Ruby On Rails,Ruby,我有一个helper方法,它执行昂贵的计算并返回一个哈希值,这个哈希值在我的整个应用程序生命周期内是不变的(这意味着它只能在重新部署后更改),而且它也不接受任何参数 为了提高性能,我希望能够“缓存”生成的Hash 我不想为此使用Rails缓存,因为我想避免对memcached的额外访问,也不想将字符串反序列化为哈希的开销 我的第一个想法是将得到的散列分配给一个常量,并对其调用.freeze。但是helper是一个实例方法,常量存在于类中,我不得不做这个非常粗糙的解决方案: module FooH

我有一个helper方法,它执行昂贵的计算并返回一个
哈希值
,这个哈希值在我的整个应用程序生命周期内是不变的(这意味着它只能在重新部署后更改),而且它也不接受任何参数

为了提高性能,我希望能够“缓存”生成的
Hash

我不想为此使用Rails缓存,因为我想避免对memcached的额外访问,也不想将字符串反序列化为哈希的开销

我的第一个想法是将得到的散列分配给一个常量,并对其调用
.freeze
。但是helper是一个实例方法,常量存在于类中,我不得不做这个非常粗糙的解决方案:

module FooHelper

def expensive_calculation_method
  resulting_hash
end

EXPENSIVE_CALCULATION_CONSTANT = Class.new.extend(self).expensive_calculation_method.freeze
这是因为helper方法是一个实例方法,helper是一个模块(这导致了伪类extend,因此我可以调用实例方法),并且我还必须在实例方法之后声明常量(如果我在
模块fooheloper
之后立即声明它,我会得到一个
未定义的方法“昂贵的计算方法”

第二个想法是使用记忆,但至少对于Rails控制器来说,记忆是一个变量在单个请求的生命周期中的持久性,因此只有在单个请求中多次重用一个变量时,它才有价值,这不是我的情况,但同时助手是模块,而不是类举个例子,现在我不知道该怎么办


如何缓存该散列,或以一种在请求中持续存在的方式对其进行记忆?

如果要在启动时缓存某个痛苦操作的结果:

module MyExpensiveOperation
  COMPUTED_RESULT = OtherModule.expensive_operation

  def self.cached
    COMPUTED_RESULT
  end
end
只要确保模块以某种方式加载,否则它不会启动。如果需要,您可以在
environment.rb
或作为
config/initializer
类型文件强制-
require
该模块

如果要延迟加载,基本原则相同:

module MyExpensiveOperation
  def self.cached
    return @cached if (defined?(@cached))

    @cached = OtherModule.expensive_operation
  end
end

这将处理由于任何原因返回
nil
false
的操作。它将运行一次,并且仅运行一次,除非有多个线程同时触发它。如果是这种情况,可以通过自动锁定使模块并发性感知。

根据您的注释,这只会在ap时更改应用程序启动,因此将其置于初始值设定项中即可

# config/initializers/expensive_thing.rb
$EXENSIVE_THING_GLOBAL = expensive_calculation

# or
EXPENSIVE_THING_CONSTANT = expensive_calculation

# or

Rails.application.config.expensive_thing = expensive_calcualatioin

模块中声明的常量应在模块使用或导入时随
include
一起使用的任何上下文中都可用。您想在启动时还是在第一次使用时使用它?您在这里描述的是视图缓存的确切用例。您能解释一下为什么不想使用Rails缓存吗?@Danielwestndorf-生成的散列有数百个键,它将用于应用程序的一个非常关键的部分,因此我希望它的性能尽可能好。例如,如果我使用memcached,散列将被序列化并保存为字符串,每次都需要对其进行解析(反序列化)请记住:这是一个固定的哈希,除非在部署之后,否则它不会改变,所以我不明白为什么我需要将本机ruby哈希序列化为字符串并保存到memcached中。@tadman我希望在启动时受到影响。从Memca来回传送这样的数据ched或Redis非常轻松。将其放入常量也应该可以。不清楚您的具体问题是什么。在第一个示例中,直接调用常量(
MyExpensiveOperation::COMPUTED_RESULT
)与调用类方法(
MyExpensiveOperation.cached
)有什么区别?我倾向于避免分享“内部信息”在类或模块之间,它会创建不必要的相互依赖关系。通过使用类似于“缓存”的方法,这意味着您可以更改“计算结果”的定义方式,以及它包含的内容,而不必破坏所有相关的代码。
缓存的
可以更新以保持兼容性。常量没有这种能力为了适应,它要么是正确的格式,要么不是。