classx 0.0.1

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.
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