有没有Ruby方法来删除初始化器中的样板代码?

时间:2015-02-02 21:57:55

标签: ruby design-patterns

我写了许多initialize代码,用于设置参数的类似,类似于:

  class SiteClient
    attr_reader :login, :password, :domain

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

有更多Ruby方式吗?我觉得我一遍又一遍地编写相同的样板设置代码。

4 个答案:

答案 0 :(得分:8)

您可以使用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')

答案 1 :(得分:2)

你可以这样做得更好:

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

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

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

答案 2 :(得分:2)

有一个名为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方法将为定义的每个属性定义reader和writer方法。此外,它可以为每个属性分配一个默认值。初始化程序设置为接受键值对的散列,它将迭代通过调用带有要分配的值的属性方法来填充属性。

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

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

答案 3 :(得分:0)

this DAS screencast中,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行的需求。