有没有 Ruby 方法来删除初始化程序中的样板代码?
Is there a Ruby way to remove boilerplate code in initializers?
我写了很多 initialize
代码将 attrs 设置为参数,类似于:
class SiteClient
attr_reader :login, :password, :domain
def initialize(login, password, domain='somedefaultsite.com')
@login = login
@password = password
@domain = domain
end
end
有没有更Ruby的方法?我觉得我在一遍又一遍地编写相同的样板设置代码。
你可以像这样做得更好一点:
def initialize(login, password, site = 'somedefaultsite.com')
@login, @password, @domain = login, password, domain
end
如果你没有可选参数,那么你可以更懒一点:
def initialize(*a)
@login, @password, @domain = a
end
您可以使用 Ruby Struct
:
class MyClass < Struct.new(:login, :password, :domain)
end
或者您可以为此尝试一些 gems,即 Virtus:
class MyClass
include Virtus.model
attribute :login, String
attribute :password, String
attribute :domain, String
end
然后(在这两种情况下):
MyClass.new(login: 'a', password: 'b', domain: 'c')
有一个名为 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 和编写器方法。此外,它可以为每个属性分配一个默认值。初始化器被设置为接受键值对的散列,它将迭代通过调用属性方法来填充属性,方法是使用要分配的值。
需要注意的是,此示例将为您的属性生成 reader 和 writer 方法。在您的问题中,您只使用 attr_reader
因此如果您希望 class 数据不可变,这可能不是您所需要的。可能有一种方法可以配置 fattr
来执行此操作,但我还没有广泛使用它。
特别感谢 Avdi Grimm 和 RubyTapas 的第 276 集,这是我了解到这一点的地方。
也在 this DAS screencast, Gary Bernhardt walks through a few metaprogramming tricks that can shorten the syntax of common class constructs, one of which is the sort of initialize method you're describing. He bundled it into a 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
行的需要。
我写了很多 initialize
代码将 attrs 设置为参数,类似于:
class SiteClient
attr_reader :login, :password, :domain
def initialize(login, password, domain='somedefaultsite.com')
@login = login
@password = password
@domain = domain
end
end
有没有更Ruby的方法?我觉得我在一遍又一遍地编写相同的样板设置代码。
你可以像这样做得更好一点:
def initialize(login, password, site = 'somedefaultsite.com')
@login, @password, @domain = login, password, domain
end
如果你没有可选参数,那么你可以更懒一点:
def initialize(*a)
@login, @password, @domain = a
end
您可以使用 Ruby Struct
:
class MyClass < Struct.new(:login, :password, :domain)
end
或者您可以为此尝试一些 gems,即 Virtus:
class MyClass
include Virtus.model
attribute :login, String
attribute :password, String
attribute :domain, String
end
然后(在这两种情况下):
MyClass.new(login: 'a', password: 'b', domain: 'c')
有一个名为 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 和编写器方法。此外,它可以为每个属性分配一个默认值。初始化器被设置为接受键值对的散列,它将迭代通过调用属性方法来填充属性,方法是使用要分配的值。
需要注意的是,此示例将为您的属性生成 reader 和 writer 方法。在您的问题中,您只使用 attr_reader
因此如果您希望 class 数据不可变,这可能不是您所需要的。可能有一种方法可以配置 fattr
来执行此操作,但我还没有广泛使用它。
特别感谢 Avdi Grimm 和 RubyTapas 的第 276 集,这是我了解到这一点的地方。
也在 this DAS screencast, Gary Bernhardt walks through a few metaprogramming tricks that can shorten the syntax of common class constructs, one of which is the sort of initialize method you're describing. He bundled it into a 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
行的需要。