hash ['key']到Ruby中的hash.key

时间:2009-11-18 02:51:03

标签: ruby activerecord hash

我有一个哈希

foo = {'bar'=>'baz'}

我想致电foo.bar #=> 'baz'

我的动机是将activerecord查询重写为原始sql查询(使用Model#find_by_sql)。这将返回一个带有SELECT子句值作为键的哈希。但是,我现有的代码依赖于object.method点表示法。我想做最小的代码重写。感谢。

编辑:看来Lua有这个功能:

point = { x = 10, y = 20 }   -- Create new table
print(point["x"])            -- Prints 10
print(point.x)               -- Has exactly the same meaning as line above

5 个答案:

答案 0 :(得分:81)

>> require 'ostruct'
=> []
>> foo = {'bar'=>'baz'}
=> {"bar"=>"baz"}
>> foo_obj = OpenStruct.new foo
=> #<OpenStruct bar="baz">
>> foo_obj.bar
=> "baz"
>>

答案 1 :(得分:35)

您要找的是OpenStruct。它是标准库的一部分。

答案 2 :(得分:22)

一个好的解决方案:

class Hash
  def method_missing(method, *opts)
    m = method.to_s
    if self.has_key?(m)
      return self[m]
    elsif self.has_key?(m.to_sym)
      return self[m.to_sym]
    end
    super
  end
end

注意:此实现只有一个已知错误:

x = { 'test' => 'aValue', :test => 'bar'}
x.test # => 'aValue'

如果您更喜欢符号查找而不是字符串查找,那么请交换两个“if”条件

答案 3 :(得分:6)

不是将所有内容复制到散列中,而是可以向Hash添加一些行为来进行查找。

如果添加此定义,则扩展Hash以将所有未知方法作为哈希查找处理:

class Hash
  def method_missing(n)
    self[n.to_s]
  end
end

请记住,这意味着如果您在哈希上调用错误的方法,您将永远不会看到错误 - 您将获得相应的哈希查找将返回的任何内容。

您可以通过仅将方法置于特定哈希 - 或者根据需要添加多个哈希值来大大减少调试问题:

a={'foo'=>5, 'goo'=>6}
def a.method_missing(n)
   self[n.to_s]
end

另一个观察是,当系统调用method_missing时,它会给你一个Symbol参数。我的代码将其转换为String。如果您的哈希键不是字符串,则此代码将永远不会返回这些值 - 如果您使用符号而非字符串键入,只需将n替换为上面的n.to_s

答案 4 :(得分:4)

这有一些宝石。这是我最近的宝石,hash_dot,还有一些我在RubyGems上发布的类似名字的宝石,包括dot_hash

HashDot允许使用点符号语法,同时仍解决@avdi解决的NoMethodErrors问题。它比使用OpenStruct创建的对象更快,更易遍历。

require 'hash_dot'
a = {b: {c: {d: 1}}}.to_dot
a.b.c.d => 1

require 'open_struct'
os = OpenStruct.new(a)
os.b => {c: {d: 1}}
os.b.c.d => NoMethodError

当调用非方法时,它还会保持预期的行为。

a.non_method => NoMethodError

请随时向HashDot提交改进或错误。