14

我怎样才能动态设置而不必全部编写相同的代码。

现在代码如下所示:

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
4

3 回答 3

16
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
于 2013-09-18T15:44:52.627 回答
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 

现在孩子将使用正确的文件夹和文件前缀进行初始化。如果我要使用第二个选项 - 它们将被初始化为零。

于 2015-05-27T17:12:03.107 回答
0

如果您使用 Ruby v2.5 或更高版本,请考虑使用Struct

MyClass = Struct.new(:foo, :bar, keyword_init: true)
MyClass.new(foo: 1, bar: 2)

https://ruby-doc.org/core-2.5.0/Struct.html#method-c-new

于 2021-06-08T07:33:29.133 回答