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 正在这样做)