ruby_ext 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/Rakefile +64 -0
  2. data/lib/ruby_ext/array.rb +13 -0
  3. data/lib/ruby_ext/basic_object.rb +22 -0
  4. data/lib/ruby_ext/class.rb +11 -0
  5. data/lib/ruby_ext/declarative_cache.rb +85 -0
  6. data/lib/ruby_ext/deep_clone.rb +62 -0
  7. data/lib/ruby_ext/extra_blank_slate.rb +16 -0
  8. data/lib/ruby_ext/file.rb +20 -0
  9. data/lib/ruby_ext/hash.rb +15 -0
  10. data/lib/ruby_ext/kernel.rb +69 -0
  11. data/lib/ruby_ext/micelaneous.rb +14 -0
  12. data/lib/ruby_ext/module.rb +119 -0
  13. data/lib/ruby_ext/multiple_inheritance.rb +76 -0
  14. data/lib/ruby_ext/must.rb +192 -0
  15. data/lib/ruby_ext/not_defined.rb +2 -0
  16. data/lib/ruby_ext/object.rb +8 -0
  17. data/lib/ruby_ext/observable2.rb +23 -0
  18. data/lib/ruby_ext/open_constructor.rb +51 -0
  19. data/lib/ruby_ext/open_object.rb +157 -0
  20. data/lib/ruby_ext/prepare_arguments.rb +105 -0
  21. data/lib/ruby_ext/prototype_inheritance.rb +110 -0
  22. data/lib/ruby_ext/should.rb +166 -0
  23. data/lib/ruby_ext/string.rb +44 -0
  24. data/lib/ruby_ext/symbol.rb +21 -0
  25. data/lib/ruby_ext/synchronize.rb +24 -0
  26. data/lib/ruby_ext/tuple.rb +7 -0
  27. data/lib/ruby_ext.rb +50 -0
  28. data/lib/spec_ext.rb +10 -0
  29. data/readme.md +66 -0
  30. data/spec/_prototype_inheritance_spec.rb +190 -0
  31. data/spec/array_spec.rb +8 -0
  32. data/spec/declarative_cache_spec.rb +115 -0
  33. data/spec/deep_clone_spec.rb +37 -0
  34. data/spec/helper.rb +20 -0
  35. data/spec/kernel_spec/TheNamespace/ClassA.rb +7 -0
  36. data/spec/kernel_spec/another_class.rb +5 -0
  37. data/spec/kernel_spec/the_namespace/class_b.rb +11 -0
  38. data/spec/kernel_spec.rb +53 -0
  39. data/spec/module_spec.rb +160 -0
  40. data/spec/multiple_inheritance_spec.rb +131 -0
  41. data/spec/must_spec.rb +29 -0
  42. data/spec/observable2_spec.rb +42 -0
  43. data/spec/open_constructor_spec.rb +36 -0
  44. data/spec/open_object_spec.rb +29 -0
  45. data/spec/prepare_arguments_spec.rb +46 -0
  46. data/spec/should_spec.rb +24 -0
  47. data/spec/spec.opts +2 -0
  48. data/spec/synchronize_spec.rb +80 -0
  49. metadata +127 -0
@@ -0,0 +1,37 @@
1
+ require "#{File.dirname __FILE__}/helper"
2
+ require "ruby_ext/deep_clone"
3
+
4
+ describe 'deep_clone' do
5
+ it "basic" do
6
+ hash, array = {}, ['value']
7
+ hash['key'] = array
8
+
9
+ hash2 = hash.deep_clone
10
+ array2 = hash2['key']
11
+
12
+ hash2.should == hash
13
+ hash2.object_id.should_not == hash.object_id
14
+
15
+ array2.should == array
16
+ array2.object_id.should_not == array.object_id
17
+ end
18
+
19
+ it do
20
+ class Metadata
21
+ attr_accessor :registry
22
+
23
+ def initialize
24
+ @registry = {}
25
+ end
26
+ end
27
+
28
+ m = Metadata.new
29
+ m.registry[:a] = 1
30
+
31
+ m2 = m.deep_clone
32
+ m2.registry.should include(:a)
33
+ m2.registry[:b] = 2
34
+
35
+ m.registry.should == {:a => 1}
36
+ end
37
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'spec'
2
+ require 'spec_ext'
3
+
4
+ ruby_ext_dir = File.expand_path("#{File.dirname(__FILE__)}/../..")
5
+ $LOAD_PATH << "#{ruby_ext_dir}/lib"
6
+
7
+ %w{
8
+ file
9
+ kernel
10
+ open_object
11
+ module
12
+ not_defined
13
+ object
14
+ class
15
+ string
16
+ symbol
17
+ extra_blank_slate
18
+ must
19
+ deep_clone
20
+ }.each{|f| require "ruby_ext/#{f}"}
@@ -0,0 +1,7 @@
1
+ module TheNamespace
2
+ class ClassA
3
+ def self.problem_method
4
+ raise_without_self "Some problem"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ class AnotherClass
2
+ def self.exclude_multiple_classes
3
+ TheNamespace::ClassB.exclude_multiple_classes
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ module TheNamespace
2
+ class ClassB
3
+ def self.problem_method
4
+ raise_without_self "Some problem"
5
+ end
6
+
7
+ def self.exclude_multiple_classes
8
+ raise_without_self "Some problem", AnotherClass
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,53 @@
1
+ require "#{File.dirname __FILE__}/helper"
2
+ require "ruby_ext/kernel"
3
+
4
+ describe 'Kernel' do
5
+ class Respond
6
+ def test; 2 end
7
+ end
8
+
9
+ after :all do
10
+ [:TheNamespace, :AnotherClass].each{|c| Object.send :remove_const, c if Object.const_defined? c}
11
+ end
12
+
13
+ it "respond_to" do
14
+ r = Respond.new
15
+ r.respond_to(:not_exist).should be_nil
16
+ r.respond_to(:test).should == 2
17
+ end
18
+
19
+ it "raise_without_self" do
20
+ dir = File.dirname __FILE__
21
+ require "#{dir}/kernel_spec/TheNamespace/ClassA"
22
+ require "#{dir}/kernel_spec/the_namespace/class_b"
23
+ require "#{dir}/kernel_spec/another_class"
24
+
25
+ begin
26
+ TheNamespace::ClassA.problem_method
27
+ rescue StandardError => e
28
+ e.message.should =~ /Some problem/
29
+ stack = e.backtrace
30
+ stack.any?{|line| line =~ /ClassA/}.should be_false
31
+ stack.any?{|line| line =~ /kernel_spec/}.should be_true
32
+ end
33
+
34
+ begin
35
+ TheNamespace::ClassB.problem_method
36
+ rescue StandardError => e
37
+ e.message.should =~ /Some problem/
38
+ stack = e.backtrace
39
+ stack.any?{|line| line =~ /class_b/}.should be_false
40
+ stack.any?{|line| line =~ /kernel_spec/}.should be_true
41
+ end
42
+
43
+ begin
44
+ AnotherClass.exclude_multiple_classes
45
+ rescue StandardError => e
46
+ e.message.should =~ /Some problem/
47
+ stack = e.backtrace
48
+ stack.any?{|line| line =~ /class_b/}.should be_false
49
+ stack.any?{|line| line =~ /another_class/}.should be_false
50
+ stack.any?{|line| line =~ /kernel_spec/}.should be_true
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,160 @@
1
+ require "#{File.dirname __FILE__}/helper"
2
+ require "ruby_ext/module"
3
+ require 'ruby_ext/multiple_inheritance'
4
+
5
+ describe "Module" do
6
+ after :each do
7
+ remove_constants %w(
8
+ A X Y Z
9
+ InheritableAccessorForModule
10
+ InheritableAccessorForClass
11
+ InheritableAccessor
12
+ InheritableAccessorBase
13
+ InheritableAccessorA
14
+ InheritableAccessorB
15
+ )
16
+ end
17
+
18
+ it "Namespace" do
19
+ class A
20
+ class B
21
+ class C
22
+
23
+ end
24
+ end
25
+ end
26
+
27
+ File.namespace.should == nil
28
+ A::B::C.namespace.should == A::B
29
+ end
30
+
31
+ # class AnonymousClass
32
+ # class << self
33
+ # def anonymous_name
34
+ # self.name
35
+ # end
36
+ # end
37
+ # end
38
+
39
+ it "name" do
40
+ class A
41
+ class B
42
+ class C
43
+
44
+ end
45
+ end
46
+ end
47
+
48
+ A::B::C.name.should == "A::B::C"
49
+ end
50
+
51
+ it "each_ancestor" do
52
+ class X; end
53
+ class Y < X; end
54
+ class Z < Y; end
55
+
56
+ list = []
57
+ Z.each_ancestor{|a| list << a}
58
+ list.should include Y
59
+ list.should include X
60
+ list.should_not include Z
61
+ list.should_not include Object
62
+ list.should_not include Kernel
63
+
64
+ list = []
65
+ Z.each_ancestor(true){|a| list << a}
66
+ list.should include Y
67
+ list.should include X
68
+ list.should_not include Z
69
+ list.should include Object
70
+ list.should include Kernel
71
+ end
72
+
73
+ it "each_namespace" do
74
+ class A
75
+ class B
76
+ class C
77
+
78
+ end
79
+ end
80
+ end
81
+
82
+ list = []
83
+ A::B::C.each_namespace{|n| list << n}
84
+ list.should == [A::B, A]
85
+ end
86
+
87
+ it "is?" do
88
+ File.is?(IO).should be_true
89
+ end
90
+
91
+ class WrapMethod
92
+ def method_name value
93
+ 10*value
94
+ end
95
+ end
96
+
97
+ it "wrap_method" do
98
+ WrapMethod.wrap_method :method_name do |old, value|
99
+ send(old, value)*value
100
+ end
101
+ WrapMethod.new.method_name(10).should == 1000
102
+ end
103
+
104
+ it "escape_method" do
105
+ Object.escape_method("><=?")
106
+ end
107
+
108
+ it "inheritable_accessor" do
109
+ module InheritableAccessorForModule
110
+ module ClassMethods
111
+ inheritable_accessor :callbacks, [:set_user]
112
+ inheritable_accessor :layout, "for_module"
113
+ end
114
+ end
115
+
116
+ class InheritableAccessorForClass
117
+ class << self
118
+ inheritable_accessor :callbacks2, []
119
+ inheritable_accessor :layout2, "for_class"
120
+ end
121
+ callbacks2 << :set_user
122
+ end
123
+
124
+ class InheritableAccessor < InheritableAccessorForClass
125
+ inherit InheritableAccessorForModule
126
+ callbacks << :set_model
127
+ callbacks2 << :set_model
128
+ self.layout2 = "anoter_layout"
129
+ end
130
+
131
+ InheritableAccessorForClass.callbacks2.should == [:set_user]
132
+ InheritableAccessor.callbacks.should == [:set_user, :set_model]
133
+ InheritableAccessor.callbacks2.should == [:set_user, :set_model]
134
+
135
+ InheritableAccessorForClass.layout2.should == "for_class"
136
+ InheritableAccessor.layout2.should == "anoter_layout"
137
+ InheritableAccessor.layout.should == "for_module"
138
+ end
139
+
140
+ it "inheritable_accessor (from error)" do
141
+ module InheritableAccessorBase
142
+ module ClassMethods
143
+ inheritable_accessor :callbacks, []
144
+ end
145
+ end
146
+
147
+ class InheritableAccessorA
148
+ inherit InheritableAccessorBase
149
+ callbacks << :a
150
+ end
151
+
152
+ class InheritableAccessorB
153
+ inherit InheritableAccessorBase
154
+ callbacks << :b
155
+ end
156
+
157
+ InheritableAccessorA.callbacks.should == [:a]
158
+ InheritableAccessorB.callbacks.should == [:b]
159
+ end
160
+ end
@@ -0,0 +1,131 @@
1
+ require "#{File.dirname __FILE__}/helper"
2
+ require "ruby_ext/multiple_inheritance"
3
+
4
+ describe "Multiple Inheritance" do
5
+ after :each do
6
+ remove_constants %w(M A M2 B AddedAfterInheritance)
7
+ end
8
+
9
+ it "showcase" do
10
+ module M
11
+ def instance_method; end
12
+
13
+ class_methods do
14
+ def class_method; end
15
+ end
16
+
17
+ def self.inherited target
18
+ target.send :attr_accessor, :some_accessor
19
+ end
20
+ end
21
+
22
+ M.should respond_to(:class_method)
23
+
24
+ class A
25
+ inherit M
26
+ end
27
+
28
+ A.should respond_to(:class_method)
29
+ A.new.should respond_to(:instance_method)
30
+ A.new.should respond_to(:some_accessor)
31
+
32
+ M.directly_included_by.should == [A].to_set
33
+ end
34
+
35
+ it "should inherit all ancestors class methods" do
36
+ module M
37
+ def instance_method; end
38
+
39
+ class_methods do
40
+ def class_method; end
41
+ end
42
+ end
43
+
44
+ module M2
45
+ inherit M
46
+
47
+ class_methods do
48
+ def class_method2; end
49
+ end
50
+ end
51
+
52
+ class B
53
+ inherit M2
54
+ end
55
+
56
+ M2.should respond_to(:class_method)
57
+
58
+ B.should respond_to(:class_method)
59
+ B.should respond_to(:class_method2)
60
+ B.new.should respond_to(:instance_method)
61
+
62
+ M.directly_included_by.should == [M2].to_set
63
+ M2.directly_included_by.should == [B].to_set
64
+ end
65
+
66
+ it "shouldn't redefine ancestors class methods" do
67
+ module M
68
+ class_methods do
69
+ def class_method; end
70
+ end
71
+ end
72
+
73
+ module M2
74
+ inherit M
75
+
76
+ class_methods do
77
+ def class_method2; end
78
+ end
79
+ end
80
+
81
+ class A
82
+ inherit M
83
+ end
84
+
85
+ A.should_not respond_to(:class_method2)
86
+ end
87
+
88
+ it "should also allow to explicitly use ClassMethods prototype (from error)" do
89
+ module A
90
+ module ClassMethods
91
+ attr_accessor :callbacks
92
+ end
93
+ end
94
+
95
+ class B
96
+ inherit A
97
+ end
98
+
99
+ B.should respond_to(:callbacks)
100
+ end
101
+
102
+ it "methods defined on base class after inheritance must be propagated to all descendants" do
103
+ module M; end
104
+
105
+ class A
106
+ inherit M
107
+ end
108
+
109
+ A.instance_methods.should_not include('method_added_after_inheritance')
110
+ M.send(:define_method, :method_added_after_inheritance){}
111
+ M.instance_methods.should include('method_added_after_inheritance')
112
+ A.instance_methods.should include('method_added_after_inheritance')
113
+ end
114
+
115
+ it "modules included in base class after inheritance must be propagated to all descendants" do
116
+ module M; end
117
+
118
+ class A
119
+ inherit M
120
+ end
121
+
122
+ module AddedAfterInheritance
123
+ def module_added_after_inheritance; end
124
+ end
125
+
126
+ M.instance_methods.should_not include('module_added_after_inheritance')
127
+ M.inherit AddedAfterInheritance
128
+ M.instance_methods.should include('module_added_after_inheritance')
129
+ A.instance_methods.should include('module_added_after_inheritance')
130
+ end
131
+ end
data/spec/must_spec.rb ADDED
@@ -0,0 +1,29 @@
1
+ require "#{File.dirname __FILE__}/helper"
2
+ require "ruby_ext/array"
3
+ require "ruby_ext/must"
4
+
5
+ describe 'Assert' do
6
+ it 'must & must_not' do
7
+ lambda{must_be.never_called}.should raise_error(/ever/)
8
+ lambda{nil.must_not_be.nil}.should raise_error(/nil/)
9
+ 1.must_not_be.nil
10
+ 1.must_be.== 1
11
+ lambda{1.must_be.== 2}.should raise_error(%r{==})
12
+ 1.must_be.in 1, 2
13
+ 0.must_be.in 0..1
14
+ "".must_be.a String
15
+ 1.must_be.< 2
16
+ end
17
+
18
+ it 'must_be & must_not_be' do
19
+ [].must_be.empty
20
+ [''].must_not_be.empty
21
+
22
+ lambda{[''].must_be.empty}.should raise_error(/must be/)
23
+ lambda{[].must_not_be.empty}.should raise_error(/must not be/)
24
+ end
25
+
26
+ it "should return result" do
27
+ [].must_be.empty.should == []
28
+ end
29
+ end
@@ -0,0 +1,42 @@
1
+ require "#{File.dirname __FILE__}/helper"
2
+ require "ruby_ext/observable2"
3
+
4
+ describe "Observable" do
5
+ class AnObservable
6
+ include Observable2
7
+ end
8
+
9
+ it "Method without Parameters" do
10
+ mock = mock("Observer")
11
+ obs = AnObservable.new
12
+ obs.add_observer mock
13
+ mock.should_receive(:update).with(2)
14
+ obs.notify_observers :update, 2
15
+ end
16
+
17
+ # it "Method without Parameters" do
18
+ # mock = mock("Observer")
19
+ # obs = AnObservable.new
20
+ # obs.add_observer(mock, :method => :custom_update, :filter => lambda{|o| o == 2})
21
+ # mock.should_receive(:custom_update).with(2)
22
+ # obs.notify_observers 2
23
+ # obs.notify_observers 4
24
+ # end
25
+ #
26
+ # it "With Block" do
27
+ # mock = mock("Observer")
28
+ # mock.should_receive(:got)
29
+ # obs = AnObservable.new
30
+ # obs.add_observer{mock.got}
31
+ # obs.notify_observers
32
+ # end
33
+ #
34
+ # it "With Block and Filter" do
35
+ # mock = mock("Observer")
36
+ # obs = AnObservable.new
37
+ # obs.add_observer(:filter => lambda{|o| o == 2}){|o| mock.got o}
38
+ # mock.should_receive(:got).with(2)
39
+ # obs.notify_observers 2
40
+ # obs.notify_observers 4
41
+ # end
42
+ end
@@ -0,0 +1,36 @@
1
+ require "#{File.dirname __FILE__}/helper"
2
+ require "ruby_ext/open_constructor"
3
+
4
+ describe 'OpenConstructor' do
5
+ class Test
6
+ include OpenConstructor
7
+ attr_accessor :name, :value
8
+ end
9
+
10
+ it 'should initialize atributes from Hash' do
11
+ t = Test.new.set(:name => 'name', :value => 'value')
12
+ [t.name, t.value].should == ['name', 'value']
13
+ end
14
+
15
+ it 'should initialize atributes from any Object' do
16
+ t = Test.new.set(:name => 'name', :value => 'value')
17
+ t2 = Test.new.set t
18
+ [t2.name, t2.value].should == ['name', 'value']
19
+ end
20
+
21
+ it 'restrict copied values' do
22
+ t = Test.new.set(:name => 'name', :value => 'value')
23
+ t2 = Test.new.set t, [:name]
24
+ [t2.name, t2.value].should == ['name', nil]
25
+
26
+ t = {:name => 'name', :value => 'value'}
27
+ t2 = Test.new.set t, [:name]
28
+ [t2.name, t2.value].should == ['name', nil]
29
+ end
30
+
31
+ it 'to_hash' do
32
+ h = {:name => 'name', :value => 'value'}
33
+ t = Test.new.set h
34
+ t.to_hash.should == h
35
+ end
36
+ end
@@ -0,0 +1,29 @@
1
+ require "#{File.dirname __FILE__}/helper"
2
+ require "ruby_ext/array"
3
+
4
+ describe 'OpenObject' do
5
+ it 'should be comparable with hashes' do
6
+ {}.to_openobject.should == {}
7
+ {}.should == {}.to_openobject
8
+
9
+ {:a => :b}.to_openobject.should == {:a => :b}
10
+ {'a' => :b}.to_openobject.should == {:a => :b}
11
+
12
+ {:a => :b}.to_openobject.should == {'a' => :b}
13
+ {'a' => :b}.to_openobject.should == {'a' => :b}
14
+
15
+ {:a => :b}.to_openobject.should_not == {:a => :c}
16
+ end
17
+
18
+ it "must be hash (from error)" do
19
+ {}.to_openobject.is_a?(Hash).should be_true
20
+ end
21
+
22
+ it 'merge! should be indifferent to string and symbol' do
23
+ oo = OpenObject.new
24
+ oo.merge! :a => true
25
+ oo.a.should be_true
26
+ oo.merge! 'b' => true
27
+ oo.b.should be_true
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ require "#{File.dirname __FILE__}/helper"
2
+ require "ruby_ext/prepare_arguments"
3
+
4
+ describe "Prepare Arguments" do
5
+
6
+ it "basic parsing" do
7
+ ArgumentsParser.register :m, [:object, :array, :hash]
8
+ ArgumentsParser.parse_arguments_for(:m, :o, 1).should == [:o, [1], {}]
9
+ end
10
+
11
+ it "basic method wrapping" do
12
+ class BMWTest
13
+ def add content, options
14
+ :ok
15
+ end
16
+ prepare_arguments_for :add, {:type => :object, :required => true}, :hash
17
+ end
18
+
19
+ BMWTest.new.add('text').should == :ok
20
+ end
21
+
22
+ it "except_last_hash for array" do
23
+ ArgumentsParser.register :m, [{:type => :array, :range => :except_last_hash}, :hash]
24
+ ArgumentsParser.parse_arguments_for(:m, 1, 2, 3, :a => :b).should == [[1, 2, 3], {:a => :b}]
25
+ ArgumentsParser.parse_arguments_for(:m, :a => :b).should == [[], {:a => :b}]
26
+ ArgumentsParser.parse_arguments_for(:m, 1, 2, 3).should == [[1, 2, 3], {}]
27
+ end
28
+
29
+ it "except_last_hash for object" do
30
+ ArgumentsParser.register :m, [{:type => :object, :range => :except_last_hash}, :hash]
31
+ ArgumentsParser.parse_arguments_for(:m, 1, :a => :b).should == [1, {:a => :b}]
32
+ ArgumentsParser.parse_arguments_for(:m, :a => :b).should == [nil, {:a => :b}]
33
+ ArgumentsParser.parse_arguments_for(:m, 1).should == [1, {}]
34
+ end
35
+
36
+ it "default value" do
37
+ ArgumentsParser.register :m, [{:type => :object, :default => ""}]
38
+ ArgumentsParser.parse_arguments_for(:m).should == [""]
39
+ end
40
+
41
+ it "string" do
42
+ ArgumentsParser.register :m, [:string]
43
+ ArgumentsParser.parse_arguments_for(:m).should == [""]
44
+ end
45
+
46
+ end
@@ -0,0 +1,24 @@
1
+ require "#{File.dirname __FILE__}/helper"
2
+ require "ruby_ext/should"
3
+
4
+ describe 'Assert' do
5
+ it 'should! & should_not!' do
6
+ lambda{should! :be_never_called}.should raise_error(/ever/)
7
+ lambda{nil.should_not! :be_nil}.should raise_error(/nil/)
8
+ 1.should_not! :be_nil
9
+ 1.should! :==, 1
10
+ lambda{1.should! :==, 2}.should raise_error(%r{==})
11
+ 1.should! :be_in, [1, 2]
12
+ "".should! :be_a, String
13
+ String.should! :be, String
14
+ 1.should! :<, 2
15
+ end
16
+
17
+ it 'should_be! & should_not_be!' do
18
+ [].should_be! :empty
19
+ [''].should_not_be! :empty
20
+
21
+ lambda{[''].should_be! :empty}.should raise_error(/should be/)
22
+ lambda{[].should_not_be! :empty}.should raise_error(/should not be/)
23
+ end
24
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --reverse