classx 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. data/ChangeLog +4 -0
  2. data/README +39 -0
  3. data/Rakefile +52 -0
  4. data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-block_rb.html +661 -0
  5. data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-callbacks_rb.html +932 -0
  6. data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-change_rb.html +779 -0
  7. data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-hunk_rb.html +867 -0
  8. data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs_rb.html +1715 -0
  9. data/doc/output/coverage/-Library-Ruby-Gems-gems-rcov-0_8_1_2_0-lib-rcov_rb.html +1598 -0
  10. data/doc/output/coverage/-System-Library-Frameworks-Ruby_framework-Versions-1_8-usr-lib-ruby-1_8-drb-drb_rb.html +2373 -0
  11. data/doc/output/coverage/-System-Library-Frameworks-Ruby_framework-Versions-1_8-usr-lib-ruby-1_8-drb-eq_rb.html +626 -0
  12. data/doc/output/coverage/-System-Library-Frameworks-Ruby_framework-Versions-1_8-usr-lib-ruby-1_8-drb-invokemethod_rb.html +646 -0
  13. data/doc/output/coverage/-System-Library-Frameworks-Ruby_framework-Versions-1_8-usr-lib-ruby-1_8-forwardable_rb.html +828 -0
  14. data/doc/output/coverage/-System-Library-Frameworks-Ruby_framework-Versions-1_8-usr-lib-ruby-1_8-pp_rb.html +1257 -0
  15. data/doc/output/coverage/-System-Library-Frameworks-Ruby_framework-Versions-1_8-usr-lib-ruby-1_8-prettyprint_rb.html +1506 -0
  16. data/doc/output/coverage/-System-Library-Frameworks-Ruby_framework-Versions-1_8-usr-lib-ruby-1_8-timeout_rb.html +715 -0
  17. data/doc/output/coverage/index.html +603 -0
  18. data/doc/output/coverage/lib-classx-validate_rb.html +645 -0
  19. data/doc/output/coverage/lib-classx_rb.html +752 -0
  20. data/lib/classx.rb +142 -0
  21. data/lib/classx.rb.new +102 -0
  22. data/lib/classx/attributes.rb +13 -0
  23. data/lib/classx/commandable.rb +8 -0
  24. data/lib/classx/validate.rb +35 -0
  25. data/spec/classx_spec.rb +261 -0
  26. data/spec/classx_validate_spec.rb +40 -0
  27. data/spec/spec.opts +1 -0
  28. data/spec/spec_helper.rb +4 -0
  29. data/tasks/basic_config.rake +22 -0
  30. data/tasks/basic_tasks.rake +139 -0
  31. metadata +107 -0
@@ -0,0 +1,142 @@
1
+
2
+ class ClassX
3
+ class AttrRequiredError < Exception; end
4
+ class InvalidAttrArgument < Exception; end
5
+ class LazyOptionShouldHaveDefault < Exception; end
6
+ class OptionalAttrShouldBeWritable < Exception; end
7
+ class RequiredAttrShouldNotHaveDefault < Exception; end
8
+ class <<self
9
+ def has name, attrs={}
10
+ name = name.to_s
11
+
12
+ setter_definition = ''
13
+ if !attrs[:respond_to].nil?
14
+ setter_definition += <<-END_OF_RESPOND_TO
15
+ raise InvalidAttrArgument, "param :#{name}'s value \#{val.inspect} should respond_to #{attrs[:respond_to]}}" unless val.respond_to? #{attrs[:respond_to]}
16
+ END_OF_RESPOND_TO
17
+ end
18
+ if !attrs[:kind_of].nil?
19
+ setter_definition += <<-END_OF_KIND_OF
20
+ raise InvalidAttrArgument, "param :#{name}'s value \#{val.inspect} should kind_of #{attrs[:kind_of]}" unless val.kind_of? #{attrs[:kind_of]}
21
+ END_OF_KIND_OF
22
+ end
23
+
24
+ self.class_eval <<-END_OF_ACCESSOR
25
+ attr_reader "#{name}"
26
+
27
+ def #{name}= val
28
+ #{setter_definition}
29
+ @#{name} = val
30
+ end
31
+ END_OF_ACCESSOR
32
+
33
+ if attrs[:default].nil?
34
+ raise LazyOptionShouldHaveDefault, "in :#{name}: :lazy option need specifying :default" if attrs[:lazy]
35
+ else
36
+ # when you specify :optional to false explicitly, raise Error.
37
+ if attrs[:optional].nil?
38
+ attrs[:optional] = true
39
+ end
40
+ raise RequiredAttrShouldNotHaveDefault, "in :#{name}: required attribute should not have :default option" unless attrs[:optional]
41
+ case attrs[:default]
42
+ when Proc
43
+ register_attr_default_value_proc name, &attrs[:default]
44
+ else
45
+ register_attr_default_value name, attrs[:default]
46
+ end
47
+ end
48
+
49
+ if attrs[:optional]
50
+ if attrs[:writable].nil?
51
+ attrs[:writable] = true
52
+ else
53
+ raise OptionalAttrShouldBeWritable unless attrs[:writable]
54
+ end
55
+ else
56
+ register_attr_required name
57
+ end
58
+
59
+ unless attrs[:writable]
60
+ __send__ :private,"#{name}="
61
+ end
62
+
63
+ end
64
+
65
+ def register_attr_default_value name, value
66
+ self.class_eval do
67
+ define_method "set_attr_default_value_of[#{name}]" do
68
+ self.__send__ "#{name}=", value
69
+ end
70
+
71
+ private "set_attr_default_value_of[#{name}]"
72
+ end
73
+ end
74
+
75
+ def register_attr_default_value_proc name, &block
76
+ self.class_eval do
77
+ define_method "set_attr_default_value_of[#{name}]" do
78
+ self.__send__ "#{name}=", block.call(self)
79
+ end
80
+
81
+ private "set_attr_default_value_of[#{name}]"
82
+ end
83
+ end
84
+
85
+ def register_attr_required name
86
+ define_method "attr_required[#{name}]" do
87
+ end
88
+
89
+ private "attr_required[#{name}]"
90
+ end
91
+
92
+ ATTR_REGEX = /^([^=]*?)=$/
93
+ def attributes
94
+ ( public_instance_methods + private_instance_methods ).select {|meth|
95
+ meth.to_s =~ ATTR_REGEX
96
+ }.map {|item|
97
+ item.to_s.sub(ATTR_REGEX) { $1 }
98
+ }
99
+ end
100
+
101
+ ATTR_REQUIRED_REGEX = /^attr_required\[(.*?)\]/
102
+ def required_attributes
103
+ private_instance_methods.select {|meth|
104
+ meth.to_s =~ ATTR_REQUIRED_REGEX
105
+ }.map {|item|
106
+ item.sub(ATTR_REQUIRED_REGEX) { $1 }
107
+ }
108
+ end
109
+ end
110
+
111
+ def initialize hash={}
112
+ before_init hash
113
+
114
+ unless hash && hash.kind_of?(Hash)
115
+ raise ArgumentError, "#{hash.inspect} was wrong as arguments. please specify kind of Hash instance"
116
+ end
117
+
118
+ hash = hash.inject({}) {|h,item| h[item.first.to_s] = item.last; h } # allow String or Symbol for key
119
+ self.class.required_attributes.each do |name|
120
+ raise AttrRequiredError, "param :#{name} is required to #{hash.inspect}" unless hash.keys.include?(name)
121
+ end
122
+ hash.each do |key,val|
123
+ if respond_to? "#{key}=", true
124
+ __send__ "#{key}=", val
125
+ end
126
+ end
127
+ private_methods.select do |meth|
128
+ meth.to_s =~ /^set_attr_default_value_of\[(.*?)\]$/
129
+ end.each do |meth|
130
+ __send__ meth
131
+ end
132
+ after_init
133
+ end
134
+
135
+ # just extend point
136
+ def before_init hash
137
+ end
138
+
139
+ def after_init
140
+ end
141
+
142
+ end
@@ -0,0 +1,102 @@
1
+
2
+ class ClassX
3
+ class AttrRequiredError < Exception; end
4
+ class InvalidSetterArgument < Exception; end
5
+ class LazyOptionShouldHaveDefault < Exception; end
6
+ class <<self
7
+ def has name, attrs={ :is => :ro, :required => false }
8
+ __send__ :attr_accessor, name
9
+
10
+ setter_definition = ''
11
+ if !attrs[:respond_to].nil?
12
+ setter_definition += <<-END_OF_RESPOND_TO
13
+ raise InvalidSetterArgument, "param :#{name}'s value \#{val.inspect} should respond_to #{attrs[:respond_to]}}" unless val.respond_to? #{attrs[:respond_to]}
14
+ END_OF_RESPOND_TO
15
+ end
16
+ if !attrs[:kind_of].nil?
17
+ setter_definition += <<-END_OF_KIND_OF
18
+ raise InvalidSetterArgument, "param :#{name}'s value \#{val.inspect} should kind_of #{attrs[:kind_of]}" unless val.kind_of? #{attrs[:kind_of]}
19
+ END_OF_KIND_OF
20
+ end
21
+
22
+ if !attrs[:default].nil?
23
+ case attrs[:default]
24
+ when Proc
25
+ register_attr_default_value_proc name, &attrs[:default]
26
+ else
27
+ register_attr_default_value name, attrs[:default]
28
+ end
29
+ else
30
+ raise LazyOptionShouldHaveDefault, "in :#{name}: :lazy option need specifying :default" if attrs[:lazy]
31
+ end
32
+
33
+ if attrs[:required]
34
+ register_attr_required name
35
+ end
36
+
37
+ self.class_eval <<-END_OF_ACCESSOR
38
+ attr_reader "#{name.to_s}"
39
+
40
+ def #{name.to_s}= val
41
+ #{setter_definition}
42
+ @#{name.to_s} = val
43
+ end
44
+ END_OF_ACCESSOR
45
+
46
+ if attrs[:is] == :ro
47
+ __send__ :private,"#{name.to_s}="
48
+ end
49
+ end
50
+
51
+ def register_attr_default_value name, value
52
+ self.class_eval do
53
+ define_method "set_attr_default_value_of[#{name.to_s}]" do
54
+ self.__send__ "#{name.to_s}=", value
55
+ end
56
+
57
+ private "set_attr_default_value_of[#{name.to_s}]"
58
+ end
59
+ end
60
+
61
+ def register_attr_default_value_proc name, &block
62
+ self.class_eval do
63
+ define_method "set_attr_default_value_of[#{name.to_s}]" do
64
+ self.__send__ "#{name.to_s}=", block.call(self)
65
+ end
66
+
67
+ private "set_attr_default_value_of[#{name.to_s}]"
68
+ end
69
+ end
70
+
71
+ def register_attr_required name
72
+ @@attr_required ||= {}
73
+ @@attr_required[name] = true
74
+ end
75
+ end
76
+
77
+ def initialize hash={}
78
+ before_init
79
+ @@attr_required ||= {}
80
+ @@attr_required.each do |req, is_required|
81
+ if is_required
82
+ raise AttrRequiredError, "param :#{req} is required to initialize #{self.class}" unless hash.keys.include?(req)
83
+ end
84
+ end
85
+ hash.each do |key,val|
86
+ __send__ "#{key.to_s}=", val
87
+ end
88
+ private_methods.select do |meth|
89
+ meth.to_s =~ /^set_attr_default_value_of\[(.*?)\]$/
90
+ end.each do |meth|
91
+ __send__ meth
92
+ end
93
+ after_init
94
+ end
95
+
96
+ # just extend point
97
+ def before_init
98
+ end
99
+
100
+ def after_init
101
+ end
102
+ end
@@ -0,0 +1,13 @@
1
+ class ClassX
2
+ class Attributes
3
+ attr_reader :name, :reader, :setter, :writable, :required
4
+ def initialize name, options={ :is => :ro }
5
+ @name = name.to_s
6
+
7
+ if options[:writable]
8
+ setter = proc.call {
9
+ }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ require 'optparse'
2
+
3
+ class ClassX
4
+ module Commandable
5
+ def from_argv argv=ARGV.dup
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,35 @@
1
+ module ClassX::Validate
2
+ private
3
+ #
4
+ # for validatation Hash parameter declaretively.
5
+ #
6
+ # require 'classx/validate'
7
+ #
8
+ # class YourClass < ClassX
9
+ # include Validate
10
+ #
11
+ # def run params
12
+ # validate params do
13
+ # has :x
14
+ # has :y, :default => "hoge", :kind_of => Hash
15
+ # end
16
+ #
17
+ # # do something with params
18
+ #
19
+ # end
20
+ # end
21
+ #
22
+ # YourClass.new.run(:x => 10) # raise ClassX::AttrRequiredError
23
+ #
24
+ def validate hash, &block
25
+ # FIXME: it's experimental feature for caching validate class.
26
+ # it can use class variable because it use caller[0] as key.
27
+ @@__validate_cached ||= {}
28
+ uniq_key = caller[0]
29
+ unless @@__validate_cached[uniq_key]
30
+ @@__validate_cached[uniq_key] = Class.new(ClassX)
31
+ @@__validate_cached[uniq_key].class_eval &block
32
+ end
33
+ @@__validate_cached[uniq_key].new hash
34
+ end
35
+ end
@@ -0,0 +1,261 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ require 'classx'
3
+
4
+ describe ClassX do
5
+ describe '#has' do
6
+ describe 'without accessor' do
7
+ before do
8
+ @class = Class.new(ClassX)
9
+ @class.class_eval do
10
+ end
11
+ end
12
+
13
+ it 'should not raise_error' do
14
+ lambda { @class.new }.should_not raise_error(Exception)
15
+ end
16
+
17
+ it 'should raise ArgumentError when recieved nil as initialize argument' do
18
+ lambda { @class.new(nil) }.should raise_error(ArgumentError)
19
+ end
20
+
21
+ it 'should raise ArgumentError when recieved not kind of Hash instance as initialize argument' do
22
+ lambda { @class.new([]) }.should raise_error(ArgumentError)
23
+ end
24
+
25
+ it 'should have empty attributes' do
26
+ @class.attributes.should be_empty
27
+ end
28
+ end
29
+
30
+ describe 'without any option' do
31
+ before do
32
+ @class = Class.new(ClassX)
33
+ @class.class_eval do
34
+ has :x
35
+ end
36
+ end
37
+
38
+ it 'should required :x on initialize' do
39
+ lambda { @class.new }.should raise_error(ClassX::AttrRequiredError)
40
+ end
41
+
42
+ it 'should define #x= private method to class' do
43
+ @class.private_instance_methods.map {|meth| meth.to_s }.should be_include("x=")
44
+ end
45
+ end
46
+
47
+ describe 'with :writable option' do
48
+ describe 'when you specify false for attribute' do
49
+ before do
50
+ @class = Class.new(ClassX)
51
+ @class.class_eval do
52
+ has :x, :writable => false
53
+ end
54
+ end
55
+
56
+ it 'should define #x public method to class' do
57
+ @class.instance_methods.map {|meth| meth.to_s }.should be_include('x')
58
+ end
59
+
60
+ it 'should define #x= private method to class' do
61
+ @class.private_instance_methods.map {|meth| meth.to_s }.should be_include("x=")
62
+ end
63
+
64
+ it 'should have attributes [:x]' do
65
+ @class.attributes.should == ['x']
66
+ end
67
+ end
68
+
69
+ describe 'when you specify true for attribute' do
70
+ before do
71
+ @class = Class.new(ClassX)
72
+ @class.class_eval do
73
+ has :x, :writable => true
74
+ end
75
+ end
76
+
77
+ it 'should define #x public method to class' do
78
+ @class.instance_methods.map {|meth| meth.to_s }.should be_include('x')
79
+ end
80
+
81
+ it 'should define #x= public method to class' do
82
+ @class.public_instance_methods.map {|meth| meth.to_s }.should be_include("x=")
83
+ end
84
+
85
+ it 'should have attributes [:x]' do
86
+ @class.attributes.should == ['x']
87
+ end
88
+ end
89
+ end
90
+
91
+ describe 'with :default option' do
92
+ describe 'when value is Proc' do
93
+ before do
94
+ @class = Class.new(ClassX)
95
+ @class.class_eval do
96
+ has :x, :default => proc { Object.new }
97
+ end
98
+ end
99
+
100
+ it 'shouold have any value when instanciate' do
101
+ @class.new.x.should_not be_nil
102
+ end
103
+
104
+ it 'should have difference of object_id between some instance' do
105
+ @class.new.x.should_not equal(@class.new.x)
106
+ end
107
+
108
+ # TODO: with lazy option
109
+ # it "can use self as Proc's argument" do
110
+ # @class.class_eval do
111
+ # has :y, :default => proc {|mine| mine.x }
112
+ # end
113
+
114
+ # @class.new.y.should equal(@class.new.x)
115
+ # end
116
+ end
117
+
118
+ describe 'when value is not Proc' do
119
+ before do
120
+ @class = Class.new(ClassX)
121
+ @class.class_eval do
122
+ has :x, :default => []
123
+ end
124
+ end
125
+
126
+ it 'should have any value when instanciate' do
127
+ @class.new.x.should == []
128
+ end
129
+
130
+ it 'should have the same object_id between some instance' do
131
+ @class.new.x.should equal(@class.new.x)
132
+ end
133
+ end
134
+ end
135
+
136
+ describe 'with :optional is false' do
137
+ before do
138
+ @class = Class.new(ClassX)
139
+ @class.class_eval do
140
+ has :x, :optional => false
141
+ end
142
+ end
143
+
144
+ it "should raise AttrRequiredError without value" do
145
+ lambda { @class.new }.should raise_error(ClassX::AttrRequiredError)
146
+ end
147
+
148
+ it "should not raise AttrRequiredError with value" do
149
+ lambda { @class.new(:x => Object.new) }.should_not raise_error(ClassX::AttrRequiredError)
150
+ end
151
+
152
+ it 'should not raise AttrRequiredError with key as String' do
153
+ lambda { @class.new('x' => Object.new) }.should_not raise_error(ClassX::AttrRequiredError)
154
+ end
155
+ end
156
+
157
+ describe ':optional is false and with :default option' do
158
+ it 'should raise ClassX::RequiredAttrShouldNotHaveDefault' do
159
+ lambda {
160
+ klass = Class.new(ClassX)
161
+ klass.class_eval do
162
+ has :x, :optional => false, :default => 1
163
+ end
164
+ }.should raise_error(ClassX::RequiredAttrShouldNotHaveDefault)
165
+ end
166
+ end
167
+
168
+ describe 'declare attribute without :optional and :default option' do
169
+ before do
170
+ @class = Class.new(ClassX)
171
+ @class.class_eval do
172
+ has :x, :kind_of => Integer
173
+ end
174
+ end
175
+
176
+ it 'should be required attribute' do
177
+ lambda { @class.new }.should raise_error(ClassX::AttrRequiredError)
178
+ end
179
+ end
180
+
181
+ describe ':optional is true and without :default option' do
182
+ before do
183
+ @class = Class.new(ClassX)
184
+ @class.class_eval do
185
+ has :x, :optional => true, :kind_of => Integer
186
+ end
187
+ end
188
+
189
+ it 'should be required attribute' do
190
+ lambda { @class.new }.should_not raise_error(ClassX::AttrRequiredError)
191
+ end
192
+ end
193
+
194
+ describe 'with multiple class' do
195
+ before do
196
+ @class1 = Class.new(ClassX)
197
+ @class1.class_eval do
198
+ has :x
199
+ end
200
+ @class2 = Class.new(ClassX)
201
+ @class2.class_eval do
202
+ end
203
+ end
204
+
205
+ it 'should not raise AttrRequiredError when initialized anothor class' do
206
+ lambda { @class2.new }.should_not raise_error(ClassX::AttrRequiredError)
207
+ end
208
+ end
209
+
210
+ describe 'with :optional is true' do
211
+ describe 'without :writable option' do
212
+ before do
213
+ @class = Class.new(ClassX)
214
+ @class.class_eval do
215
+ has :x, :optional => true
216
+ end
217
+ end
218
+ it 'should not raise AttrRequiredError' do
219
+ lambda { @class.new }.should_not raise_error(ClassX::AttrRequiredError)
220
+ end
221
+ end
222
+
223
+ describe 'with :writable is false' do
224
+ it 'should raise ClassX::OptionalAttrShouldBeWritable' do
225
+ lambda {
226
+ klass = Class.new(ClassX)
227
+ klass.class_eval do
228
+ has :x, :optional => true, :writable => false
229
+ end
230
+ }.should raise_error(ClassX::OptionalAttrShouldBeWritable)
231
+ end
232
+ end
233
+
234
+ describe 'with :writable is true' do
235
+ it 'should raise ClassX::OptionalAttrShouldBeWritable' do
236
+ lambda {
237
+ klass = Class.new(ClassX)
238
+ klass.class_eval do
239
+ has :x, :optional => true, :writable => true
240
+ end
241
+ }.should_not raise_error(ClassX::OptionalAttrShouldBeWritable)
242
+ end
243
+ end
244
+ end
245
+
246
+ describe 'not attribute param exist in #initialize argument' do
247
+ before do
248
+ @class = Class.new(ClassX)
249
+ @class.class_eval do
250
+ has :x
251
+ end
252
+ end
253
+
254
+ # TODO: I'll change it to be able to choosee wheather check this strictly or not.
255
+ # In many case, lack argument cause any problem. On the other hand, extra argument does not cause any problem, I think.
256
+ it 'should be ignored' do
257
+ lambda { @class.new(:x => 10, :y => 20 ) }.should_not raise_error(Exception)
258
+ end
259
+ end
260
+ end
261
+ end