如何在对象上调用方法名称的嵌套哈希?
例如,给定以下哈希:
hash = {:a => {:b => {:c => :d}}}
我想创建一个方法,给定上面的哈希,它具有以下等价物:
object.send(:a).send(:b).send(:c).send(:d)
我的想法是,我需要从未知的关联中获取特定属性(此方法未知,但程序员已知)。
我希望能够指定一个方法链来以嵌套哈希的形式检索该属性。例如:
hash = {:manufacturer => {:addresses => {:first => :postal_code}}}
car.execute_method_hash(hash)
=> 90210
答案 0 :(得分:11)
我使用数组而不是散列,因为散列允许不一致(如果(子)散列中有多个键会怎么样?)。
object = Thing.new
object.call_methods [:a, :b, :c, :d]
使用数组,以下工作:
# This is just a dummy class to allow introspection into what's happening
# Every method call returns self and puts the methods name.
class Thing
def method_missing(m, *args, &block)
puts m
self
end
end
# extend Object to introduce the call_methods method
class Object
def call_methods(methods)
methods.inject(self) do |obj, method|
obj.send method
end
end
end
在call_methods
中,我们在符号数组中使用inject
,以便我们将每个符号发送到前一个方法发送返回的方法执行结果。最后一次发送的结果由inject
自动返回。
答案 1 :(得分:1)
这是一种更简单的方法。
class Object
def your_method
attributes = %w(thingy another.sub_thingy such.attribute.many.method.wow)
object = Object.find(...)
all_the_things << attributes.map{ |attr| object.send_chain(attr.split('.')) }
end
def send_chain(methods)
methods.inject(self, :try)
end
end
答案 2 :(得分:0)
没有预定义的方法,但您可以为此定义自己的方法:
class Object
def send_chain(chain)
k = chain.keys.first
v = chain.fetch(k)
r = send(k)
if v.kind_of?(Hash)
r.send_chain(v)
else
r.send(v)
end
end
end
class A
def a
B.new
end
end
class B
def b
C.new
end
end
class C
def c
D.new
end
end
class D
def d
12345
end
end
chain = { a: { b: { c: :d } } }
a = A.new
puts a.send_chain(chain) # 12345
进行测试