Размышления о параметрах метода в Ruby

Возьмите следующий класс:

class Automator
  def fill_specific_form(fields)
    fields.each_pair do |key, value|
      puts "Setting '#{key}' to '#{value}'"
    end
  end
end

a = Automator.new
a.fill_specific_form :first_name => "Mads", :last_name => "Mobæk"

# => Setting 'first_name' to 'Mads'
# => Setting 'last_name' to 'Mobæk'

Можно ли сделать то же самое без хеша? Поскольку все параметры обязательны, я хочу метод со следующей подписью:

fill_specific_form(first_name, last_name)

На мой взгляд, это было бы возможно, если бы тело метода отражало и перебирало свои параметры, достигая, таким образом, того же результата.

Как бы вы это реализовали? Шаблон / идиома для этого уже существует? Два очевидных преимущества - это информация о параметрах в IDE и отсутствие необходимости проверять, предоставлены ли все хеш-ключи.

Чего я хочу избежать, так это:

puts "Setting first_name to #{first_name}"
puts "Setting last_name to #{last_name}"
# and so on

3 ответа

Решение

Если вы не установите никаких других локальных переменных внутри метода, local_variables выдаст список имен параметров метода (если вы установите другие переменные, вы можете просто вызвать local_variables первым делом и запомним результат). Таким образом, вы можете делать то, что вы хотите с local_variables+eval:

class Automator
  def fill_specific_form(first_name, last_name)
    local_variables.each do |var|
      puts "Setting #{var} to #{eval var.to_s}"
    end
  end
end

Automator.new().fill_specific_form("Mads", "Mobaek")

Однако имейте в виду, что это чистое зло.

И хотя бы для вашего примера

puts "Setting first_name to #{first_name}"
puts "Setting last_name to #{last_name}"

кажется гораздо более разумным.

Вы могли бы также сделать fields = {:first_name => first_name, :last_name => last_name} в начале метода, а затем идти с вашим fields.each_pair код.

Я не совсем понимаю. Вы хотите получить все параметры в одном массиве?

def fill_specific_form *args
    #Process args
end

Задуматься о методе (или Procс) параметры, которые вы можете использовать Proc#parameters, Method#parameters или же UnboundMethod#parameters:

->(m1, o1=nil, *s, m2, &b){}.parameters
# => [[:req, :m1], [:opt, :o1], [:rest, :s], [:req, :m2], [:block, :b]]

Однако в вашем случае я не понимаю, зачем вам нужно размышление, так как вы все равно уже знаете имена параметров.

Другие вопросы по тегам