Вот немного другой ответ на вопрос Тадмана:
class Volume
ATTRIBUTES = [
:name, :size, :type, :owner, :date_created, :date_modified,
:iscsi_target, :iscsi_portal
].freeze
ATTRIBUTES.each do |attr|
attr_accessor attr
end
SYSTEM = 0
DATA = 1
DEFAULTS = {
:type => SYSTEM
}.freeze
def initialize(&block)
ATTRIBUTES.each do |attr|
self.__send__ "#{attr}=", DEFAULTS[attr]
end
yield(self)
end
def inspect
ATTRIBUTES.inject({}) { |h,attr| h[attr] = self.__send__ attr; h }
end
def to_json
self.inspect.to_json
end
end
Это позволяет сделать это:
vol = Volume.new do |v|
v.name = 'myVolume'
end
Мне это нравится, потому что преимущество заключается в том, что вы сразу же получаете ошибки, если кто-то сделал опечатку для атрибута.
Кроме того, в отличие от его ответа, он инициализирует значения по умолчанию, когда они не поставляются.
или если вы в конечном итоге делаете это много и действительно нуждаетесь в СУХОЙ:
module Attributable
@@ATTRIBUTES = []
@@DEFAULTS = {}
def initialize(&block)
@@ATTRIBUTES.each do |attr|
self.class.__send__ :attr_accessor, attr
self.__send__ "#{attr}=", @@DEFAULTS[attr]
end
yield(self)
end
end
class Volume
include Attributable
@@ATTRIBUTES = [ :name, :size, :type, :owner ]
@@DEFAULTS = { :type => 0 }
end
не мог понять, как это сделать с константами, поэтому я сделал это с переменными класса.