如何动态设置而无需全部编写相同的代码。
现在代码看起来像这样:
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
答案 0 :(得分:15)
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
或遵循John Ledbetter和Cary Swoveland的建议:
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
答案 1 :(得分:2)
这是一个基于Sawa的答案的工作示例。选项号#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进行初始化。如果我要使用第二个选项 - 它们将被初始化为nil。
答案 2 :(得分:0)
如果您使用的是 v2.5 或更高版本的 Ruby,请考虑使用 Struct
:
MyClass = Struct.new(:foo, :bar, keyword_init: true)
MyClass.new(foo: 1, bar: 2)