Ruby에서 메서드 인수에 액세스하는 방법이 있습니까?
Ruby와 ROR을 처음 접하고 매일 그것을 좋아하므로 Google을 어떻게하는지 몰랐기 때문에 여기에 내 질문이 있습니다 (그리고 시도했습니다 :))
우리는 방법이 있습니다
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이기 때문에 나는 방법이 있다고 가정합니다 :) 그것이 자바라면 나는 그들을 나열 할 것입니다 :)
출력은 다음과 같습니다.
Method has failed, here are all method arguments {"Mario", "Super", 40, true, true}
Ruby 1.9.2 이상에서는 parameters
메서드에 대한 메서드를 사용하여 해당 메서드에 대한 매개 변수 목록을 가져올 수 있습니다. 그러면 매개 변수 이름과 필수 여부를 나타내는 쌍 목록이 반환됩니다.
예 :
만약 당신이
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 }
Ruby 2.1부터 binding.local_variable_get 을 사용 하여 메서드 매개 변수 (인수)를 포함한 모든 지역 변수의 값을 읽을 수 있습니다 . 덕분에 허용되는 답변 을 개선하여악 eval.
def foo(x, y)
method(__method__).parameters.map do |_, name|
binding.local_variable_get(name)
end
end
foo(1, 2) # => 1, 2
이를 처리하는 한 가지 방법은 다음과 같습니다.
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_variables를 사용 하고 있습니까? 그러나 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
도움이 될 수 있습니다 ...
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
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.
You could use a "splat" argument. It shoves everything into an array. It would look like:
def foo(*bar)
...
log.error "Error with arguments #{bar.joins(', ')}"
end
If you would change the method signature, you can do something like this:
def foo(*args)
# some code
# error happens here
logger.error "Method has failed, here are all method arguments #{args}"
end
Or:
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
It seems like what this question is trying to accomplish could be done with a gem I just released, https://github.com/ericbeland/exception_details. It will list local variables and vlaues (and instance variables) from rescued exceptions. Might be worth a look...
You can define a constant such as:
ARGS_TO_HASH = "method(__method__).parameters.map { |arg| arg[1].to_s }.map { |arg| { arg.to_sym => eval(arg) } }.reduce Hash.new, :merge"
And use it in your code like:
args = eval(ARGS_TO_HASH)
another_method_that_takes_the_same_arguments(**args)
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
Just add this class to your project:
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]]
참고URL : https://stackoverflow.com/questions/9211813/is-there-a-way-to-access-method-arguments-in-ruby
'Programing' 카테고리의 다른 글
삽입 모드에서 Linux vi 화살표 키가 깨짐 (0) | 2020.08.31 |
---|---|
내일 날짜를 얻는 가장 깨끗하고 파이썬적인 방법? (0) | 2020.08.31 |
Scala에서 함수를 정의하는 세 가지 방법의 차이점 (0) | 2020.08.31 |
조건부 판다 교체 (0) | 2020.08.31 |
Windows에서 pip 설치 액세스가 거부되었습니다. (0) | 2020.08.31 |