是否有一种 Ruby 方法可以删除初始值设定项中的样板代码



我编写了很多initialize代码来设置参数,类似于这样:

  class SiteClient
    attr_reader :login, :password, :domain
    def initialize(login, password, domain='somedefaultsite.com')
      @login = login
      @password = password
      @domain = domain
    end
  end

有没有更多的Ruby方法可以做到这一点?我觉得我正在一遍又一遍地编写相同的样板设置代码。

您可以使用

Ruby Struct

class MyClass < Struct.new(:login, :password, :domain)
end

或者你可以尝试一些宝石,即 Virtus:

class MyClass
  include Virtus.model
  attribute :login, String
  attribute :password, String
  attribute :domain, String
end

然后(在这两种情况下):

MyClass.new(login: 'a', password: 'b', domain: 'c')
你可以

像这样做得更好一点:

def initialize(login, password, site = 'somedefaultsite.com')
  @login, @password, @domain = login, password, domain
end

如果你没有可选的参数,那么你可能会更懒惰一点:

def initialize(*a)
  @login, @password, @domain = a
end

有一个名为 fattr 的 gem,您可以将其包含在 Ruby 应用程序或 gem 中以执行此操作。

require 'fattr'
class SiteClient
  fattr :login
  fattr :password
  fattr :domain => 'somedefaultsite.com'
  def initialize(**attributes)
    attributes.each do |k, v|
      public_send k, v
    end
  end
end
client = SiteClient.new
client.username = 'susan'
client.password = 'anything'
another_client = SiteClient.new username: 'bob', password: 'p@ssword1'

在此示例中,fattr 方法将为定义的每个属性定义读取器和编写器方法。此外,它可以为每个属性分配默认值。初始值设定项设置为接受键值对的哈希,它将循环访问该哈希,以通过使用要分配的值调用属性方法来填充属性。

需要注意的是,此示例将为属性生成读取器和编写器方法。在您的问题中,您只使用attr_reader因此,如果您希望类数据不可变,这可能不完全是您所需要的。可能有一种方法可以配置fattr来执行此操作,但我还没有广泛地使用它。

特别感谢Avdi Grimm和RubyTapas的第276集,这是我了解到这一点的地方。

在这个 DAS 截屏视频中,Gary Bernhardt 介绍了一些可以缩短常见类结构语法的元编程技巧,其中之一就是您所描述的初始化方法。他还将其捆绑到一个 gem 中,这将使您的代码看起来像

class SiteClient
  extend Cls
  takes       :login, :password, :domain
  attr_reader :login, :password, :domain
end

如果您对一些猴子修补感到满意,您还可以按照截屏视频中的方式实现 takes 方法。

class Module
  def takes(*names)
    define_method(:initialize) do |*values|
      names.zip(values).each do |name, value|
        instance_variable_set(:"@#{name}", value)
      end
    end
  end
end

这消除了上面示例中对extend Cls行的需求。

最新更新