我可以在Ruby中以哈希的形式访问方法的关键字参数吗?

2uluyalo  于 11个月前  发布在  Ruby
关注(0)|答案(2)|浏览(87)

我有几个带有关键字参数的方法,这些方法用相同的参数调用 * 其他方法 *。目前我必须手动传递每个参数。有没有一种方法可以访问所有的关键字参数作为哈希,并直接向下传递?
示例代码-

def method1(arg1:, arg2:)
  # do something specific to method1
  result = executor1(arg1: arg1, arg2: arg2)
  # do something with result
end

def method2(arg3:, arg4:, arg5:, arg6:)
  # do something specific to method2
  result = executor2(arg3: arg3, arg4: arg4, arg5: arg5, arg6: arg6)
  # do something with result
end

def method3(arg7:)
  # do something specific to method3
  result = executor3(arg7: arg7)
  # do something with result
end

字符串
我能做点什么把密码改成-

def method1(arg1:, arg2:)
  # do something specific to method1
  args = method1_args_as_a_hash
  result = executor1(args)
  # do something with result
end

def method2(arg3:, arg4:, arg5:, arg6:)
  # do something specific to method2
  args = method2_args_as_a_hash
  result = executor2(args)
  # do something with result
end

def method3(arg7:)
  # do something specific to method3
  args = method3_args_as_a_hash
  result = executor3(args)
  # do something with result
end


上下文-这些关键字参数的数量在我的代码库中已经增长得相当大,并按原样传递它们(或有时略有修改)executorX方法使代码文件变得太大,难以阅读。不幸的是,我无法更改methodX方法的签名,因为我无法访问使用它们的每个代码库,也不能冒险破坏它们的任何消费者。我完全控制它们的逻辑和executorX方法。我的目标是重构这段代码,减少行数,提高可读性。
谢谢你,谢谢

ktca8awb

ktca8awb1#

当你总是想把所有的关键字参数从方法调用传递到嵌套的方法调用时,那么使用双splat运算符(**)应该对你有用:

def method1(**)
  # do something specific to method1
  result = executor1(**)
  # do something with result
end

字符串

2q5ifsrm

2q5ifsrm2#

这是可以做到的,但相当笨重。
您可以使用method方法对方法进行inspect并获取其签名,然后使用binding获取具有相同名称的局部变量:

def foo(bar:, baz:)
  params = method(__method__).parameters # [[:keyreq, :bar], [:keyreq, :baz]]
  params.each_with_object({}) do |(_, name), hash|
    hash[name] = binding.local_variable_get(name) 
  end
end

个字符
__method__是一个特殊的魔术方法,包含当前方法的名称。
只是要注意,如果你想避免在你的代码库中重复这个操作,你需要将绑定对象传递给你的其他方法以及方法的名称。

module Collector
  # @param [Binding] context
  # @param [String|Symbol] method_name
  # @return [Hash] 
  def collect_arguments(context, method_name)
    params = context.reciever.method(method_name).parameters
    params.each_with_object({}) do |(_, name), hash|
      hash[name] = context.local_variable_get(name) 
    end
  end
end
class Thing
  include Collector

  def method1(arg1:, arg2:)
    # do something specific to method1
    args = collect_arguments(binding, __method__)
    result = executor1(**args)
    # do something with result
  end
end

的字符串

相关问题