您正在尝试做的事情有过早优化的味道。我建议在哈希中尽可能集中使用符号作为键和值。符号的内存效率很高,查找速度也很快,因为 Ruby 只会为给定的符号创建一个内存槽,有效地做你想做的事情。
您的示例结构可以使用符号重写:
config = {
:assets => {
:path => :'/assets',
:aliases => {
:'/assets/' => :'/assets/index.html',
:'/assets/index.htm' => :'/assets/index.html'
}
},
:api => {
:path => :'/auth/api',
:aliases => {
:'/auth/api/me' => :'/auth/api/whoami'
}
}
}
:'/assets/index.html'
,无论在哪里看到,总是指向同一个符号,不像字符串。
每当您需要访问期望字符串的值时,请to_s
对它执行 a 。添加值时,to_sym
对其执行 a 。
在幕后,您将在 Hash 中更有效地使用内存,并使用 Ruby 中最快的值查找。
现在,如果您使用哈希结构来配置您的应用程序,并且它被存储在磁盘上,您可以使用 YAML 节省一些空间,它支持其数据文件中的别名和锚点。在解析为 Ruby 对象后,它们不会在哈希内创建指针,但它们可以减小文件的大小。
编辑:
如果您需要动态定义配置,则为各种字符串的所有子部分创建变量,然后添加一个生成它的方法。以下是动态创建此类事物的基础知识:
require 'awesome_print'
def make_config(
assets = '/assets',
index_html = 'index.html',
auth_api = '/auth/api'
)
assets_index = File.join(assets, index_html)
{
:assets => {
:path => assets,
:aliases => {
assets + '/' => assets_index,
assets_index[0..-2] => assets_index
}
},
:api => {
:path => auth_api,
:aliases => {
File.join(auth_api, 'me') => File.join(auth_api, 'whoami')
}
}
}
end
ap make_config()
ap make_config(
'/new_assets',
['new','path','to','index.html'],
'/auth/new_api'
)
将生成什么:
{
:assets => {
:path => "/assets",
:aliases => {
"/assets/" => "/assets/index.html",
"/assets/index.htm" => "/assets/index.html"
}
},
:api => {
:path => "/auth/api",
:aliases => {
"/auth/api/me" => "/auth/api/whoami"
}
}
}
和:
{
:assets => {
:path => "/new_assets",
:aliases => {
"/new_assets/" => "/new_assets/new/path/to/index.html",
"/new_assets/new/path/to/index.htm" => "/new_assets/new/path/to/index.html"
}
},
:api => {
:path => "/auth/new_api",
:aliases => {
"/auth/new_api/me" => "/auth/new_api/whoami"
}
}
}
编辑:
复制值指针的另一种方法是创建返回所需信息的 lambda 或 proc。我认为它们就像是 C 或 Perl 中的函数指针,允许我们保留范围内变量的状态,或操作传入的值。这不是一个完美的解决方案,因为会发生变量范围,但它是该框的另一个工具:
lambda1 = lambda { 'bar' }
proc2 = Proc.new { |a,b| a + b }
proc3 = Proc.new { proc2.call(1,2) }
foo = {
:key1 => lambda1,
:key2 => proc2,
:key3 => proc2,
:key4 => proc3
}
foo[:key1].object_id # => 70222460767180
foo[:key2].object_id # => 70222460365960
foo[:key3].object_id # => 70222460365960
foo[:key4].object_id # => 70222460149600
foo[:key1].call # => "bar"
foo[:key2].call(1, 2) # => 3
foo[:key3].call(%w[a b]) # => "ab"
foo[:key4].call # => 3
有关 lambda 和 procs 的更多信息,请参阅“何时使用 lambda,何时使用 Proc.new? ”。