Ruby конструктор вызовов со случайным количеством параметров - PullRequest
2 голосов
/ 06 апреля 2011

У меня есть несколько классов, таких как

class Demo1 < Struct.new(:text, :text2) 
end
class Demo2 < Struct.new(:text, :text2, :text3) 
end

Как я могу вызвать конструктор каждого класса, если у меня есть только имя и хэш параметров, мне нужно написать метод, подобный этому, но это неправильно, потому что после отправки (: new, args) Struct будет содержать: текст, который равен args

 def call_demo_object(demo_name, args={})
          demo_name.to_s.constantize.send(:new,args) 
  end

Проблема Миана заключается в вызове конструктора со случайными параметрами из хеша

Ответы [ 3 ]

3 голосов
/ 06 апреля 2011

вариант первый:

def call_demo_object(demo_name, args={})
  z = [':new']
  args.keys.each do |key|
    z.push "args[:"+key.to_s+"]"
  end
  eval('demo_name.to_s.constantize.send(' + z.join(', ') +')' )
end

второй вариант:

def call_demo_object(demo_name, args={})
  a = demo_name.to_s.constantize.send(:new)
    args.each do |key, value|
      a[key] = value if a.members.include?(key)
    end
  a
end
2 голосов
/ 06 апреля 2011

Один из возможных вариантов:

def call_demo_object(demo_name, args={})
  obj = demo_name.new
  obj.members.each do |member|
    obj[member] = args[member]
  end
  obj
end

Это плюсы:

  • args может быть в любом порядке
  • будут назначены только доступные члены структуры
1 голос
/ 06 апреля 2011

Я вижу пару вещей неправильно:

Не уверен, действительно ли ваши классы выглядят так, но вам понадобится end в конце, иначе вы получите синтаксические ошибки.

Кроме того, constantize - это не метод для строк в Ruby, это то, что определяет Rails. Так что вам нужно будет использовать

Kernel.const_get(demo_name.to_s)

, чтобы получить ту же функциональность.

Как указано в комментариях, я не упомянул, как расширить параметры.

Для этого вам нужно использовать так называемый «оператор сплат»

Kernel.const_get(demo_name.to_s).send(:new,*args) #notice the * in front of args

Это расширит аргументы.

Однако, когда args является хешем, скажем, {:text=>"hello", :text2=>"hello2"}, он расширит его до массива с 2 элементами, где каждый элемент является массивом, в котором они вводят первую позицию и вводят во вторую позицию.

Вместо этого, если вы передадите массив как args с упорядоченными объектами, вы получите то, что ищете.

Я думаю, что если вы собираетесь узнать, что означает именованные параметры, вам, возможно, придется попробовать другой маршрут, но я точно не знаю.

Чтобы использовать необязательные или именованные параметры, вы можете посмотреть, как это делает Rails: использовать хеш для параметра, а затем передать хеш с ключами. Затем вы можете сохранить действительный список ключей и проверить переданный хэш и либо отклонить их, либо выдать ошибку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...