Ruby - 动态定义 class 级别变量
Ruby - defining class level variable dynamically
我是 ruby 的新手,想知道这是否可行。假设我有一个像这样的不同块的文件
fruits[tomato=1,orange=2]
greens[peas=2,potato=3]
我已经解析了这个文件并将其存储到这样的散列中
{"fruits"=>{"tomato"=>"1", "orange"=>"2"}, "greens"=>{"potato" =>"3", "peas"=>"2"}}
而且我也知道如何访问散列的不同部分。但是假设如果想把它做成这样
fruits.tomato # 1
fruits.orange # 2
(Like an object with tomato and orange being its variables)
这里的问题是假设我不知道该文件是否将包含水果和蔬菜,它可能包含一个名为肉类的不同组。我知道如果我将所有内容插入到一个散列中,键作为组名,值将是另一个散列,这个动态问题就可以解决。但这可以用我上面提供的 fruit.tomato 或 fruits.orange 的例子来完成吗(可能是通过在 class 中声明它,但我不确定如何动态添加 class 变量在 ruby 中,或者如果这是可能的,因为我是该语言的新手)。
我花了很多时间制作这样的程序,以帮助加快 API 的开发。我最终写了一个 gem 来对象化原始 JSON(无耻的插件:ClassyJSON)。
也就是说,我认为您的用例很适合 OpenStruct。我将我的代码限制为您的示例和您想要的结果,但它可能看起来像这样:
require 'ostruct'
hash = {"fruits"=>{"tomato"=>"1", "orange"=>"2"}, "greens"=>{"potato"=>"3", "peas"=>"2"}}
structs = []
hash.each do |k, v|
if v.is_a? Hash
obj = OpenStruct.new({k => OpenStruct.new(v)})
end
structs << obj
end
这里我们构建了一些 OpenStruct 对象,并且可以按照您的概述访问它们的值:
[1] pry(main)> structs
=> [#<OpenStruct fruits=#<OpenStruct tomato="1", orange="2">>, #<OpenStruct greens=#<OpenStruct potato="3", peas="2">>]
[2] pry(main)> structs.first
=> #<OpenStruct fruits=#<OpenStruct tomato="1", orange="2">>
[3] pry(main)> structs.first.fruits
=> #<OpenStruct tomato="1", orange="2">
[4] pry(main)> structs.first.fruits.tomato
=> "1"
def add_accessor_method(name, ref)
define_singleton_method name do
return ref
end
end
我找到了这个解决方案,它将在解析文件本身的过程中为我创建一个访问器方法。所以我以后不必使用 OpenStruct 将我的散列转换为具有不同访问器方法的对象。 (我确信引擎盖下的 OpenStruct 正在这样做)
我是 ruby 的新手,想知道这是否可行。假设我有一个像这样的不同块的文件
fruits[tomato=1,orange=2]
greens[peas=2,potato=3]
我已经解析了这个文件并将其存储到这样的散列中
{"fruits"=>{"tomato"=>"1", "orange"=>"2"}, "greens"=>{"potato" =>"3", "peas"=>"2"}}
而且我也知道如何访问散列的不同部分。但是假设如果想把它做成这样
fruits.tomato # 1
fruits.orange # 2
(Like an object with tomato and orange being its variables)
这里的问题是假设我不知道该文件是否将包含水果和蔬菜,它可能包含一个名为肉类的不同组。我知道如果我将所有内容插入到一个散列中,键作为组名,值将是另一个散列,这个动态问题就可以解决。但这可以用我上面提供的 fruit.tomato 或 fruits.orange 的例子来完成吗(可能是通过在 class 中声明它,但我不确定如何动态添加 class 变量在 ruby 中,或者如果这是可能的,因为我是该语言的新手)。
我花了很多时间制作这样的程序,以帮助加快 API 的开发。我最终写了一个 gem 来对象化原始 JSON(无耻的插件:ClassyJSON)。
也就是说,我认为您的用例很适合 OpenStruct。我将我的代码限制为您的示例和您想要的结果,但它可能看起来像这样:
require 'ostruct'
hash = {"fruits"=>{"tomato"=>"1", "orange"=>"2"}, "greens"=>{"potato"=>"3", "peas"=>"2"}}
structs = []
hash.each do |k, v|
if v.is_a? Hash
obj = OpenStruct.new({k => OpenStruct.new(v)})
end
structs << obj
end
这里我们构建了一些 OpenStruct 对象,并且可以按照您的概述访问它们的值:
[1] pry(main)> structs
=> [#<OpenStruct fruits=#<OpenStruct tomato="1", orange="2">>, #<OpenStruct greens=#<OpenStruct potato="3", peas="2">>]
[2] pry(main)> structs.first
=> #<OpenStruct fruits=#<OpenStruct tomato="1", orange="2">>
[3] pry(main)> structs.first.fruits
=> #<OpenStruct tomato="1", orange="2">
[4] pry(main)> structs.first.fruits.tomato
=> "1"
def add_accessor_method(name, ref)
define_singleton_method name do
return ref
end
end
我找到了这个解决方案,它将在解析文件本身的过程中为我创建一个访问器方法。所以我以后不必使用 OpenStruct 将我的散列转换为具有不同访问器方法的对象。 (我确信引擎盖下的 OpenStruct 正在这样做)