我写了许多initialize
代码,用于设置参数的类似,类似于:
class SiteClient
attr_reader :login, :password, :domain
def initialize(login, password, domain='somedefaultsite.com')
@login = login
@password = password
@domain = domain
end
end
有更多Ruby方式吗?我觉得我一遍又一遍地编写相同的样板设置代码。
答案 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
行的需求。