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