在初始化时使用attr_accessor设置ruby 2.0关键字参数
如何动态设置而无需全部编写相同的代码。
现在代码看起来像这样:
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
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
这是一个基于Sawa答案的工作示例。 选项号#1无法正常inheritance。
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进行初始化。 如果我要使用第二个选项 - 它们将初始化为零。