在Ruby中hash 到hash.key
我有一个哈希
foo = {'bar'=>'baz'}
我想打电话给foo.bar #=> 'baz'
我的动机是将主动logging查询重写为原始sql查询(使用Model#find_by_sql)。 这将以SELECT子句值作为键返回一个散列。 但是,我现有的代码依赖于object.method点符号。 我想做最小的代码重写。 谢谢。
编辑:看来Lua有这个function:
point = { x = 10, y = 20 } -- Create new table print(point["x"]) -- Prints 10 print(point.x) -- Has exactly the same meaning as line above
>> require 'ostruct' => [] >> foo = {'bar'=>'baz'} => {"bar"=>"baz"} >> foo_obj = OpenStruct.new foo => #<OpenStruct bar="baz"> >> foo_obj.bar => "baz" >>
你在找什么叫做OpenStruct 。 这是标准库的一部分。
一个好的解决scheme
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
注意:这个实现只有一个已知的bug:
x = { 'test' => 'aValue', :test => 'bar'} x.test # => 'aValue'
如果您更喜欢符号查找而不是string查找,则交换两个“if”条件
而不是复制所有的东西哈希,你可以添加一些行为哈希来做查找。
如果你添加这个定义,你扩展哈希以处理所有未知的方法作为哈希查找:
class Hash def method_missing(n) self[n.to_s] end end
请记住,这意味着如果你在hash上调用了错误的方法,你将不会看到错误 – 你只要得到相应的hash查询就会返回。
只需将该方法放在特定的散列函数上,就可以大大减lessdebugging问题,或者根据需要进行多次散列:
a={'foo'=>5, 'goo'=>6} def a.method_missing(n) self[n.to_s] end
另一种观察是,当method_missing
被系统调用时,它会给你一个Symbol
参数。 我的代码转换成一个String
。 如果您的散列键不是string,这个代码将永远不会返回这些值 – 如果您使用符号而不是string键入,只需将n
replace为上面的n.to_s
。
这有几个gem。 有我最近的gem, hash_dot和其他一些我在RubyGems上发布的类似名字的gem,包括dot_hash 。
HashDot允许使用点符号语法,同时仍然解决有关由@avdi处理的NoMethodErrors问题。 它比使用OpenStruct创build的对象更快,更易于穿越。
require 'hash_dot' a = {b: {c: {d: 1}}}.to_dot abcd => 1 require 'open_struct' os = OpenStruct.new(a) os.b => {c: {d: 1}} os.bcd => NoMethodError
当非方法被调用时,它也保持预期的行为。
a.non_method => NoMethodError
请随时向HashDot提交改进或错误。