ruby_ext 0.4.6

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 (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,192 @@
1
+ class AssertionError < StandardError; end
2
+
3
+ class MustAssertions < ExtraBlankSlate
4
+ attr_reader :obj
5
+
6
+ def initialize obj
7
+ @obj = obj
8
+ end
9
+
10
+ def == o
11
+ @obj == o
12
+ end
13
+
14
+ def =~ o
15
+ @obj =~ o
16
+ end
17
+
18
+ def never_called
19
+ false
20
+ end
21
+
22
+ def nil
23
+ @obj.equal? nil
24
+ end
25
+
26
+ def defined
27
+ !nil
28
+ end
29
+
30
+ def respond_to method
31
+ @obj.respond_to? method
32
+ end
33
+
34
+ def a klass
35
+ if klass.class == Array
36
+ klass.any?{|k| @obj.is_a? k}
37
+ else
38
+ @obj.is_a? klass
39
+ end
40
+ end
41
+ alias_method :an, :a
42
+
43
+ # def be klass = nil
44
+ # if klass.class == Array
45
+ # klass.any?{|k| @obj.respond_to :is?, k}
46
+ # else
47
+ # @obj.respond_to :is?, klass
48
+ # end
49
+ # end
50
+
51
+ def include o
52
+ @obj.include? o
53
+ end
54
+
55
+ def in *args
56
+ if args.size == 1
57
+ obj = args.first
58
+ if obj.is_a?(Array) or obj.is_a?(Range)
59
+ obj.include? @obj
60
+ else
61
+ args.include? @obj
62
+ end
63
+ else
64
+ args.include? @obj
65
+ end
66
+ end
67
+
68
+ def true
69
+ !!@obj
70
+ end
71
+
72
+ def false
73
+ !@obj
74
+ end
75
+
76
+ def empty
77
+ @obj.empty?
78
+ end
79
+
80
+ def blank
81
+ @obj.blank?
82
+ end
83
+
84
+ def present
85
+ !@obj.blank?
86
+ end
87
+
88
+ def > o
89
+ @obj > o
90
+ end
91
+
92
+ def < o
93
+ @obj < o
94
+ end
95
+
96
+ def >= o
97
+ @obj >= o
98
+ end
99
+
100
+ def <= o
101
+ @obj <= o
102
+ end
103
+
104
+ def exist arg
105
+ @obj.exist? arg
106
+ end
107
+
108
+ def be
109
+ @prefix = 'be'
110
+ self
111
+ end
112
+
113
+ def have
114
+ @prefix = 'have'
115
+ self
116
+ end
117
+
118
+ def self.assertions
119
+ special = %w{be have}
120
+ instance_methods.select{|m| m !~ /^__/ and m != 'be'}
121
+ end
122
+
123
+ protected
124
+ def method_missing m, *args, &b
125
+ raise RuntimeError, "Assertion '#{m}' is unknown!", caller[1..-1]
126
+ end
127
+
128
+ def failed method, negative, *args
129
+ stack = caller.sfilter('must.rb')
130
+
131
+ unless args.empty?
132
+ Kernel.raise AssertionError, "
133
+ ASSERTION FAILED (#{stack.first}):
134
+ #{@obj.inspect} must #{'not ' if negative}#{"#{@prefix} " if @prefix}#{method} #{args.first.inspect}
135
+ ", stack
136
+ else
137
+ Kernel.raise AssertionError, "
138
+ ASSERTION FAILED (#{stack.first}):
139
+ #{@obj.inspect} must #{'not ' if negative}#{"#{@prefix} " if @prefix}#{method}
140
+ ", stack
141
+ end
142
+ end
143
+ end
144
+
145
+ class Must < MustAssertions
146
+ assertions.each do |m|
147
+ desition = "_#{m}"
148
+ alias_method desition, m
149
+ define_method m do |*args|
150
+ failed m, false, *args unless __send__(desition, *args)
151
+ @obj
152
+ end
153
+ end
154
+ end
155
+
156
+ class MustNot < MustAssertions
157
+ assertions.each do |m|
158
+ desition = "_#{m}"
159
+ alias_method desition, m
160
+ define_method m do |*args|
161
+ failed m, true, *args if __send__(desition, *args)
162
+ @obj
163
+ end
164
+ end
165
+ end
166
+
167
+ Object.class_eval do
168
+
169
+ def must
170
+ Must.new(self)
171
+ end
172
+
173
+ def must_not
174
+ MustNot.new(self)
175
+ end
176
+
177
+ def must_be
178
+ must.be
179
+ end
180
+
181
+ def must_not_be
182
+ must_not.be
183
+ end
184
+
185
+ # def must_have
186
+ # must.have
187
+ # end
188
+ #
189
+ # def must_not_have
190
+ # must_not.have
191
+ # end
192
+ end
@@ -0,0 +1,2 @@
1
+ module NotDefined
2
+ end
@@ -0,0 +1,8 @@
1
+ Object.class_eval do
2
+ def self; self end
3
+
4
+ public :extend
5
+ # def copy
6
+ # Marshal.load(Marshal.dump self) # Stub
7
+ # end
8
+ end
@@ -0,0 +1,23 @@
1
+ module Observable2
2
+ def add_observer observer
3
+ @observable_observers ||= []
4
+ @observable_observers << observer unless @observable_observers.include? observer
5
+ end
6
+
7
+ def notify_observers method, *args
8
+ raise "Invalid usage, method must be Symbol or String!" unless method.is_a?(Symbol) or method.is_a?(String)
9
+ @observable_observers.each{|observer| observer.respond_to method, *args} if @observable_observers
10
+ end
11
+
12
+ def delete_observer observer
13
+ @observable_observers.delete observer if @observable_observers
14
+ end
15
+
16
+ def delete_observers
17
+ @observable_observers.clear if @observable_observers
18
+ end
19
+
20
+ def observers_count
21
+ @observable_observers ? @observable_observers.size : 0
22
+ end
23
+ end
@@ -0,0 +1,51 @@
1
+ module OpenConstructor
2
+ def set values, list = nil
3
+ unless list
4
+ if values.is_a? Hash
5
+ values.each do |k, v|
6
+ self.respond_to k.to_writer, v
7
+ end
8
+ else
9
+ values.instance_variables.each do |name|
10
+ accessor = name[1..name.size].to_writer
11
+ if self.respond_to? accessor
12
+ self.send accessor, values.instance_variable_get(name)
13
+ end
14
+ end
15
+ end
16
+ else
17
+ if values.is_a? Hash
18
+ values.each do |k, v|
19
+ self.respond_to k.to_writer, v if list.include? k
20
+ end
21
+ else
22
+ values.instance_variables.each do |name|
23
+ accessor = name[1..name.size]
24
+ if list.include?(accessor.to_sym)
25
+ accessor = accessor.to_writer
26
+ if self.respond_to?(accessor)
27
+ self.send accessor, values.instance_variable_get(name)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ return self
34
+ end
35
+
36
+ def set_with_check values
37
+ values.each do |k, v|
38
+ self.send k.to_writer, v
39
+ end
40
+ return self
41
+ end
42
+ alias_method :set!, :set_with_check
43
+
44
+ def to_hash
45
+ hash = {}
46
+ instance_variables.each do |name|
47
+ hash[name[1..name.size].to_sym] = instance_variable_get name
48
+ end
49
+ return hash
50
+ end
51
+ end
@@ -0,0 +1,157 @@
1
+ raise "You shouldn't use OpenObject defined in facets, it's incopatible with this version!" if defined?(OpenObject)
2
+
3
+ class OpenObject < Hash
4
+
5
+ PUBLIC_METHODS = %w(as send each size is_a? clone dup empty? blank? present? merge merge! stringify_keys stringify_keys! symbolize_keys symbolize_keys! to_query)
6
+ PUBLIC_METHODS_RE = /(^__|^object_)/
7
+
8
+ protected(*public_instance_methods.select{ |m| !PUBLIC_METHODS.include?(m) and m !~ PUBLIC_METHODS_RE })
9
+
10
+ def inspect
11
+ "#<#{self.class}:#{self.object_id} #{super}>"
12
+ end
13
+
14
+ def to_a; super end
15
+
16
+ def to_proc; super end
17
+
18
+ def to_openobject deep = false
19
+ unless deep
20
+ self
21
+ else
22
+ r = OpenObject.new
23
+ each do |k, v|
24
+ r[k] = if v.is_a? Hash
25
+ v.to_openobject
26
+ else
27
+ v
28
+ end
29
+ end
30
+ r
31
+ end
32
+ end
33
+
34
+ def each &block; super(&block) end
35
+
36
+ def merge other
37
+ d = dup
38
+ other.each{|k, v| d[k] = v}
39
+ d
40
+ # d = dup
41
+ # d.send(:update, other)
42
+ # d
43
+ end
44
+
45
+ def merge! other
46
+ other.each{|k, v| self[k] = v}
47
+ end
48
+
49
+ def update other
50
+ other.to_hash.each{|k,v| self[k.to_s] = v}
51
+ self
52
+ end
53
+
54
+ def delete key
55
+ super key.to_s
56
+ end
57
+
58
+ def == other
59
+ return false unless other.respond_to?(:each) and other.respond_to?(:size) and other.respond_to?(:[]) and self.size == other.size
60
+ other.each do |k, v|
61
+ return false unless self[k] == v
62
+ end
63
+ true
64
+ end
65
+
66
+ def []= k, v
67
+ super k.to_s, v
68
+ end
69
+
70
+ def [] k
71
+ super k.to_s
72
+ end
73
+
74
+ def include? k
75
+ super k.to_s
76
+ end
77
+
78
+ def to_hash deep = false
79
+ unless deep
80
+ {}.update(self)
81
+ else
82
+ h = {}
83
+ each do |k, v|
84
+ if v.is_a? OpenObject
85
+ h[k] = v.to_hash(true)
86
+ else
87
+ h[k] = v
88
+ end
89
+ end
90
+ h
91
+ end
92
+ end
93
+ alias_method :to_h, :to_hash
94
+
95
+ def to_json *args
96
+ to_hash.to_json *args
97
+ end
98
+
99
+ # hack to works well with RSpec
100
+ def should; super end
101
+ def should_not; super end
102
+
103
+ def respond_to? m
104
+ true
105
+ end
106
+
107
+ protected
108
+ def method_missing m, arg = nil, &block
109
+ m = m.to_s
110
+ type = m[-1,1]
111
+ # key = m.to_s.sub(/[=?!]$/,'').to_s
112
+ if type == '='
113
+ self[m[0..-2]] = arg
114
+ elsif type == '!'
115
+ self[m[0..-2]]
116
+ elsif type == '?'
117
+ !self[m[0..-2]].blank?
118
+ else
119
+ self[m]
120
+ end
121
+ end
122
+ end
123
+
124
+
125
+ #
126
+ # Core Extensions
127
+ #
128
+ class NilClass
129
+ def to_openobject deep = false
130
+ OpenObject.new
131
+ end
132
+ end
133
+
134
+ class Hash
135
+ def to_openobject deep = false
136
+ unless deep
137
+ OpenObject.new.update self
138
+ else
139
+ r = OpenObject.new
140
+ each do |k, v|
141
+ r[k] = if v.is_a? Hash
142
+ v.to_openobject
143
+ else
144
+ v
145
+ end
146
+ end
147
+ r
148
+ end
149
+ end
150
+
151
+ alias_method :oo_eql, :==
152
+ def == other
153
+ true if self.equal? other
154
+ other == self if other.is_a? OpenObject
155
+ oo_eql other
156
+ end
157
+ end
@@ -0,0 +1,105 @@
1
+ class ArgumentsParser
2
+ class << self
3
+ def register method, arguments
4
+ # check and prepare metadata
5
+ arguments.collect!{|meta| meta.is_a?(Hash) ? meta : {:type => meta}}
6
+ arguments.each{|meta| meta.must.include :type}
7
+
8
+ # register
9
+ @registry ||= {}
10
+ @registry[method] = arguments
11
+ end
12
+
13
+ def parse_arguments_for method, *args, &block
14
+ metadata = @registry[method]
15
+ index = 0
16
+ parsed_args = metadata.collect do |options|
17
+ send options[:type], args, block, options, index, (index == metadata.size - 1)
18
+ end
19
+ args.must_be.empty
20
+ return parsed_args
21
+ end
22
+
23
+ protected
24
+ def string args, block, options, index, last
25
+ object(args, block, options, index, last) || ""
26
+ end
27
+
28
+ def object args, block, options, index, last
29
+ a = if range = options[:range]
30
+ if range == :except_last_hash
31
+ if args.size == 1 and args.last.is_a? Hash
32
+ nil
33
+ else
34
+ args.shift
35
+ end
36
+ else
37
+ must_be.never_called
38
+ end
39
+ else
40
+ args.shift
41
+ end
42
+
43
+ a = _common_options a, options
44
+ a
45
+ end
46
+
47
+ def array args, block, options, index, last
48
+ a = if last
49
+ args
50
+ elsif range = options[:range]
51
+ if range == :except_last_hash
52
+ if args.last.is_a? Hash
53
+ tmp = args[0..-2]
54
+ args[0..-2] = nil
55
+ tmp
56
+ else
57
+ tmp = args[0..-1]
58
+ args.clear
59
+ tmp
60
+ end
61
+ else
62
+ must_be.never_called
63
+ end
64
+ else
65
+ args.shift
66
+ end
67
+
68
+ a = _common_options a, options
69
+ a ||= []
70
+ a = [a] unless a.is_a?(Array)
71
+ a
72
+ end
73
+
74
+ def hash args, block, options, index, last
75
+ a = object(args, block, options, index, last) || {}
76
+ a.must_be.a Hash
77
+ a
78
+ end
79
+
80
+ def _common_options a, options
81
+ a.must_not_be.nil if options[:require]
82
+ if (default = options[:default]) and a.eql?(nil)
83
+ a = default
84
+ end
85
+ a
86
+ end
87
+ end
88
+ end
89
+
90
+ Module.class_eval do
91
+ def prepare_arguments_for method, *args
92
+ # Register parsers
93
+ ArgumentsParser.register method, args
94
+
95
+ # Wrap method
96
+ old_method = :"#{method}_wparg"
97
+ alias_method old_method, method
98
+ code = <<END
99
+ def #{method} *args, &block
100
+ #{old_method} *ArgumentsParser.parse_arguments_for(:#{method}, *args), &block
101
+ end
102
+ END
103
+ class_eval code, __FILE__, __LINE__
104
+ end
105
+ end
@@ -0,0 +1,110 @@
1
+ #
2
+ # Fix for ruby's broken include.
3
+ # Included modules doesn't propagated to it's children.
4
+ #
5
+ # Test case:
6
+ # module A; end
7
+ # module B
8
+ # include A
9
+ # end
10
+ #
11
+ # module Plugin; end
12
+ # A.send(:include, Plugin)
13
+ #
14
+ # p "Ancestors of A: " + A.ancestors.join(', ') # => "Ancestors of A: A, Plugin"
15
+ # p "Ancestors of B: " + B.ancestors.join(', ') # => "Ancestors of B: B, A" << NO PLUGIN!
16
+ #
17
+ class Module
18
+ def directly_included_by
19
+ @directly_included_by ||= Set.new
20
+ end
21
+
22
+ def fixed_include mod
23
+ unless mod.directly_included_by.include? self
24
+ mod.directly_included_by.add self
25
+ end
26
+
27
+ include mod
28
+ directly_included_by.each do |child|
29
+ child.fixed_include self
30
+ end
31
+ end
32
+ end
33
+
34
+
35
+ #
36
+ # Prototypes
37
+ #
38
+ class Class
39
+ def prototype
40
+ unless @prototype
41
+ unless const_defined? :Prototype
42
+ class_eval "module Prototype; end", __FILE__, __LINE__
43
+ end
44
+ @prototype = const_get :Prototype
45
+
46
+ fixed_include @prototype
47
+ end
48
+ @prototype
49
+ end
50
+
51
+ def class_prototype
52
+ unless @class_prototype
53
+ unless const_defined? :ClassPrototype
54
+ class_eval "module ClassPrototype; end", __FILE__, __LINE__
55
+ end
56
+ @class_prototype = const_get :ClassPrototype
57
+
58
+ (class << self; self end).fixed_include @class_prototype
59
+ end
60
+ @class_prototype
61
+ end
62
+ end
63
+
64
+
65
+ #
66
+ # Inheritance logic
67
+ #
68
+ class Class
69
+ def define_instance_methods &block
70
+ prototype.class_eval &block
71
+ # self.include prototype
72
+ end
73
+
74
+ def define_class_methods &block
75
+ self.class_prototype.class_eval &block
76
+ # self.extend self.class.prototype
77
+ end
78
+
79
+ def inherit *classes
80
+ classes.each do |klass|
81
+ raise "You can inherit classes only ('#{klass}')!" unless klass.class == Class
82
+
83
+ prototype.fixed_include klass.prototype
84
+ # self.include prototype
85
+
86
+ class_prototype.fixed_include klass.class_prototype
87
+ # (class << self; self end).include class_prototype
88
+
89
+ # callback
90
+ klass.inherited self if klass.respond_to? :inherited
91
+ end
92
+ end
93
+ end
94
+
95
+
96
+ #
97
+ # Sugar
98
+ #
99
+ Class.class_eval do
100
+ alias_method :instance_methods_without_prototype, :instance_methods
101
+ def instance_methods *args, &block
102
+ if block
103
+ define_instance_methods &block
104
+ else
105
+ instance_methods_without_prototype
106
+ end
107
+ end
108
+
109
+ alias_method :class_methods, :define_class_methods
110
+ end