classx 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/ChangeLog +354 -0
  2. data/README +5 -0
  3. data/Rakefile +2 -2
  4. data/bench/attribute_get.rb +73 -0
  5. data/bench/attribute_set.rb +53 -19
  6. data/bench/define_attribute.rb +226 -0
  7. data/bench/initialize.rb +25 -7
  8. data/doc/output/coverage/index.html +74 -128
  9. data/doc/output/coverage/lib-classx-attribute_rb.html +291 -190
  10. data/doc/output/coverage/lib-classx-attributes_rb.html +167 -101
  11. data/doc/output/coverage/lib-classx-bracketable_rb.html +671 -0
  12. data/doc/output/coverage/lib-classx-class_attributes_rb.html +775 -0
  13. data/doc/output/coverage/lib-classx-commandable_rb.html +727 -0
  14. 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
  15. data/doc/output/coverage/lib-classx-validate_rb.html +43 -41
  16. data/doc/output/coverage/lib-classx_rb.html +208 -78
  17. data/example/commandable.rb +1 -0
  18. data/lib/classx.rb +146 -16
  19. data/lib/classx/attribute.rb +244 -143
  20. data/lib/classx/attributes.rb +93 -27
  21. data/lib/classx/bracketable.rb +61 -0
  22. data/lib/classx/class_attributes.rb +165 -0
  23. data/lib/classx/commandable.rb +55 -4
  24. data/lib/classx/declare.rb +40 -3
  25. data/lib/classx/role/logger.rb +17 -13
  26. data/lib/classx/validate.rb +26 -24
  27. data/spec/classx/handles_spec.rb +21 -6
  28. data/spec/classx/serialize_spec.rb +57 -0
  29. data/spec/classx/{with_coerce.rb → with_coerce_spec.rb} +0 -0
  30. data/spec/classx/with_extend_spec.rb +58 -0
  31. data/spec/classx/with_include_spec.rb +58 -0
  32. data/spec/classx/with_validate_spec.rb +363 -0
  33. data/spec/classx/without_anyoption_spec.rb +1 -1
  34. data/spec/classx/writable_option_spec.rb +29 -4
  35. data/spec/classx_bracketable_spec.rb +160 -0
  36. data/spec/classx_class_attributes/default_option_spec.rb +121 -0
  37. data/spec/classx_class_attributes/dsl_accessor_spec.rb +88 -0
  38. data/spec/classx_class_attributes/handles_spec.rb +77 -0
  39. data/spec/classx_class_attributes/with_coerce_spec.rb +119 -0
  40. data/spec/classx_class_attributes/with_extend_spec.rb +64 -0
  41. data/spec/classx_class_attributes/with_include_spec.rb +64 -0
  42. data/spec/classx_class_attributes/with_multiple_class_spec.rb +60 -0
  43. data/spec/classx_class_attributes/with_validate_spec.rb +248 -0
  44. data/spec/classx_class_attributes/without_accessor_spec.rb +19 -0
  45. data/spec/classx_class_attributes/without_anyoption_spec.rb +21 -0
  46. data/spec/classx_class_attributes/writable_option_spec.rb +100 -0
  47. data/spec/classx_declare_spec.rb +117 -0
  48. data/spec/classx_validate_spec.rb +1 -3
  49. data/tasks/basic_tasks.rake +1 -1
  50. metadata +36 -26
  51. data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-callbacks_rb.html +0 -932
  52. data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-change_rb.html +0 -779
  53. data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-hunk_rb.html +0 -867
  54. data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs_rb.html +0 -1715
  55. data/doc/output/coverage/-Library-Ruby-Gems-gems-rcov-0_8_1_2_0-lib-rcov_rb.html +0 -1598
  56. data/spec/classx/with_extend.rb +0 -27
  57. data/spec/classx/with_include.rb +0 -27
@@ -18,7 +18,7 @@ describe ClassX do
18
18
  end
19
19
 
20
20
  it 'should define #x= private method to class' do
21
- @class.private_instance_methods.map {|meth| meth.to_s }.should be_include("x=")
21
+ @class.private_instance_methods.map {|meth| meth.to_s }.should include("x=")
22
22
  end
23
23
  end
24
24
  end
@@ -14,16 +14,29 @@ describe ClassX do
14
14
  end
15
15
 
16
16
  it 'should define #x public method to class' do
17
- @class.instance_methods.map {|meth| meth.to_s }.should be_include('x')
17
+ @class.instance_methods.map {|meth| meth.to_s }.should include('x')
18
18
  end
19
19
 
20
20
  it 'should define #x= private method to class' do
21
- @class.private_instance_methods.map {|meth| meth.to_s }.should be_include("x=")
21
+ @class.private_instance_methods.map {|meth| meth.to_s }.should include("x=")
22
22
  end
23
23
 
24
24
  it 'should have attributes [:x]' do
25
25
  @class.attribute_of.keys.should == ['x']
26
26
  end
27
+
28
+ it 'should raise NoMethodError using attr_name = val' do
29
+ instance = @class.new(:x => 10)
30
+ lambda { instance.x = 20 }.should raise_error(NoMethodError)
31
+ end
32
+
33
+ # NOTE: why don't it unify Exception Class between above and this?
34
+ # => This exception was caused by mistake of program. So, in general I think, you should not
35
+ # rascue this error.
36
+ it 'should raise RuntimeError using attr_name(val)' do
37
+ instance = @class.new(:x => 10)
38
+ lambda { instance.x(20) }.should raise_error(RuntimeError)
39
+ end
27
40
  end
28
41
 
29
42
  describe 'when you specify true for attribute' do
@@ -36,16 +49,28 @@ describe ClassX do
36
49
  end
37
50
 
38
51
  it 'should define #x public method to class' do
39
- @class.instance_methods.map {|meth| meth.to_s }.should be_include('x')
52
+ @class.instance_methods.map {|meth| meth.to_s }.should include('x')
40
53
  end
41
54
 
42
55
  it 'should define #x= public method to class' do
43
- @class.public_instance_methods.map {|meth| meth.to_s }.should be_include("x=")
56
+ @class.public_instance_methods.map {|meth| meth.to_s }.should include("x=")
44
57
  end
45
58
 
46
59
  it 'should have attributes [:x]' do
47
60
  @class.attribute_of.keys.should == ['x']
48
61
  end
62
+
63
+ it 'should update value using attr_name = val' do
64
+ instance = @class.new(:x => 10)
65
+ instance.x = 20
66
+ instance.x.should == 20
67
+ end
68
+
69
+ it 'should update value using attr_name(val)' do
70
+ instance = @class.new(:x => 10)
71
+ instance.x(20)
72
+ instance.x.should == 20
73
+ end
49
74
  end
50
75
 
51
76
  end
@@ -0,0 +1,160 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ require 'classx'
3
+ require 'classx/bracketable'
4
+
5
+ describe ClassX::Bracketable do
6
+ describe 'for attribute' do
7
+ describe 'with writable attribute' do
8
+ before do
9
+ @class = Class.new
10
+ @class.class_eval do
11
+ include ClassX
12
+ include ClassX::Bracketable
13
+
14
+ has :x, :writable => true
15
+ end
16
+
17
+ @obj = @class.new(:x => 10)
18
+ end
19
+
20
+ it 'should be able to access Hash like interface' do
21
+ @obj[:x].should == 10
22
+ end
23
+
24
+ it 'should return nil when you access non-attribute class' do
25
+ @obj[:y].should be_nil
26
+ end
27
+
28
+ it 'should be able to set value' do
29
+ @obj[:x] = 20
30
+ @obj[:x].should == 20
31
+ end
32
+ end
33
+
34
+ describe 'with non-writable attribute' do
35
+ before do
36
+ @class = Class.new
37
+ @class.class_eval do
38
+ include ClassX
39
+ include ClassX::Bracketable
40
+
41
+ has :x, :writable => false
42
+ end
43
+
44
+ @obj = @class.new(:x => 10)
45
+ end
46
+
47
+ it 'should be able to access Hash like interface' do
48
+ @obj[:x].should == 10
49
+ end
50
+
51
+ it 'should return nil when you access non-attribute class' do
52
+ @obj[:y].should be_nil
53
+ end
54
+
55
+ it 'should be raise NoMethodError in setting value to non writable attribute' do
56
+ lambda { @obj[:x] = 20 }.should raise_error(NoMethodError)
57
+ end
58
+ end
59
+
60
+ describe 'with non-attribute method' do
61
+ before do
62
+ @class = Class.new
63
+ @class.class_eval do
64
+ include ClassX
65
+ include ClassX::Bracketable
66
+
67
+ has :x
68
+
69
+ attr_accessor :y
70
+ end
71
+
72
+ @obj = @class.new(:x => 10)
73
+ @obj.y = 10
74
+ end
75
+
76
+ it 'should be able to access attrubte as Hash like interface' do
77
+ @obj[:x].should == 10
78
+ end
79
+
80
+ it 'should return nil when you access non-attribute class' do
81
+ @obj[:y].should be_nil
82
+ end
83
+ end
84
+ end
85
+
86
+ describe 'for class attribute' do
87
+ describe 'with writable class attribute' do
88
+ before do
89
+ @class = Class.new
90
+ @class.class_eval do
91
+ extend ClassX::CAttrs
92
+ extend ClassX::Bracketable
93
+
94
+ class_has :x, :writable => true
95
+
96
+ self.x = 10
97
+ end
98
+ end
99
+
100
+ it 'should be able to access class attribute as Hash like interface' do
101
+ @class[:x].should == 10
102
+ end
103
+
104
+ it 'should return nil when you access non-class-attribute class' do
105
+ @class[:y].should be_nil
106
+ end
107
+
108
+ it 'should be able to set value' do
109
+ @class[:x] = 20
110
+ @class[:x].should == 20
111
+ end
112
+ end
113
+
114
+ describe 'with non-writable class attribute' do
115
+ before do
116
+ @class = Class.new
117
+ @class.class_eval do
118
+ extend ClassX::CAttrs
119
+ extend ClassX::Bracketable
120
+
121
+ class_has :x, :writable => false
122
+
123
+ self.x = 10
124
+ end
125
+ end
126
+
127
+ it 'should be able to access class attribute as Hash like interface' do
128
+ @class[:x].should == 10
129
+ end
130
+
131
+ it 'should return nil when you access non-class-attribute class' do
132
+ @class[:y].should be_nil
133
+ end
134
+
135
+ it 'should be raise NoMethodError in setting value to non writable class attribute' do
136
+ lambda { @class[:x] = 20 }.should raise_error(NoMethodError)
137
+ end
138
+ end
139
+ end
140
+
141
+ describe 'for non-ClassX class' do
142
+ before do
143
+ @class = Class.new
144
+ @class.class_eval do
145
+ include ClassX::Bracketable
146
+ end
147
+
148
+ @obj = @class.new
149
+ end
150
+
151
+ it 'should return nil' do
152
+ @obj[:x].should be_nil
153
+ end
154
+
155
+ it 'should return nil' do
156
+ @obj[:x] = 20
157
+ @obj[:x].should be_nil
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,121 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+ require 'classx'
3
+ require 'classx/attribute'
4
+ require 'classx/class_attributes'
5
+
6
+ describe ClassX::ClassAttributes do
7
+ describe '#class_has' do
8
+ describe 'with :default option' do
9
+ describe 'when value is Proc' do
10
+ before do
11
+ @class = Class.new
12
+ @class.class_eval do
13
+ extend ClassX::ClassAttributes
14
+ class_has :x, :default => proc { Object.new }
15
+ end
16
+ end
17
+
18
+ it 'should have any value accessing accessor' do
19
+ @class.x.should_not be_nil
20
+ end
21
+
22
+ it "can use self as Proc's argument" do
23
+ @class.class_eval do
24
+ class_has :y, :default => proc {|mine| mine.x }, :lazy => true
25
+ class_has :z, :default => proc {|mine| mine.y }, :lazy => true
26
+ end
27
+
28
+ @class.y.should equal(@class.x)
29
+ @class.z.should equal(@class.y)
30
+ end
31
+ end
32
+
33
+ describe 'when value is not Proc' do
34
+ before do
35
+ @class = Class.new
36
+ @class.class_eval do
37
+ extend ClassX::ClassAttributes
38
+ class_has :x, :default => []
39
+ end
40
+ end
41
+
42
+ it 'should have any value when instanciate' do
43
+ @class.x.should == []
44
+ end
45
+ end
46
+ end
47
+
48
+ describe 'with :optional is false' do
49
+ before do
50
+ @class = Class.new
51
+ @class.class_eval do
52
+ extend ClassX::ClassAttributes
53
+ class_has :x, :optional => false
54
+ end
55
+ end
56
+
57
+ it "should raise AttrRequiredError without value" do
58
+ lambda { @class.x }.should raise_error(ClassX::AttrRequiredError)
59
+ end
60
+
61
+ it "should not raise AttrRequiredError with value" do
62
+ lambda { @class.x = Object.new; @class.x }.should_not raise_error(ClassX::AttrRequiredError)
63
+ end
64
+ end
65
+
66
+ describe ':optional is false and with :default option' do
67
+ it 'should raise ClassX::RequiredAttrShouldNotHaveDefault' do
68
+ lambda {
69
+ klass = Class.new
70
+ klass.class_eval do
71
+ extend ClassX::ClassAttributes
72
+ class_has :x, :optional => false, :default => 1
73
+ end
74
+ }.should raise_error(ClassX::RequiredAttrShouldNotHaveDefault)
75
+ end
76
+ end
77
+
78
+ describe 'declare attribute without :optional and :default option' do
79
+ before do
80
+ @class = Class.new
81
+ @class.class_eval do
82
+ extend ClassX::ClassAttributes
83
+ class_has :x, :kind_of => Integer
84
+ end
85
+ end
86
+
87
+ it 'should be required attribute' do
88
+ lambda { @class.x }.should raise_error(ClassX::AttrRequiredError)
89
+ end
90
+ end
91
+
92
+ describe ':optional is true and without :default option' do
93
+ before do
94
+ @class = Class.new
95
+ @class.class_eval do
96
+ extend ClassX::ClassAttributes
97
+ class_has :x, :optional => true, :kind_of => Integer
98
+ end
99
+ end
100
+
101
+ it 'should not be required attribute' do
102
+ lambda { @class.x }.should_not raise_error(ClassX::AttrRequiredError)
103
+ end
104
+ end
105
+
106
+ describe 'with :optional is true' do
107
+ describe 'without :writable option' do
108
+ before do
109
+ @class = Class.new
110
+ @class.class_eval do
111
+ extend ClassX::ClassAttributes
112
+ class_has :x, :optional => true
113
+ end
114
+ end
115
+ it 'should not raise AttrRequiredError' do
116
+ lambda { @class.x }.should_not raise_error(ClassX::AttrRequiredError)
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,88 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+ require 'classx'
3
+
4
+ # This test come from dsl_accessor's test/default_test.rb
5
+
6
+ describe ClassX::ClassAttributes do
7
+ describe 'DSLAccessor compatible' do
8
+ describe "normal usage" do
9
+ before :all do
10
+ class CoolActiveRecord
11
+ extend ClassX::ClassAttributes
12
+ class_has :primary_key, :default => proc { "id" }
13
+ class_has :table_name, :default => proc {|klass| klass.to_s.split(/::/).last.downcase } # ruby 1.9.0 return klass.to_s as "<Class:0x725470>::Item"
14
+ end
15
+
16
+ class Item < CoolActiveRecord
17
+ end
18
+
19
+ class User < CoolActiveRecord
20
+ end
21
+
22
+ class Folder
23
+ extend ClassX::ClassAttributes
24
+ class_has :array_folder, :default => []
25
+ class_has :hash_folder, :default => {}
26
+ end
27
+
28
+ class SubFolder < Folder
29
+ end
30
+ end
31
+
32
+ it "should get default value when it was not setted value" do
33
+ Item.primary_key.should == "id"
34
+ end
35
+
36
+ it 'should also be able to get default in subclass' do
37
+ User.primary_key.should == "id"
38
+ end
39
+
40
+ it "should be able to using Proc with default value" do
41
+ Item.table_name.should == "item"
42
+ end
43
+
44
+ it "should also be able to using Proc with default value in subclass" do
45
+ User.table_name.should == "user"
46
+ end
47
+
48
+ it 'should be modifiable' do
49
+ Folder.array_folder.should == []
50
+ Folder.array_folder << 1
51
+ Folder.array_folder.should == [1]
52
+
53
+ Folder.hash_folder.should == {}
54
+ Folder.hash_folder[:name] = 'walf443'
55
+ Folder.hash_folder.should == {:name => "walf443"}
56
+ end
57
+
58
+ it 'should not be affect modification of parent class attribute to subclass ' do
59
+ Folder.array_folder << 1
60
+ SubFolder.array_folder.should == []
61
+
62
+ Folder.hash_folder[:name] = 'walf443'
63
+ SubFolder.hash_folder == {}
64
+ end
65
+ end
66
+
67
+ describe "overwrite class accessor in subclass" do
68
+ before :all do
69
+ class CoolActiveRecord
70
+ extend ClassX::ClassAttributes
71
+
72
+ class_has :primary_key, :default=>"id"
73
+ class_has :table_name, :default=>proc{|klass| klass.to_s.downcase}
74
+ end
75
+
76
+ class Item < CoolActiveRecord
77
+ primary_key :item_id
78
+ table_name :item_table
79
+ end
80
+ end
81
+
82
+ it 'should be affect modification in subclass' do
83
+ Item.primary_key.should == :item_id
84
+ Item.table_name.should == :item_table
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,77 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+ require 'classx'
3
+
4
+ describe ClassX::ClassAttributes do
5
+ describe '#class_has' do
6
+ describe 'with handles option as Hash' do
7
+ before do
8
+ @class1 = Class.new
9
+ @class1.class_eval do
10
+ extend ClassX::ClassAttributes
11
+ class_has :x, :handles => {
12
+ :x_inspect => :inspect,
13
+ :x_slice => :slice
14
+ }
15
+ end
16
+ end
17
+
18
+ it 'should respond_to x_inspect method' do
19
+ obj = []
20
+ @class1.respond_to?(:x_inspect).should be_true
21
+ end
22
+
23
+ it 'should delegate method to value' do
24
+ obj = []
25
+ @class1.class_eval do
26
+ self.x = obj
27
+ end
28
+ @class1.x_inspect.should == obj.inspect
29
+ end
30
+
31
+ it 'should delegate method with args to value' do
32
+ obj = []
33
+ obj.push 1
34
+ @class1.class_eval do
35
+ self.x = obj
36
+ end
37
+ @class1.x_slice(0).should == obj.slice(0)
38
+ end
39
+ end
40
+
41
+ describe 'with handles option as Array' do
42
+ before do
43
+ @class1 = Class.new
44
+ @class1.class_eval do
45
+ extend ClassX::ClassAttributes
46
+
47
+ class_has :x, :handles => [ :length, :slice ]
48
+ end
49
+ end
50
+
51
+ it 'should respond_to item name method' do
52
+ obj = [1, 2, 3]
53
+ @class1.class_eval do
54
+ self.x = obj
55
+ end
56
+ @class1.respond_to?(:length).should be_true
57
+ end
58
+
59
+ it 'should delegate method to the same item name' do
60
+ obj = [1, 2, 3]
61
+ @class1.class_eval do
62
+ self.x = obj
63
+ end
64
+ @class1.length.should == obj.length
65
+ end
66
+
67
+ it 'should delegate method with args to value' do
68
+ obj = [1, 2, 3]
69
+ obj.push 1
70
+ @class1.class_eval do
71
+ self.x = obj
72
+ end
73
+ @class1.slice(0).should == obj.slice(0)
74
+ end
75
+ end
76
+ end
77
+ end