Как динамически вызвать метод, который принимает массив в качестве параметров? - PullRequest
1 голос
/ 22 февраля 2012

У меня есть такой метод:

def method (a=[],b=[])
 ...
end

Я вызываю этот метод с такими переменными:

method(h[0].values_at("value"), h[1].values_at("value")) 

, где h[0] и h[1] - хэши.Работает нормально.

Я не знаю, будет ли h[1] там в следующем запуске, поэтому выдает ошибку, если хеша h[1] нет.

Как я могуизмените его так, чтобы он выполнял вызов динамически в зависимости от того, есть ли h[0], h[1] или нет, и вызывает метод с правильным количеством параметров.

Ответы [ 4 ]

1 голос
/ 22 февраля 2012

Надеюсь, я правильно понял вашу проблему:

method(h[0].values_at("value"), 
        h[1] ? h[1].values_at("value") : []
      ) 

Ваша проблема: если h[1] не существует, h[1].values_at вызовет исключение.Поэтому сначала нужно проверить, доступно ли значение.В приведенном выше фрагменте кода я использовал троичный оператор.

Расширенная версия будет иметь вид:

par2 = []
par2 = h[1].values_at("value") if h[1]

method(h[0].values_at("value"), 
        par2
      ) 

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


В своем комментарии вы расширили свой вопрос.

С четырьмя параметрами вы можете использовать его следующим образом:

def method(p1,p2,p3,p4)
  #...
end

method(
    h[0] ? h[0].values_at("value") : [],
    h[1] ? h[1].values_at("value") : [],
    h[2] ? h[2].values_at("value") : [],
    h[3] ? h[3].values_at("value") : [],
  ) 

Но я бы порекомендовал более общую версию:

def method(*pars)
  #pars is an Array with all values (including empty arrays.
  #The next check make only sense, if you need exactly 4 values.
  raise "Expected 4 values, get #{pars.size}"  unless pars.size == 4
end

method( *(h.map{|i|i.values_at("x")})

И еще одна, вероятно, не очень хорошая идея:

Расширить nil (результат h[1], если h не имеет этого элемента), чтобы вернуть []для values_at:

class NilClass  
  def values_at(x)
    []
  end
end
1 голос
/ 22 февраля 2012

Самый простой способ сделать именно то, что вы просите, будет:

if h[1]
  method(h[0].values_at("x"), h[1].values_at("x"))
else
  method(h[0].values_at("x"))
end

Другая идея состоит в том, чтобы поместить хэш по умолчанию в случае, когда h [1] равен nil

method(h[0].values_at("x"), (h[1]||{}).values_at("x") )

Если вы уверены, что h никогда не имеет более 2 предметов, вы можете сделать:

method *(h.map{|i|i.values_at("x")})
0 голосов
/ 22 февраля 2012

Вы можете изменить сигнатуру функции, чтобы принимать переменные аргументы.

def foo(*args)
  options = args.extract_options!
  p options
  p args 
end
  • Вызов без параметров

    foo()
    {}
    []
    
  • Вызов с 2 параметрами

    foo(1, 2)
    {}
    [1, 2]
    
  • Вызов с 3 параметрами

    foo(1, 2, 3)
    {}
    [1, 2, 3]
    
  • Вызов с 3 параметрами и дополнительным хешем

    foo(1, 2, 3, :debug => true)
    {:debug=>true}
    [1, 2, 3]
    
0 голосов
/ 22 февраля 2012

Если вы используете Ruby On Rails, вы можете выполнить try метод:

method(h[0].values_at("value"), h[1].try(:values_at, 'value') || [])

Примеры для метода try:

nil.try('[]', :x) # => nil
{:x => 't'}.try('[]', :x) # => 't'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...