lib/moosex.rb in moosex-0.0.7 vs lib/moosex.rb in moosex-0.0.8
- old
+ new
@@ -65,32 +65,32 @@
attr = MooseX::Attribute.new(attr_name, attr_options)
g = attr.generate_getter
- define_method attr.attr_symbol, &g
+ define_method attr.reader, &g
s = attr.generate_setter
case attr.is
when :rw
- define_method "#{attr.attr_symbol}=", &s
+ define_method attr.writter, &s
when :rwp
- define_method "#{attr.attr_symbol}=", &s
+ define_method attr.writter, &s
- private "#{attr.attr_symbol}="
+ private attr.writter
end
__meta.add(attr)
end
end
end
class Attribute
- attr_reader :attr_symbol, :is
+ attr_reader :attr_symbol, :is, :reader, :writter, :lazy, :builder
DEFAULTS= {
lazy: false,
clearer: false,
required: false,
predicate: false,
@@ -104,11 +104,10 @@
is: lambda do |is, field_name|
unless [:rw, :rwp, :ro, :lazy].include?(is)
raise "invalid value for field '#{field_name}' is '#{is}', must be one of :rw, :rwp, :ro or :lazy"
end
end,
- handles: lambda {|handles, field_name| true }, # TODO: add implementation
};
COERCE = {
is: lambda do |is, field_name|
is.to_sym
@@ -197,17 +196,42 @@
handles.map do |key,value|
{ key.to_sym => value.to_sym }
end.reduce({}) do |hash,e|
hash.merge(e)
end
- end,
+ end,
+ reader: lambda do |reader, field_name|
+ reader.to_sym
+ end,
+ writter: lambda do |writter, field_name|
+ writter.to_sym
+ end,
+ builder: lambda do |builder, field_name|
+ unless builder.is_a? Proc
+ builder_method_name = builder.to_sym
+ builder = lambda do |object|
+ object.send(builder_method_name)
+ end
+ end
+
+ builder
+ end,
+ init_arg: lambda do |init_arg, field_name|
+ init_arg.to_sym
+ end,
};
def initialize(a, o)
# todo extract this to a framework, see issue #21 on facebook
- o = DEFAULTS.merge(o)
+ o = DEFAULTS.merge({
+ reader: a,
+ writter: a.to_s.concat("=").to_sym,
+ builder: "build_#{a}".to_sym,
+ init_arg: a,
+ }).merge(o)
+
REQUIRED.each { |field|
unless o.has_key?(field)
raise "field #{field} is required for Attribute #{a}"
end
}
@@ -218,10 +242,18 @@
end
VALIDATE.each_pair do |field, validate|
return if ! o.has_key? field
validate.call(o[field], a)
+ end
+
+ if o[:is].eql? :lazy
+ o[:lazy] = true
+ end
+
+ unless o[:lazy]
+ o[:builder] = nil
end
@attr_symbol = a
@is = o[:is]
@isa = o[:isa]
@@ -229,16 +261,19 @@
@required = o[:required]
@predicate = o[:predicate]
@clearer = o[:clearer]
@handles = o[:handles]
@lazy = o[:lazy]
+ @reader = o[:reader]
+ @writter = o[:writter]
+ @builder = o[:builder]
+ @init_arg = o[:init_arg]
end
def init(object, args)
inst_variable_name = "@#{@attr_symbol}".to_sym
- setter = @attr_symbol.to_s.concat("=").to_sym
value = nil
attr_symbol = @attr_symbol
@handles.each_pair do | method, target_method |
object.define_singleton_method method do |*args|
@@ -258,50 +293,66 @@
remove_instance_variable inst_variable_name
end
end
end
- if args.has_key? @attr_symbol
- value = args[ @attr_symbol ]
+ if args.has_key? @init_arg
+ value = args[ @init_arg ]
elsif @default
value = @default.call
elsif @required
raise "attr \"#{@attr_symbol}\" is required"
else
return
end
- if @is.eql? :ro
+ if @is.eql?(:ro) || @is.eql?(:lazy)
# TODO: remove redundancy
- type_check = generate_type_check
+ type_check = @isa
type_check.call(value)
+
object.instance_variable_set inst_variable_name, value
else
- object.send( setter, value )
+ object.send( @writter, value )
end
end
def generate_getter
inst_variable_name = "@#{@attr_symbol}".to_sym
- Proc.new { instance_variable_get inst_variable_name }
+
+ builder = @builder
+ before_get = lambda {|object| }
+
+ if @lazy
+ type_check = @isa
+
+ before_get = lambda do |object|
+ return if object.instance_variable_defined? inst_variable_name
+
+ value = builder.call(object)
+ type_check.call(value)
+
+ object.instance_variable_set(inst_variable_name, value)
+ end
+ end
+
+ Proc.new do
+ before_get.call(self)
+ instance_variable_get inst_variable_name
+ end
end
def generate_setter
inst_variable_name = "@#{@attr_symbol}".to_sym
- type_check = generate_type_check
+ type_check = @isa
Proc.new do |value|
type_check.call(value)
instance_variable_set inst_variable_name, value
end
- end
-
- def generate_type_check
-
- return @isa
- end
+ end
end
end
\ No newline at end of file