classx 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +354 -0
- data/README +5 -0
- data/Rakefile +2 -2
- data/bench/attribute_get.rb +73 -0
- data/bench/attribute_set.rb +53 -19
- data/bench/define_attribute.rb +226 -0
- data/bench/initialize.rb +25 -7
- data/doc/output/coverage/index.html +74 -128
- data/doc/output/coverage/lib-classx-attribute_rb.html +291 -190
- data/doc/output/coverage/lib-classx-attributes_rb.html +167 -101
- data/doc/output/coverage/lib-classx-bracketable_rb.html +671 -0
- data/doc/output/coverage/lib-classx-class_attributes_rb.html +775 -0
- data/doc/output/coverage/lib-classx-commandable_rb.html +727 -0
- data/doc/output/coverage/{-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-block_rb.html → lib-classx-declare_rb.html} +60 -62
- data/doc/output/coverage/lib-classx-validate_rb.html +43 -41
- data/doc/output/coverage/lib-classx_rb.html +208 -78
- data/example/commandable.rb +1 -0
- data/lib/classx.rb +146 -16
- data/lib/classx/attribute.rb +244 -143
- data/lib/classx/attributes.rb +93 -27
- data/lib/classx/bracketable.rb +61 -0
- data/lib/classx/class_attributes.rb +165 -0
- data/lib/classx/commandable.rb +55 -4
- data/lib/classx/declare.rb +40 -3
- data/lib/classx/role/logger.rb +17 -13
- data/lib/classx/validate.rb +26 -24
- data/spec/classx/handles_spec.rb +21 -6
- data/spec/classx/serialize_spec.rb +57 -0
- data/spec/classx/{with_coerce.rb → with_coerce_spec.rb} +0 -0
- data/spec/classx/with_extend_spec.rb +58 -0
- data/spec/classx/with_include_spec.rb +58 -0
- data/spec/classx/with_validate_spec.rb +363 -0
- data/spec/classx/without_anyoption_spec.rb +1 -1
- data/spec/classx/writable_option_spec.rb +29 -4
- data/spec/classx_bracketable_spec.rb +160 -0
- data/spec/classx_class_attributes/default_option_spec.rb +121 -0
- data/spec/classx_class_attributes/dsl_accessor_spec.rb +88 -0
- data/spec/classx_class_attributes/handles_spec.rb +77 -0
- data/spec/classx_class_attributes/with_coerce_spec.rb +119 -0
- data/spec/classx_class_attributes/with_extend_spec.rb +64 -0
- data/spec/classx_class_attributes/with_include_spec.rb +64 -0
- data/spec/classx_class_attributes/with_multiple_class_spec.rb +60 -0
- data/spec/classx_class_attributes/with_validate_spec.rb +248 -0
- data/spec/classx_class_attributes/without_accessor_spec.rb +19 -0
- data/spec/classx_class_attributes/without_anyoption_spec.rb +21 -0
- data/spec/classx_class_attributes/writable_option_spec.rb +100 -0
- data/spec/classx_declare_spec.rb +117 -0
- data/spec/classx_validate_spec.rb +1 -3
- data/tasks/basic_tasks.rake +1 -1
- metadata +36 -26
- data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-callbacks_rb.html +0 -932
- data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-change_rb.html +0 -779
- data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-hunk_rb.html +0 -867
- data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs_rb.html +0 -1715
- data/doc/output/coverage/-Library-Ruby-Gems-gems-rcov-0_8_1_2_0-lib-rcov_rb.html +0 -1598
- data/spec/classx/with_extend.rb +0 -27
- data/spec/classx/with_include.rb +0 -27
data/example/commandable.rb
CHANGED
data/lib/classx.rb
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
require 'classx/attribute'
|
2
2
|
require 'classx/attributes'
|
3
3
|
|
4
|
+
# usage
|
5
|
+
#
|
6
|
+
# require 'classx'
|
7
|
+
# class Point
|
8
|
+
# include ClassX
|
9
|
+
#
|
10
|
+
# has :x, :kind_of => Fixnum
|
11
|
+
# has :y, :kind_of => Fixnum
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# class Point3D < Point
|
15
|
+
# has :z, :writable => true, :kind_of => Fixnum, :optional => true
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# Point.new(:x => 30, :y => 40) #=> <# Point @x=30, @y=40 >
|
19
|
+
# point3d = Point3D.new(:x => 30, :y => 40, :z => 50) #=> <# Point3D @x=30, @y=40, @z=50 >
|
20
|
+
# point3d.z = 60.0 # raise ClassX::InvalidAttrArgument
|
4
21
|
module ClassX
|
22
|
+
autoload :ClassAttributes, 'classx/class_attributes'
|
23
|
+
autoload :CAttrs, 'classx/class_attributes'
|
5
24
|
autoload :Validate, 'classx/validate'
|
6
25
|
autoload :Commandable, 'classx/commandable'
|
7
26
|
autoload :Declare, 'classx/declare'
|
8
|
-
autoload :
|
27
|
+
autoload :Bracketable, 'classx/bracketable'
|
9
28
|
module Role
|
10
29
|
autoload :Logger, 'classx/role/logger'
|
11
30
|
end
|
12
31
|
|
32
|
+
MODULE_USAGE_MAP_OF = {
|
33
|
+
:ClassAttributes => :extend,
|
34
|
+
:CAttrs => :extend,
|
35
|
+
:Commandable => :extend,
|
36
|
+
:Declare => :extend,
|
37
|
+
:Bracketable => :include,
|
38
|
+
:Validate => :include,
|
39
|
+
}
|
40
|
+
|
13
41
|
class InstanceException < Exception; end
|
14
42
|
class AttrRequiredError < InstanceException; end
|
15
43
|
class InvalidAttrArgument < InstanceException; end
|
@@ -17,10 +45,10 @@ module ClassX
|
|
17
45
|
class OptionalAttrShouldBeWritable < Exception; end
|
18
46
|
class RequiredAttrShouldNotHaveDefault < Exception; end
|
19
47
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
48
|
+
# *args is Hash in default.
|
49
|
+
# Hash should have attribute's key and valid value for attribute.
|
50
|
+
# This method checking required value is setted and taking value is valid to attribute.
|
51
|
+
#
|
24
52
|
def initialize *args
|
25
53
|
hash = before_init(*args)
|
26
54
|
|
@@ -28,21 +56,20 @@ module ClassX
|
|
28
56
|
raise ArgumentError, "#{hash.inspect} was wrong as arguments. please specify kind of Hash instance"
|
29
57
|
end
|
30
58
|
|
31
|
-
# allow String or Symbol for key
|
59
|
+
# allow String or Symbol for key
|
32
60
|
tmp_hash = {}
|
33
61
|
hash.each do |key,val|
|
34
62
|
tmp_hash[key.to_s] = val
|
35
63
|
end
|
36
64
|
hash = tmp_hash
|
37
65
|
|
38
|
-
cached_attribute_of = attribute_of
|
39
66
|
hash.each do |key, val|
|
40
|
-
if
|
41
|
-
|
67
|
+
if attribute_of[key]
|
68
|
+
attribute_of[key].set val
|
42
69
|
end
|
43
70
|
end
|
44
71
|
|
45
|
-
|
72
|
+
attribute_of.each do |key, val|
|
46
73
|
next if val.class.lazy?
|
47
74
|
raise AttrRequiredError, "param: :#{key} is required to #{hash.inspect}" if !val.class.optional? && !val.get
|
48
75
|
end
|
@@ -50,18 +77,32 @@ module ClassX
|
|
50
77
|
after_init
|
51
78
|
end
|
52
79
|
|
80
|
+
# return Hash of attribute's name as a key and attribute's meta class instance as a value.
|
81
|
+
# for example,
|
82
|
+
#
|
83
|
+
# class YourClass
|
84
|
+
# include ClassX
|
85
|
+
# has :x
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# obj = YourClass.new(:x => 10)
|
89
|
+
# obj.attribute_of #=> { "x" => <#<ClassX::Attribute> parent=<# YourClass> ... > }
|
90
|
+
#
|
53
91
|
def attribute_of
|
54
|
-
|
55
|
-
|
56
|
-
self.class.attribute_of
|
57
|
-
|
92
|
+
unless instance_variable_defined?('@__attribute_of') && @__attribute_of
|
93
|
+
@__attribute_of = {}
|
94
|
+
if self.class.attribute_of
|
95
|
+
self.class.attribute_of.keys.each do |key|
|
96
|
+
@__attribute_of[key] = __send__ "attribute_of:#{key}"
|
97
|
+
end
|
58
98
|
end
|
59
99
|
end
|
60
100
|
|
61
|
-
|
101
|
+
@__attribute_of
|
62
102
|
end
|
63
103
|
|
64
|
-
#
|
104
|
+
# processing initialize argument to hash
|
105
|
+
# you can override this method for not taking initializer your classx based class.
|
65
106
|
def before_init *args
|
66
107
|
raise ArgumentError if args.size > 1
|
67
108
|
|
@@ -69,7 +110,96 @@ module ClassX
|
|
69
110
|
hash.nil? ? {} : hash
|
70
111
|
end
|
71
112
|
|
113
|
+
alias process_init_args before_init
|
114
|
+
|
115
|
+
# automatically called this method on last of #initialize.
|
116
|
+
# you can override this method.
|
72
117
|
def after_init
|
73
118
|
end
|
74
119
|
|
120
|
+
# shared implementation for comparing classx based object.
|
121
|
+
def == other
|
122
|
+
return false unless other.kind_of? self.class
|
123
|
+
attribute_of.all? do |key, val|
|
124
|
+
val.get == other.__send__(key)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
UNSERIALIZE_INSTANCE_VARIABLES = ["@__attribute_of", "@__attribute_data_of"]
|
129
|
+
|
130
|
+
# convert attribute key and value to Hash.
|
131
|
+
def to_hash
|
132
|
+
result = {}
|
133
|
+
|
134
|
+
attribute_of.each do |key, val|
|
135
|
+
result[key] = val.get
|
136
|
+
end
|
137
|
+
|
138
|
+
result
|
139
|
+
end
|
140
|
+
|
141
|
+
# dupping classx based class.
|
142
|
+
def dup
|
143
|
+
self.class.new(to_hash)
|
144
|
+
end
|
145
|
+
|
146
|
+
# for Marshal.dump
|
147
|
+
def marshal_dump
|
148
|
+
dump_of = {}
|
149
|
+
dump_of[:attribute_of] = to_hash
|
150
|
+
dump_of[:instance_variable_of] = {}
|
151
|
+
( instance_variables.map {|ival| ival.to_s } - UNSERIALIZE_INSTANCE_VARIABLES ).each do |ival|
|
152
|
+
dump_of[:instance_variable_of][ival] = instance_variable_get(ival)
|
153
|
+
end
|
154
|
+
|
155
|
+
dump_of
|
156
|
+
end
|
157
|
+
|
158
|
+
# for Marshal.load
|
159
|
+
def marshal_load val
|
160
|
+
self.attribute_of.each do |k, v|
|
161
|
+
v.set(val[:attribute_of][k])
|
162
|
+
end
|
163
|
+
val[:instance_variable_of].each do |key, val|
|
164
|
+
instance_variable_set(key, val)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# for YAML.dump
|
169
|
+
def to_yaml opts={}
|
170
|
+
require 'yaml'
|
171
|
+
YAML.quick_emit(self, opts) do |out|
|
172
|
+
out.map( taguri, to_yaml_style ) do |map|
|
173
|
+
attribute_of = {}
|
174
|
+
to_hash.each do |key, val|
|
175
|
+
attribute_of[key] = val
|
176
|
+
end
|
177
|
+
map.add(:attribute_of, attribute_of)
|
178
|
+
|
179
|
+
instance_variable_of = {}
|
180
|
+
( instance_variables.map {|ival| ival.to_s } - UNSERIALIZE_INSTANCE_VARIABLES ).each do |ival|
|
181
|
+
instance_variable_of[ival] = instance_variable_get(ival)
|
182
|
+
end
|
183
|
+
map.add(:instance_variable_of, instance_variable_of)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# for YAML.load
|
189
|
+
def yaml_initialize tag, val
|
190
|
+
self.attribute_of.each do |k, v|
|
191
|
+
v.set(val[:attribute_of][k])
|
192
|
+
end
|
193
|
+
|
194
|
+
val[:instance_variable_of].each do |k, v|
|
195
|
+
instance_variable_set(k, v)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
private
|
200
|
+
|
201
|
+
def self.included klass
|
202
|
+
klass.extend(Attributes)
|
203
|
+
end
|
204
|
+
|
75
205
|
end
|
data/lib/classx/attribute.rb
CHANGED
@@ -1,183 +1,284 @@
|
|
1
1
|
module ClassX
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
# XXX: Hack for defining class method for klass
|
8
|
-
tmp_mod = Module.new
|
9
|
-
tmp_mod.module_eval do
|
10
|
-
define_method :config do
|
11
|
-
args
|
12
|
-
end
|
2
|
+
module AttributeMethods #:nodoc:
|
3
|
+
module ClassMethods #:nodoc:
|
4
|
+
def value_class
|
5
|
+
config[:isa] || config[:kind_of]
|
6
|
+
end
|
13
7
|
|
14
|
-
|
15
|
-
|
16
|
-
|
8
|
+
# description for attribute
|
9
|
+
def desc
|
10
|
+
config[:desc]
|
11
|
+
end
|
12
|
+
|
13
|
+
# when this option specify true, not raise error in #initialize without value.
|
14
|
+
def optional?
|
15
|
+
return config[:optional]
|
16
|
+
end
|
17
|
+
|
18
|
+
# when it lazy option specified, it will not be initialized when #initialize.
|
19
|
+
def lazy?
|
20
|
+
return config[:lazy]
|
21
|
+
end
|
17
22
|
|
18
|
-
|
19
|
-
|
20
|
-
|
23
|
+
def inspect
|
24
|
+
"ClassX::Attribute[#{self.config.inspect}]"
|
25
|
+
end
|
26
|
+
|
27
|
+
module CoerceWithHash #:nodoc:
|
28
|
+
def coerce val
|
29
|
+
result = val
|
30
|
+
config[:coerce].each do |cond, rule|
|
31
|
+
case cond
|
32
|
+
when Proc
|
33
|
+
if cond.call(val)
|
34
|
+
result = rule.call(val)
|
35
|
+
break
|
36
|
+
end
|
37
|
+
when Symbol
|
38
|
+
if val.respond_to? cond
|
39
|
+
result = rule.call(val)
|
40
|
+
break
|
41
|
+
end
|
42
|
+
when Module
|
43
|
+
if val.kind_of? cond
|
44
|
+
result = rule.call(val)
|
45
|
+
break
|
46
|
+
end
|
47
|
+
end
|
21
48
|
end
|
22
49
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
case cond
|
32
|
-
when Proc
|
33
|
-
if cond.call(val)
|
34
|
-
result = rule.call(val)
|
35
|
-
break
|
36
|
-
end
|
37
|
-
when Symbol
|
38
|
-
if val.respond_to? cond
|
39
|
-
result = rule.call(val)
|
40
|
-
break
|
41
|
-
end
|
42
|
-
when Module
|
43
|
-
if val.kind_of? cond
|
44
|
-
result = rule.call(val)
|
45
|
-
break
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
50
|
+
return result
|
51
|
+
end
|
52
|
+
end
|
53
|
+
module CoerceWithArray #:nodoc:
|
54
|
+
def coerce val
|
55
|
+
result = val
|
56
|
+
config[:coerce].each do |item|
|
57
|
+
raise unless item.kind_of? Hash
|
49
58
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
item.each do |cond, rule|
|
59
|
-
|
60
|
-
case cond
|
61
|
-
when Proc
|
62
|
-
if cond.call(val)
|
63
|
-
result = rule.call(val)
|
64
|
-
break
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
break if result
|
69
|
-
end
|
59
|
+
case item
|
60
|
+
when Hash
|
61
|
+
item.each do |cond, rule|
|
62
|
+
case cond
|
63
|
+
when Proc
|
64
|
+
if cond.call(val)
|
65
|
+
result = rule.call(val)
|
66
|
+
break
|
70
67
|
end
|
71
|
-
|
72
|
-
break if result
|
73
68
|
end
|
74
69
|
|
75
|
-
|
70
|
+
break if result
|
76
71
|
end
|
77
|
-
else
|
78
|
-
return val
|
79
72
|
end
|
73
|
+
|
74
|
+
break if result
|
80
75
|
end
|
81
76
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
77
|
+
return result
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
module CoerceNothing #:nodoc:
|
82
|
+
def coerce val
|
83
|
+
val
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
module DefaultWithProc #:nodoc:
|
88
|
+
def default parent
|
89
|
+
config[:default].call(parent)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
module DefaultWithNoProc #:nodoc:
|
93
|
+
def default parent
|
94
|
+
begin
|
95
|
+
config[:default].dup
|
96
|
+
rescue Exception
|
97
|
+
config[:default]
|
103
98
|
end
|
99
|
+
end
|
100
|
+
end
|
104
101
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
102
|
+
module ValidateWithProc #:nodoc:
|
103
|
+
def validate? val
|
104
|
+
return config[:validate].call(val)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
module ValidateWithNotProc #:nodoc:
|
109
|
+
def validate? val
|
110
|
+
return config[:validate] === val
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
module ValidateEach #:nodoc:
|
115
|
+
def validate? val
|
116
|
+
return false unless val.respond_to? :all?
|
117
|
+
|
118
|
+
if self.value_class
|
119
|
+
return false unless val.kind_of?(self.value_class)
|
120
|
+
|
121
|
+
case val
|
122
|
+
when Hash
|
123
|
+
if config[:validate_each].arity == 2
|
124
|
+
val.all? {|item| config[:validate_each].call(*item) }
|
125
|
+
else
|
126
|
+
ClassX::Validate.validate(val, &config[:validate_each])
|
116
127
|
end
|
128
|
+
else
|
129
|
+
val.all? {|item| config[:validate_each].call(*item) }
|
117
130
|
end
|
131
|
+
else
|
132
|
+
val.all? {|item| config[:validate_each].call(*item) }
|
118
133
|
end
|
134
|
+
end
|
135
|
+
end
|
119
136
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
137
|
+
module ValidateKindOf #:nodoc:
|
138
|
+
def validate? val
|
139
|
+
return val.kind_of?(self.value_class)
|
140
|
+
end
|
141
|
+
end
|
124
142
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
143
|
+
module ValidateRespondTo #:nodoc:
|
144
|
+
def validate? val
|
145
|
+
return val.respond_to?(config[:respond_to])
|
146
|
+
end
|
147
|
+
end
|
129
148
|
|
130
|
-
|
131
|
-
|
132
|
-
|
149
|
+
module ValidateNothing #:nodoc:
|
150
|
+
def validate? val
|
151
|
+
# nothing checked.
|
152
|
+
true
|
133
153
|
end
|
134
|
-
|
154
|
+
end
|
155
|
+
end
|
135
156
|
|
136
|
-
|
137
|
-
|
157
|
+
module InstanceMethods #:nodoc:
|
158
|
+
def initialize val
|
159
|
+
@parent = val
|
160
|
+
@data = nil
|
161
|
+
end
|
138
162
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
163
|
+
def get
|
164
|
+
@data ||= self.class.default(@parent)
|
165
|
+
end
|
166
|
+
|
167
|
+
# XXX:
|
168
|
+
# you should not call this method except for @parent instance's setter method.
|
169
|
+
# It's because caching as instance_variable in @parent instance for performance.
|
170
|
+
def set val
|
171
|
+
val = self.class.coerce(val)
|
172
|
+
raise ClassX::InvalidAttrArgument unless self.class.validate? val
|
173
|
+
@data = val
|
174
|
+
end
|
175
|
+
|
176
|
+
def inspect
|
177
|
+
"<#ClassX::Attribute:#{object_id} #{ @data.nil? ? '@data=nil' : '@data=' + @data.inspect } @parent=#{@parent} config=#{self.class.config.inspect}>"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
#
|
183
|
+
# generating anonymous class for meta attribute class.
|
184
|
+
#
|
185
|
+
class AttributeFactory
|
186
|
+
#
|
187
|
+
# creating anonymous class for meta attribute class.
|
188
|
+
def self.create args
|
189
|
+
# TODO: hmm, ClassX::Commandable do nothing when freezed.
|
190
|
+
#
|
191
|
+
# if you would like to change attribute's infomation, it's better to redefine attribute.
|
192
|
+
# So, config should freezed.
|
193
|
+
# args.each do |key, val|
|
194
|
+
# key.freeze
|
195
|
+
# val.freeze
|
196
|
+
# end
|
197
|
+
# args.freeze
|
143
198
|
|
144
|
-
|
145
|
-
|
199
|
+
raise ClassX::RequiredAttrShouldNotHaveDefault if args[:optional] == false && !args[:default].nil?
|
200
|
+
raise ClassX::OptionalAttrShouldBeWritable if args[:optional] && args[:writable] == false
|
201
|
+
|
202
|
+
klass = Class.new
|
203
|
+
|
204
|
+
klass.extend(ClassX::AttributeMethods::ClassMethods)
|
205
|
+
|
206
|
+
# you specify type changing rule with :coerce option.
|
207
|
+
if args[:coerce]
|
208
|
+
case args[:coerce]
|
209
|
+
when Hash
|
210
|
+
klass.extend(ClassX::AttributeMethods::ClassMethods::CoerceWithHash)
|
211
|
+
when Array
|
212
|
+
klass.extend(ClassX::AttributeMethods::ClassMethods::CoerceWithArray)
|
146
213
|
end
|
214
|
+
else
|
215
|
+
klass.extend(ClassX::AttributeMethods::ClassMethods::CoerceNothing)
|
216
|
+
end
|
147
217
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
218
|
+
# default paramater for attribute.
|
219
|
+
# if default is Proc, run Proc every time in instanciate.
|
220
|
+
case args[:default]
|
221
|
+
when Proc
|
222
|
+
klass.extend(ClassX::AttributeMethods::ClassMethods::DefaultWithProc)
|
223
|
+
else
|
224
|
+
klass.extend(ClassX::AttributeMethods::ClassMethods::DefaultWithNoProc)
|
225
|
+
end
|
226
|
+
|
227
|
+
# you can specify :validate option for checking when value is setted.
|
228
|
+
# you can use :respond_to as shotcut for specifying { :validate => proc {|val| respond_to?(val, true) } }
|
229
|
+
# you can use :isa or :kind_of as shotcut for specifying { :validate => proc {|val| kind_of?(val) } }
|
230
|
+
if args[:validate]
|
231
|
+
case args[:validate]
|
232
|
+
when Proc
|
233
|
+
klass.extend(ClassX::AttributeMethods::ClassMethods::ValidateWithProc)
|
234
|
+
else
|
235
|
+
klass.extend(ClassX::AttributeMethods::ClassMethods::ValidateWithNotProc)
|
152
236
|
end
|
237
|
+
elsif args[:validate_each]
|
238
|
+
klass.extend(ClassX::AttributeMethods::ClassMethods::ValidateEach)
|
239
|
+
elsif mod = ( args[:isa] || args[:kind_of] )
|
240
|
+
klass.extend(ClassX::AttributeMethods::ClassMethods::ValidateKindOf)
|
241
|
+
elsif args[:respond_to]
|
242
|
+
klass.extend(ClassX::AttributeMethods::ClassMethods::ValidateRespondTo)
|
243
|
+
else
|
244
|
+
klass.extend(ClassX::AttributeMethods::ClassMethods::ValidateNothing)
|
245
|
+
end
|
153
246
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
end
|
161
|
-
else
|
162
|
-
self.__send__ :include, args[:include]
|
247
|
+
# for extending attribute point.
|
248
|
+
if args[:include]
|
249
|
+
case args[:include]
|
250
|
+
when Array
|
251
|
+
args[:include].each do |mod|
|
252
|
+
klass.__send__ :include, mod
|
163
253
|
end
|
254
|
+
else
|
255
|
+
klass.__send__ :include, args[:include]
|
164
256
|
end
|
257
|
+
end
|
165
258
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
end
|
172
|
-
else
|
173
|
-
self.__send__ :extend, args[:extend]
|
259
|
+
if args[:extend]
|
260
|
+
case args[:extend]
|
261
|
+
when Array
|
262
|
+
args[:extend].each do |mod|
|
263
|
+
klass.__send__ :extend, mod
|
174
264
|
end
|
265
|
+
else
|
266
|
+
klass.__send__ :extend, args[:extend]
|
175
267
|
end
|
268
|
+
end
|
176
269
|
|
177
|
-
|
178
|
-
|
270
|
+
# XXX: Hack for defining class method for klass
|
271
|
+
tmp_mod = Module.new
|
272
|
+
tmp_mod.module_eval do
|
273
|
+
define_method :config do
|
274
|
+
args
|
179
275
|
end
|
180
276
|
end
|
277
|
+
klass.extend(tmp_mod)
|
278
|
+
|
279
|
+
klass.class_eval do
|
280
|
+
include ClassX::AttributeMethods::InstanceMethods
|
281
|
+
end
|
181
282
|
|
182
283
|
klass
|
183
284
|
end
|