Задайте аргументы ключевого слова ruby 2.0 с помощью attr_accessor при инициализации
Как я могу динамически установить без необходимости писать один и тот же код.
В настоящий момент код выглядит следующим образом:
def initialize(keywords: keywords, title: title, url: url, adsetting: adsetting)
self.keywords = keywords
self.title = title
self.url = url
self.adsetting = adsetting
end
Если список становится длиннее, это быстро выходит из-под контроля.
С ruby 1.9 я просто передаю хэш методу. Вот так:
def initialize(args)
args.each do |k,v|
instance_variable_set("@#{k}", v) unless v.nil?
end
end
Но я предпочитаю использовать аргументы ключевого слова Ruby 2.0. Может ли что-то подобное быть достигнуто?
def initialize(keywords: keywords, title: title, url: url, adsetting: adsetting)
args.each do |k,v|
instance_variable_set("@#{k}", v) unless v.nil?
end
end
Ответы
Ответ 1
def initialize(keywords: nil, title: nil, url: nil, adsetting: nil)
local_variables.each do |k|
v = eval(k.to_s)
instance_variable_set("@#{k}", v) unless v.nil?
end
end
или следуя указаниям Джона Ледбеттера и Кейри Суволанда:
def initialize(keywords: nil, title: nil, url: nil, adsetting: nil)
method(__method__).parameters.each do |type, k|
next unless type == :key
v = eval(k.to_s)
instance_variable_set("@#{k}", v) unless v.nil?
end
end
Ответ 2
Вот рабочий пример, основанный на ответе Саввы. Номер опции №1 работает неправильно с наследованием.
class CsvOutline
def initialize( headers: [],
body: [],
folder: 'tmp',
file_prefix: 'test',
filename: "#{file_prefix}_#{Time.zone.now.strftime("%Y%m%d%H%M%S")}.csv",
path: File.join(folder, filename))
# Set instance variables and attribute accessors based on named parameters in initialize
local_variables.each do |k|
class_eval do
attr_accessor k
end
v = eval(k.to_s)
instance_variable_set("@#{k}", v) unless v.nil?
end
end
end
теперь, если я должен был создать дочерний класс
class ReportCsv < CsvOutline
def initialize
super(folder: 'reports', file_prefix: 'Report')
end
end
Теперь дочерний элемент будет инициализирован с правильной папкой и file_prefix. Если бы мне пришлось использовать второй вариант - они будут инициализированы нулем.