Ruby中的DRY'er对象初始化
在ruby中有更多'干'的方法来做以下事情吗?Ruby中的DRY'er对象初始化
#!/usr/bin/env ruby
class Volume
attr_accessor :name, :size, :type, :owner, :date_created, :date_modified, :iscsi_target, :iscsi_portal
SYSTEM = 0
DATA = 1
def initialize(args={:type => SYSTEM})
@name = args[:name]
@size = args[:size]
@type = args[:type]
@owner = args[:owner]
@iscsi_target = args[:iscsi_target]
@iscsi_portal = args[:iscsi_portal]
end
def inspect
return {:name => @name,
:size => @size,
:type => @type,
:owner => @owner,
:date_created => @date_created,
:date_modified => @date_modified,
:iscsi_target => @iscsi_target,
:iscsi_portal => @iscsi_portal }
end
def to_json
self.inspect.to_json
end
末
每当你看到的东西像一个长长的清单,通常你可以把它卷都成一个单一的阵列:
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(args = nil)
# EDIT
# args = args ? DEFAULTS : DEFAULTS.merge(args) # Original
args = args ? DEFAULTS.merge(args) : DEFAULTS
ATTRIBUTES.each do |attr|
if (args.key?(attr))
instance_variable_set("@#{attr}", args[attr])
end
end
end
def inspect
ATTRIBUTES.inject({ }) do |h, attr|
h[attr] = instance_variable_get("@#{attr}")
h
end
end
def to_json
self.inspect.to_json
end
end
操纵实例变量是以后很简单。
太棒了!我必须在初始化函数中更改一行 args = args? DEFAULTS:DEFAULTS.merge(args) 变成 args =(args == nil)?默认值:DEFAULTS.merge(args) 否则它将返回DEFAULTS并且不会设置任何内容。 – 2009-06-11 19:46:58
class Volume
FIELDS = %w(name size type owner iscsi_target iscsi_portal date_create date_modified)
SYSTEM = 0
DATA = 1
attr_accessor *FIELDS
def initialize(args= { :type => SYSTEM })
args.each_pair do | key, value |
self.send("#{key}=", value) if self.respond_to?("#{key}=")
end
end
def inspect
FIELDS.inject({}) do | hash, field |
hash.merge(field.to_sym => self.send(field))
end.inspect
end
end
我会#inspect
返回一个字符串(最喜欢的#inspect
方法),也许因素 出你转换成散列法成#to_hash
方法来代替。
的args.merge(DEFAULTS).merge(args)
废话让args
覆盖的DEFAULTS
,但 防止任何默认行为args
(比方说,如果args == Hash.new(3)
或args == Hash.new { |h,k| h[k] = h.to_s.length }
class Volume
ATTRIBUTES = %w{
name size type owner date_created date_modified
iscsi_target iscsi_portal
}.map! { |s| s.to_sym }.freeze
attr_accessor *ATTRIBUTES
SYSTEM = 0
DATA = 1
DEFAULTS = { :type => SYSTEM }.freeze
def initialize(args = nil)
args = args ? args.merge(DEFAULTS).merge(args) : DEFAULTS
ATTRIBUTES.each do |attr|
instance_variable_set("@#{attr}", args[attr])
end
end
def to_hash
Hash[ *ATTRIBUTES.map { |attr| [ attr, instance_variable_get("@#{attr}") ] }.flatten ]
end
def inspect
to_hash.inspect
end
def to_json
self.to_hash.to_json
end
end
这里有答案稍有不同的旋转通过tadman:
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
无法工作,如何与常量做,所以我用类变量,而不是做到了。
OpenStruct会有所需的功能吗? – 2011-06-26 05:28:18
这应该在codereview.stackexchange.com – 2012-01-31 00:36:36