Ruby on rails 向哈希中添加未知类型的数据

Ruby on rails 向哈希中添加未知类型的数据,ruby-on-rails,ruby,Ruby On Rails,Ruby,Ruby似乎是一种特别适合解决这个问题的语言,但我并没有找到一种优雅的方法。我想要的是一个方法,该方法将接受一个值并将其添加到散列中,就像这样,如果密钥已经存在,则对如何添加该值有具体要求: 将“foo”添加到:键1 {:key1 => 'foo'} {:key1=> 'foobar'} 将“条”添加到:键1 {:key1 => 'foo'} {:key1=> 'foobar'} 将['foo']添加到:键2 {:key2 = ['foo']} 将['bar']

Ruby似乎是一种特别适合解决这个问题的语言,但我并没有找到一种优雅的方法。我想要的是一个方法,该方法将接受一个值并将其添加到散列中,就像这样,如果密钥已经存在,则对如何添加该值有具体要求:

将“foo”添加到:键1

{:key1 => 'foo'}
{:key1=> 'foobar'}
将“条”添加到:键1

{:key1 => 'foo'}
{:key1=> 'foobar'}
将['foo']添加到:键2

{:key2 = ['foo']}
将['bar']添加到:键2

{:key2 => [['foo'], ['bar']]
将{:k1=>'foo'}添加到:key3

{:key3 => {:k1 => 'foo'}}
将{:k2=>'bar'}添加到:key3

{:key3 => {:k1 => 'foo', :k2 => 'bar'}}

现在我可以这样做,但它看起来很邋遢,不像惯用的Ruby。做这件事的好方法是什么?

要使它更像Ruby,您可能需要扩展Hash类以全面提供此类功能,或者为此目的创建自己的子类。例如:

class FancyHash < Hash
  def add(key, value)
    case (self[key])
    when nil
      self[key] = value
    when Array
      self[key] = [ self[key], value ]
    when Hash
      self[key].merge!(value)
    else
      raise "Adding value to unsupported #{self[key].class} structure"
    end
  end
end
class FancyHash
这将取决于您对“添加”含义的准确解释,因为您的示例看起来确实有些简单,并且没有解决将哈希添加到预先存在的数组中时会发生什么


其思想是定义一个处理程序,该处理程序可以容纳尽可能多的合理可能性,如果无法管理,则抛出一个异常。

为了使它更像Ruby,您可能希望扩展Hash类以全面提供此类功能,或者为此目的创建自己的子类。例如:

class FancyHash < Hash
  def add(key, value)
    case (self[key])
    when nil
      self[key] = value
    when Array
      self[key] = [ self[key], value ]
    when Hash
      self[key].merge!(value)
    else
      raise "Adding value to unsupported #{self[key].class} structure"
    end
  end
end
class FancyHash
这将取决于您对“添加”含义的准确解释,因为您的示例看起来确实有些简单,并且没有解决将哈希添加到预先存在的数组中时会发生什么


其思想是定义一个处理程序,该处理程序可容纳尽可能多的合理可能性,如果无法管理,则抛出异常。

如果要利用oop的多态性功能,您可能需要执行以下操作:

class Object; def add_value v; v end end
class String; def add_value v; self+v end end  # or concat(v) for destructive
class Array; def add_value v; [self, v] end end # or replace([self.dup, v]) for destructive
class Hash; def add_value v; merge(v) end end  # or merge!(v) for destructive

class Hash
  def add k, v; self[k] = self[k].add_value(v) end
end

如果要利用oop的多态特性,您可能需要执行以下操作:

class Object; def add_value v; v end end
class String; def add_value v; self+v end end  # or concat(v) for destructive
class Array; def add_value v; [self, v] end end # or replace([self.dup, v]) for destructive
class Hash; def add_value v; merge(v) end end  # or merge!(v) for destructive

class Hash
  def add k, v; self[k] = self[k].add_value(v) end
end

并不是说我完全确定您在这里要做什么,而是为什么数组部分不是
{:key2=>['foo','bar']}
?如果您刚刚定义了#+on Hash to do#merge,您可以使用它。def添加(h、k、v);h[k]?h[k]+=v:h[k]=v;endIt不是一个很好的例子,但我正在jsut展示它必须是一个数组数组。我并不完全确定您在这里要做什么,但为什么数组部分不是
{:key2=>['foo','bar']}
?如果您刚刚定义了#+on Hash来进行#merge,您可以使用它。def添加(h、k、v);h[k]?h[k]+=v:h[k]=v;endIt不是一个很好的例子,但我正在jsut展示它必须是一个数组数组。这些例子可能过于简单,但都是我需要的。顺便说一句,这是离题的,但如果您要扩展内置类,这将在Rails项目中放在哪里?您通常会将它们放在lib目录中。实际上,最终会将其放在我的config/initializers目录中。需要在加载我的任何代码之前加载吗?
config/initializers
对于小的“扩展”脚本来说是一个很好的地方,但是如果它们增长到几十行以上,请将初始化器作为一个钩子来加载完整的
lib/
托管库。这些示例可能过于简单,但这正是我所需要的。顺便说一句,这是离题的,但如果您要扩展内置类,这将在Rails项目中放在哪里?您通常会将它们放在lib目录中。实际上,最终会将其放在我的config/initializers目录中。需要在我的任何代码加载之前加载吗?
config/initializers
对于小的“扩展”脚本来说是一个很好的地方,但是如果它们增长到几十行以上,请将初始化器作为一个钩子来加载完整的
lib/
托管库。