ruby_ext 0.4.25 → 0.5.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 (50) hide show
  1. data/Rakefile +2 -0
  2. data/lib/rake_ext/project.rb +19 -19
  3. data/lib/rake_ext.rb +18 -18
  4. data/lib/rspec_ext/xhtml.rb +6 -6
  5. data/lib/rspec_ext.rb +40 -25
  6. data/lib/ruby_ext/core/array.rb +7 -7
  7. data/lib/ruby_ext/core/basic_object.rb +1 -1
  8. data/lib/ruby_ext/core/deep_clone.rb +2 -2
  9. data/lib/ruby_ext/core/enumerable.rb +1 -1
  10. data/lib/ruby_ext/core/hash.rb +4 -4
  11. data/lib/ruby_ext/core/module.rb +20 -30
  12. data/lib/ruby_ext/core/multiple_inheritance.rb +24 -24
  13. data/lib/ruby_ext/core/must.rb +39 -39
  14. data/lib/ruby_ext/core/object.rb +15 -3
  15. data/lib/ruby_ext/core/open_object.rb +22 -20
  16. data/lib/ruby_ext/core/string.rb +19 -19
  17. data/lib/ruby_ext/core/symbol.rb +1 -13
  18. data/lib/ruby_ext/core.rb +4 -8
  19. data/lib/ruby_ext/more/callbacks.rb +172 -0
  20. data/lib/ruby_ext/more/declarative_cache.rb +20 -22
  21. data/lib/ruby_ext/more/miscellaneous.rb +1 -46
  22. data/lib/ruby_ext/more/{observable2.rb → observable.rb} +8 -8
  23. data/lib/ruby_ext/more/open_constructor.rb +10 -10
  24. data/lib/ruby_ext/more/tuple.rb +1 -1
  25. data/lib/ruby_ext/more.rb +5 -3
  26. data/lib/ruby_ext.rb +0 -3
  27. data/lib/yaml_fix.rb +2 -2
  28. data/readme.md +51 -50
  29. data/spec/core/deep_clone_spec.rb +8 -8
  30. data/spec/core/module_spec.rb +29 -36
  31. data/spec/core/multiple_inheritance_spec.rb +32 -32
  32. data/spec/core/must_spec.rb +6 -6
  33. data/spec/core/object_spec.rb +15 -0
  34. data/spec/core/open_object_spec.rb +6 -6
  35. data/spec/more/callbacks_spec.rb +155 -0
  36. data/spec/more/declarative_cache_spec.rb +33 -33
  37. data/spec/more/{observable2_spec.rb → observable_spec.rb} +7 -7
  38. data/spec/more/open_constructor_spec.rb +5 -5
  39. metadata +7 -15
  40. data/lib/ruby_ext/core/class.rb +0 -0
  41. data/lib/ruby_ext/core/file.rb +0 -23
  42. data/lib/ruby_ext/core/kernel.rb +0 -69
  43. data/lib/ruby_ext/core/miscellaneous.rb +0 -14
  44. data/lib/ruby_ext/more/synchronize.rb +0 -26
  45. data/spec/core/kernel_spec/TheNamespace/ClassA.rb +0 -7
  46. data/spec/core/kernel_spec/another_class.rb +0 -5
  47. data/spec/core/kernel_spec/the_namespace/class_b.rb +0 -11
  48. data/spec/core/kernel_spec.rb +0 -51
  49. data/spec/more/miscellaneous_spec.rb +0 -14
  50. data/spec/more/synchronize_spec.rb +0 -79
@@ -0,0 +1,172 @@
1
+ module RubyExt::Callbacks
2
+ class AbstractCallback
3
+ attr_accessor :terminator
4
+
5
+ attr_reader :executor
6
+ def executor= executor
7
+ @executor = executor.must_be.a Symbol, Proc
8
+ end
9
+
10
+ attr_reader :conditions
11
+ def conditions= conditions
12
+ @conditions = {}
13
+ conditions.each do |k, v|
14
+ @conditions[k.to_sym] = if v.is_a? Symbol
15
+ v.to_s
16
+ elsif v.is_a? Array
17
+ v.collect{|e| e.to_s}
18
+ else
19
+ v
20
+ end
21
+ end
22
+ @conditions
23
+ end
24
+
25
+ def terminate? target, result
26
+ unless terminator.nil?
27
+ if terminator.is_a? Proc
28
+ terminator.call target, result
29
+ else
30
+ result == terminator
31
+ end
32
+ else
33
+ false
34
+ end
35
+ end
36
+
37
+ def run? target, inf
38
+ if cond = conditions[:if]
39
+ evaluate_if(cond, target, inf)
40
+ elsif cond = conditions[:unless]
41
+ !evaluate_if(cond, target, inf)
42
+ elsif cond = conditions[:only]
43
+ evaluate_only(cond, inf)
44
+ elsif cond = conditions[:except]
45
+ !evaluate_only(cond, inf)
46
+ else
47
+ true
48
+ end
49
+ end
50
+
51
+ def add_to_chain target, inf, &the_next
52
+ if run? target, inf
53
+ build_block target, &the_next
54
+ else
55
+ the_next
56
+ end
57
+ end
58
+
59
+ alias_method :deep_clone, :clone
60
+
61
+ protected
62
+ def evaluate_if cond, target, inf
63
+ if cond.is_a? String
64
+ target.send cond
65
+ elsif cond.is_a? Proc
66
+ cond.call target, inf
67
+ else
68
+ must_be.never_called
69
+ end
70
+ end
71
+
72
+ def evaluate_only cond, inf
73
+ method = inf[:method].to_s
74
+ if cond.is_a? String
75
+ cond == method
76
+ elsif cond.is_a? Array
77
+ cond.include? method
78
+ end
79
+ end
80
+ end
81
+
82
+ class BeforeCallback < AbstractCallback
83
+ def build_block target, &the_next
84
+ lambda do
85
+ result = if executor.is_a? Symbol
86
+ target.send executor
87
+ elsif executor.is_a? Proc
88
+ executor.call target
89
+ else
90
+ must_be.never_called
91
+ end
92
+
93
+ the_next.call unless terminate? target, result
94
+ end
95
+ end
96
+ end
97
+
98
+ class AroundCallback < AbstractCallback
99
+ def build_block target, &the_next
100
+ lambda do
101
+ if executor.is_a? Symbol
102
+ target.send executor, &the_next
103
+ elsif executor.is_a? Proc
104
+ executor.call target, the_next
105
+ else
106
+ must_be.never_called
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ class AfterCallback < AbstractCallback
113
+ def build_block target, &the_next
114
+ lambda do
115
+ result = if executor.is_a? Symbol
116
+ target.send executor
117
+ elsif executor.is_a? Proc
118
+ executor.call target
119
+ else
120
+ must_be.never_called
121
+ end
122
+
123
+ the_next.call unless terminate? target, result
124
+ end
125
+ end
126
+ end
127
+
128
+ def run_callbacks callback_name, additional_information = {}, &block
129
+ callback_name = callback_name.to_s
130
+ block.must_be.defined
131
+
132
+ callbacks = self.class.callbacks[callback_name]
133
+ chain_head = block
134
+ if callbacks and !callbacks.empty?
135
+ callbacks.reverse_each do |callback|
136
+ block = callback.add_to_chain self, additional_information, &chain_head
137
+ chain_head = block if block
138
+ end
139
+ end
140
+ chain_head.call
141
+ end
142
+
143
+ module ClassMethods
144
+ inheritable_accessor :callbacks, {}
145
+
146
+ def set_callback callback_name, type, *executor_or_options, &block
147
+ # parsing arguments
148
+ type, callback_name = type.to_s, callback_name.to_s
149
+ opt = executor_or_options.extract_options!
150
+ "You can't provide both method name and block for filter!" if block and !executor_or_options.empty?
151
+ executor = block || executor_or_options.first
152
+
153
+ type.must_be.in %w{before around after}
154
+ executor.must_be.defined
155
+
156
+ # creating callback
157
+ callback = case type
158
+ when 'before' then BeforeCallback.new
159
+ when 'around' then AroundCallback.new
160
+ when 'after' then AfterCallback.new
161
+ end
162
+
163
+ callback.executor = executor
164
+ callback.terminator = opt.delete :terminator
165
+ callback.conditions = opt
166
+
167
+ callbacks[callback_name] ||= []
168
+ callbacks[callback_name] << callback
169
+ end
170
+
171
+ end
172
+ end
@@ -4,27 +4,25 @@ Module.class_eval do
4
4
  def cache_method *methods
5
5
  DeclarativeCache.cache_method self, *methods
6
6
  end
7
-
7
+
8
8
  def cache_method_with_params *methods
9
9
  DeclarativeCache.cache_method_with_params self, *methods
10
- end
11
- end
12
-
13
- class Object
14
- def clear_cache
15
- instance_variables.each do |iv|
16
- remove_instance_variable iv if iv =~ /_cache$/ or iv =~ /_cache_check$/
10
+ end
11
+
12
+ def clear_cache obj
13
+ obj.instance_variables.each do |iv|
14
+ obj.send :remove_instance_variable, iv if iv =~ /_cache$/ or iv =~ /_cache_check$/
17
15
  end
18
16
  end
19
17
  end
20
18
 
21
- module DeclarativeCache
19
+ module DeclarativeCache
22
20
  DISABLED = false
23
21
 
24
22
  warn "CASHE DISABLED" if DISABLED
25
- unless DISABLED
23
+ unless DISABLED
26
24
  class << self
27
-
25
+
28
26
  def cache_method klass, *methods
29
27
  methods.each do |method|
30
28
  klass.class_eval do
@@ -32,9 +30,9 @@ module DeclarativeCache
32
30
  method_with_cache, method_without_cache = "#{escaped_method}_with_cache".to_sym, "#{escaped_method}_without_cache".to_sym
33
31
  iv_check = "@#{escaped_method}_cache_check"
34
32
  iv = "@#{escaped_method}_cache"
35
-
33
+
36
34
  if instance_methods.include?(method_with_cache) or instance_methods.include?(method_without_cache)
37
- warn "can't cache the :#{method} twice!"
35
+ warn "can't cache the :#{method} twice!"
38
36
  else
39
37
  alias_method method_without_cache, method
40
38
 
@@ -55,21 +53,21 @@ module DeclarativeCache
55
53
  end
56
54
  end
57
55
  end
58
-
59
- def cache_method_with_params klass, *methods
60
- methods.each do |method|
61
- klass.class_eval do
56
+
57
+ def cache_method_with_params klass, *methods
58
+ methods.each do |method|
59
+ klass.class_eval do
62
60
  escaped_method = escape_method(method)
63
61
  method_with_cache, method_without_cache = "#{escaped_method}_with_cache".to_sym, "#{escaped_method}_without_cache".to_sym
64
62
  iv_check = "@#{escaped_method}_cache_check"
65
63
  iv = "@#{escaped_method}_cache"
66
-
64
+
67
65
  if instance_methods.include?(method_with_cache) or instance_methods.include?(method_without_cache)
68
- warn "can't cache the :#{method} twice!"
66
+ warn "can't cache the :#{method} twice!"
69
67
  else
70
68
  alias_method method_without_cache, method
71
69
 
72
- define_method method_with_cache do |*args|
70
+ define_method method_with_cache do |*args|
73
71
  unless results = instance_variable_get(iv)
74
72
  results = Hash.new(NotDefined)
75
73
  instance_variable_set iv, results
@@ -77,7 +75,7 @@ module DeclarativeCache
77
75
 
78
76
  result = results[args]
79
77
 
80
- if result.equal? NotDefined
78
+ if result.equal? NotDefined
81
79
  result = send method_without_cache, *args
82
80
  results[args] = result
83
81
  end
@@ -90,7 +88,7 @@ module DeclarativeCache
90
88
  end
91
89
  end
92
90
  end
93
-
91
+
94
92
  end
95
93
  end
96
94
  end
@@ -1,52 +1,7 @@
1
1
  Kernel.class_eval do
2
2
  alias_method :old_p, :p
3
- def p *args
3
+ def p *args
4
4
  puts args.collect{|a| a.inspect}.join(' ')
5
5
  return *args
6
6
  end
7
- end
8
-
9
-
10
- #
11
- # Parsing command line
12
- #
13
- module RubyExt
14
- def self.argv input = ARGV
15
- # don't want to modify original input and can't use :clone (it may be not an array)
16
- input = input.collect{|v| v}
17
-
18
- list, options = [], {}
19
- until input.empty? do
20
- arg = input.shift.strip
21
- if arg =~ /.+:$/ and !input.empty?
22
- k = arg[0..-2].to_sym
23
- v = input.shift
24
- v = v.sub(/\s*,$/, '') if v
25
- options[k] = simple_cast(v)
26
- else
27
- v = arg.gsub(/^['"]|['"]$/, '')
28
- v = v.sub(/\s*,$/, '')
29
- list << simple_cast(v)
30
- end
31
- end
32
- list << options
33
- list
34
- end
35
-
36
- protected
37
- def self.simple_cast v
38
- if v =~ /^:[a-z_0-9]+$/i
39
- v[1..-1].to_sym
40
- elsif v =~ /^[0-9]+$/
41
- v.to_i
42
- elsif v =~ /^[0-9]*\.[0-9]+$/
43
- v.to_f
44
- elsif v =~ /^\/.+\/$/
45
- Regexp.new v[1..-2]
46
- elsif v == 'nil'
47
- nil
48
- else
49
- v
50
- end
51
- end
52
7
  end
@@ -1,22 +1,22 @@
1
- module Observable2
1
+ module RubyExt::Observable
2
2
  def add_observer observer
3
3
  @observable_observers ||= []
4
- @observable_observers << observer unless @observable_observers.include? observer
4
+ @observable_observers << observer unless @observable_observers.include? observer
5
5
  end
6
-
6
+
7
7
  def notify_observers method, *args
8
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
9
+ @observable_observers.each{|observer| observer.respond_to method, *args} if @observable_observers
10
10
  end
11
-
11
+
12
12
  def delete_observer observer
13
13
  @observable_observers.delete observer if @observable_observers
14
14
  end
15
-
16
- def delete_observers
15
+
16
+ def delete_observers
17
17
  @observable_observers.clear if @observable_observers
18
18
  end
19
-
19
+
20
20
  def observers_count
21
21
  @observable_observers ? @observable_observers.size : 0
22
22
  end
@@ -1,8 +1,8 @@
1
- module OpenConstructor
1
+ module RubyExt::OpenConstructor
2
2
  def set values, list = nil
3
3
  unless list
4
4
  if values.is_a? Hash
5
- values.each do |k, v|
5
+ values.each do |k, v|
6
6
  self.respond_to "#{k}=", v
7
7
  end
8
8
  else
@@ -15,32 +15,32 @@ module OpenConstructor
15
15
  end
16
16
  else
17
17
  if values.is_a? Hash
18
- values.each do |k, v|
18
+ values.each do |k, v|
19
19
  self.respond_to "#{k}=", v if list.include? k
20
20
  end
21
21
  else
22
22
  values.instance_variables.each do |name|
23
23
  accessor = name[1..name.size]
24
- if list.include?(accessor.to_sym)
24
+ if list.include?(accessor.to_sym)
25
25
  accessor = "#{accessor}="
26
26
  if self.respond_to?(accessor)
27
27
  self.send accessor, values.instance_variable_get(name)
28
28
  end
29
29
  end
30
30
  end
31
- end
31
+ end
32
32
  end
33
- return self
34
- end
35
-
33
+ return self
34
+ end
35
+
36
36
  def set! values
37
37
  values.each do |k, v|
38
- self.send "#{k}=", v
38
+ self.send "#{k}=", v
39
39
  end
40
40
  return self
41
41
  end
42
42
  # alias_method :set! #, :set_with_check
43
-
43
+
44
44
  def to_hash
45
45
  hash = {}
46
46
  instance_variables.each do |name|
@@ -1,6 +1,6 @@
1
1
  class Tuple
2
2
  attr_accessor :first, :last
3
-
3
+
4
4
  def initialize first = nil, last = nil
5
5
  @first, @last = first, last
6
6
  end
data/lib/ruby_ext/more.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  require 'ruby_ext/core'
2
2
 
3
+ module RubyExt; end
4
+
3
5
  %w(
4
6
  declarative_cache
5
- observable2
7
+ observable
6
8
  open_constructor
7
- synchronize
8
9
  tuple
9
- miscellaneous
10
+ callbacks
11
+ miscellaneous
10
12
  ).each{|f| require "ruby_ext/more/#{f}"}
data/lib/ruby_ext.rb CHANGED
@@ -1,4 +1 @@
1
- module RubyExt
2
- end
3
-
4
1
  require "ruby_ext/more"
data/lib/yaml_fix.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'yaml'
2
2
 
3
- begin
4
- require 'psych'
3
+ begin
4
+ require 'psych'
5
5
  YAML::ENGINE.yamler = 'psych'
6
6
  rescue Exception
7
7
  warn "can't load 'psych', the new YAML engine (probably the 'libyaml' is not installed), usng 'sych' a deprecated one, \
data/readme.md CHANGED
@@ -1,55 +1,56 @@
1
- # Ruby extensions
2
- **ruby_ext** is a collection of various utility classes and standard library extensions for the Ruby language.
1
+ Collection of various utility classes and standard library extensions for Ruby language.
3
2
 
4
3
  ## must - assertion tool, kind of RSpec assertions in runtime code
5
4
 
6
- 1.must_be.in 1..2
7
- "a".must_be.in 'a', 'b', 'c'
8
- key.must_be.a String
9
- value.must_not_be.nil
10
- must_be.never_called
11
- a.must_be == b
5
+ ``` ruby
6
+ 1.must_be.in 1..2
7
+ "a".must_be.in 'a', 'b', 'c'
8
+ key.must_be.a String
9
+ value.must_not_be.nil
10
+ must_be.never_called
11
+ a.must_be == b
12
+ ```
12
13
 
13
14
  ## inherit - combines include & extend in one
14
15
  Do you remember this *def self.included(base) ... end* hack? You don't need it anymore.
15
16
 
16
- module Feature
17
- def cool_method; end
18
- class_methods do
19
- def cool_class_method; end
20
- end
21
- end
22
-
23
- class TheClass
24
- inherit Feature
25
- end
26
-
27
- TheClass.new.cool_method
28
- TheClass.cool_class_method
29
-
30
- ## cache_method & synchronize_method
31
-
32
- def complex_calculation
33
- 2 * 2
34
- end
35
- cache_method :complex_calculation
36
-
37
- def money_transfer amount
38
- @from -= amount
39
- @to += amount
40
- end
41
- synchronize_method :money_transfer
17
+ ``` ruby
18
+ module Feature
19
+ def cool_method; end
20
+ class_methods do
21
+ def cool_class_method; end
22
+ end
23
+ end
24
+
25
+ class TheClass
26
+ inherit Feature
27
+ end
28
+
29
+ TheClass.new.cool_method
30
+ TheClass.cool_class_method
31
+ ```
32
+
33
+ ## cache_method
34
+
35
+ ``` ruby
36
+ def complex_calculation
37
+ 2 * 2
38
+ end
39
+ cache_method :complex_calculation
40
+ ```
42
41
 
43
42
  ## OpenConstructor - adds mass assignment to any class
44
-
45
- class TheClass
46
- include OpenConstructor
47
- attr_accessor :a, :b
48
- end
49
43
 
50
- o = TheClass.new.set a: 'a', b: 'b'
51
- o.a => 'a'
52
- o.to_hash => {a: 'a', b: 'b'}
44
+ ``` ruby
45
+ class TheClass
46
+ include RubyExt::OpenConstructor
47
+ attr_accessor :a, :b
48
+ end
49
+
50
+ o = TheClass.new.set a: 'a', b: 'b'
51
+ o.a => 'a'
52
+ o.to_hash => {a: 'a', b: 'b'}
53
+ ```
53
54
 
54
55
  ## More
55
56
 
@@ -57,14 +58,14 @@ These are just a small part of all handy methods and extensions, for more detail
57
58
 
58
59
  # Usage
59
60
 
60
- $ sudo gem install ruby_ext
61
-
62
- require 'ruby_ext'
63
-
64
- Copyright (c) Alexey Petrushin, http://petrush.in, released under the MIT license.
61
+ ``` bash
62
+ gem install ruby_ext
63
+ ```
65
64
 
66
- # TODO
65
+ ``` ruby
66
+ require 'ruby_ext'
67
+ ```
67
68
 
68
- - config.development{} should raise 'invalid usage'
69
+ ## License
69
70
 
70
- [ioc]: http://en.wikipedia.org/wiki/Inversion_of_control
71
+ Copyright (c) Alexey Petrushin, http://petrush.in, released under the MIT license.
@@ -4,33 +4,33 @@ describe 'deep_clone' do
4
4
  it "basic" do
5
5
  hash, array = {}, ['value']
6
6
  hash['key'] = array
7
-
7
+
8
8
  hash2 = hash.deep_clone
9
9
  array2 = hash2['key']
10
-
10
+
11
11
  hash2.should == hash
12
12
  hash2.object_id.should_not == hash.object_id
13
-
13
+
14
14
  array2.should == array
15
15
  array2.object_id.should_not == array.object_id
16
16
  end
17
-
17
+
18
18
  it do
19
19
  class Metadata
20
20
  attr_accessor :registry
21
-
21
+
22
22
  def initialize
23
23
  @registry = {}
24
24
  end
25
25
  end
26
-
26
+
27
27
  m = Metadata.new
28
28
  m.registry[:a] = 1
29
-
29
+
30
30
  m2 = m.deep_clone
31
31
  m2.registry.should include(:a)
32
32
  m2.registry[:b] = 2
33
-
33
+
34
34
  m.registry.should == {a: 1}
35
35
  end
36
36
  end