有没有办法访问 Ruby 中的方法参数?

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

So what I am looking for way to get all arguments passed to method, without listing each one. Since this is Ruby I assume there is a way :) if it was java I would just list them :)

产出将是:

Method has failed, here are all method arguments {"Mario", "Super", 40, true, true}
72298 次浏览

解决这个问题的方法之一是:

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

这是个有趣的问题。也许用 Local _ variable 局部变量?但肯定有别的办法,而不是用 eval。我正在查看内核 医生

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

Before I go further, you're passing too many arguments into foo. It looks like all of those arguments are attributes on a Model, correct? You should really be passing the object itself. End of speech.

你可以使用“ splat”参数。它把所有东西都放到一个数组中。它看起来像:

def foo(*bar)
...
log.error "Error with arguments #{bar.joins(', ')}"
end

如果要更改方法签名,可以这样做:

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

In this case, interpolated args or opts.values will be an array, but you can join if on comma. Cheers

In Ruby 1.9.2 and later you can use the parameters method on a method to get the list of parameters for that method. This will return a list of pairs indicating the name of the parameter and whether it is required.

例如:。

如果你愿意的话

def foo(x, y)
end

那么

method(:foo).parameters # => [[:req, :x], [:req, :y]]

您可以使用特殊变量 __method__来获取当前方法的名称。因此在一个方法中,它的参数的名称可以通过

args = method(__method__).parameters.map { |arg| arg[1].to_s }

You could then display the name and value of each parameter with

logger.error "Method failed with " + args.map { |arg| "#{arg} = #{eval arg}" }.join(', ')

Note: since this answer was originally written, in current versions of Ruby eval can no longer be called with a symbol. To address this, an explicit to_s has been added when building the list of parameter names i.e. parameters.map { |arg| arg[1].to_s }

看起来这个问题想要达到的效果可以通过我刚刚发布的一个 gem https://github.com/ericbeland/exception_details来实现。它将列出获救异常中的局部变量和值(以及实例变量)。也许值得一看。

您可以定义一个常量,例如:

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)

由于 Ruby 2.1,您可以使用 Local _ variable _ get读取任何局部变量的值,包括方法参数(参数)。由于这一点,你可以改进的 接受的答案,以避免 邪恶评估。

def foo(x, y)
method(__method__).parameters.map do |_, name|
binding.local_variable_get(name)
end
end


foo(1, 2)  # => 1, 2

这可能会有帮助。

  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

If you need arguments as a Hash, and you don't want to pollute method's body with tricky extraction of parameters, use this:

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

If the function is inside some class then you can do something like this:

class Car
def drive(speed)
end
end


car = Car.new
method = car.method(:drive)


p method.parameters #=> [[:req, :speed]]