Ruby和ROR的新手并且每天都喜欢它,所以这是我的问题,因为我不知道如何谷歌它(我已经尝试过:))
我们有方法
def foo(first_name, last_name, age, sex, is_plumber)
# some code
# error happens here
logger.error "Method has failed, here are all method arguments #{SOMETHING}"
end
所以我正在寻找将所有参数传递给方法的方法,而不是列出每个参数。因为这是Ruby我假设有一种方法:)如果它是java我只会列出它们:)
输出将是:
Method has failed, here are all method arguments {"Mario", "Super", 40, true, true}
答案 0 :(得分:144)
在Ruby 1.9.2及更高版本中,您可以在方法上使用parameters
方法来获取该方法的参数列表。这将返回一个对列表,指示参数的名称以及是否需要它。
e.g。
如果你这样做
def foo(x, y)
end
然后
method(:foo).parameters # => [[:req, :x], [:req, :y]]
您可以使用特殊变量__method__
来获取当前方法的名称。因此,在方法中,可以通过
args = method(__method__).parameters.map { |arg| arg[1].to_s }
然后,您可以使用
显示每个参数的名称和值logger.error "Method failed with " + args.map { |arg| "#{arg} = #{eval arg}" }.join(', ')
注意:,因为最初编写此答案,因此无法再使用符号调用当前版本的Ruby eval
。为解决此问题,在构建参数名称列表时添加了显式to_s
,即parameters.map { |arg| arg[1].to_s }
答案 1 :(得分:45)
从Ruby 2.1开始,您可以使用binding.local_variable_get来读取任何局部变量的值,包括方法参数(参数)。多亏了你,你可以改进accepted answer以避免 evil eval。
def foo(x, y)
method(__method__).parameters.map do |_, name|
binding.local_variable_get(name)
end
end
foo(1, 2) # => 1, 2
答案 2 :(得分:16)
处理此问题的一种方法是:
def foo(*args)
first_name, last_name, age, sex, is_plumber = *args
# some code
# error happens here
logger.error "Method has failed, here are all method arguments #{args.inspect}"
end
答案 3 :(得分:6)
这是一个有趣的问题。也许使用local_variables?但除了使用eval之外,必须有其他方法。我正在查看内核doc
class Test
def method(first, last)
local_variables.each do |var|
puts eval var.to_s
end
end
end
Test.new().method("aaa", 1) # outputs "aaa", 1
答案 4 :(得分:5)
def foo(x, y)
args(binding)
end
def args(callers_binding)
callers_name = caller[0][/`.*'/][1..-2]
parameters = method(callers_name).parameters
parameters.map { |_, arg_name|
callers_binding.local_variable_get(arg_name)
}
end
答案 5 :(得分:2)
在我走得更远之前,你向foo传递了太多的论据。看起来所有这些参数都是Model上的属性,对吗?你应该真正传递对象本身。演讲结束。
您可以使用“splat”参数。它把所有东西推到一个阵列中。它看起来像是:
def foo(*bar)
...
log.error "Error with arguments #{bar.joins(', ')}"
end
答案 6 :(得分:2)
如果要更改方法签名,可以执行以下操作:
def foo(*args)
# some code
# error happens here
logger.error "Method has failed, here are all method arguments #{args}"
end
或者:
def foo(opts={})
# some code
# error happens here
logger.error "Method has failed, here are all method arguments #{opts.values}"
end
在这种情况下,插值args
或opts.values
将是一个数组,但如果使用逗号,则可以join
。干杯
答案 7 :(得分:2)
似乎这个问题试图通过我刚刚发布的gem https://github.com/ericbeland/exception_details来完成。它将列出来自获救异常的局部变量和值(和实例变量)。可能值得一看......
答案 8 :(得分:2)
您可以定义一个常量,例如:
ARGS_TO_HASH = "method(__method__).parameters.map { |arg| arg[1].to_s }.map { |arg| { arg.to_sym => eval(arg) } }.reduce Hash.new, :merge"
并在您的代码中使用它,如:
args = eval(ARGS_TO_HASH)
another_method_that_takes_the_same_arguments(**args)
答案 9 :(得分:1)
如果您需要参数作为哈希,并且您不想通过棘手的参数提取来污染方法体,请使用:
def mymethod(firstarg, kw_arg1:, kw_arg2: :default)
args = MethodArguments.(binding) # All arguments are in `args` hash now
...
end
只需将此类添加到您的项目中:
class MethodArguments
def self.call(ext_binding)
raise ArgumentError, "Binding expected, #{ext_binding.class.name} given" unless ext_binding.is_a?(Binding)
method_name = ext_binding.eval("__method__")
ext_binding.receiver.method(method_name).parameters.map do |_, name|
[name, ext_binding.local_variable_get(name)]
end.to_h
end
end
答案 10 :(得分:0)
如果函数在某个类中,则可以执行以下操作:
class Car
def drive(speed)
end
end
car = Car.new
method = car.method(:drive)
p method.parameters #=> [[:req, :speed]]