ruby_ext 0.5.1 → 0.5.2

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.
data/Rakefile CHANGED
@@ -8,8 +8,6 @@ project(
8
8
  gem: true,
9
9
  summary: "Ruby Extensions",
10
10
 
11
- version: '0.5.1',
12
-
13
11
  author: "Alexey Petrushin",
14
12
  homepage: "http://github.com/alexeypetrushin/ruby_ext"
15
13
  )
@@ -21,12 +21,16 @@ require 'fileutils'
21
21
  begin
22
22
  require 'rspec/core/rake_task'
23
23
  task default: :spec
24
-
25
- RSpec::Core::RakeTask.new('spec') do |t|
26
- t.pattern = "spec/**/[^_]*_spec.rb"
27
- end
24
+ task spec: 'spec:find_and_specs'
28
25
 
29
26
  namespace :spec do
27
+ desc "Finds Specifications"
28
+ task :find_and_specs do
29
+ RSpec::Core::RakeTask.new('spec') do |t|
30
+ t.pattern = "spec/[^_]**/[^_]*_spec.rb"
31
+ end
32
+ end
33
+
30
34
  desc "Run RSpec code exapmples in isolated mode (every spec file in another Ruby process)"
31
35
  task :isolated do
32
36
  Dir.glob("spec/[^_]**/[^_]*_spec.rb").each do |spec_file|
@@ -48,9 +48,9 @@ Module.class_eval do
48
48
  each_ancestor &b
49
49
  each_namespace &b
50
50
  end
51
-
51
+
52
52
  # TODO cache it?
53
- def self.namespace_for class_name
53
+ def self.namespace_for class_name
54
54
  list = class_name.split("::")
55
55
  if list.size > 1
56
56
  list.pop
@@ -1,6 +1,6 @@
1
1
  Object.class_eval do
2
2
  def self; self end
3
-
3
+
4
4
  def metaclass &block
5
5
  (class << self; self; end)
6
6
  end
@@ -8,11 +8,15 @@ Object.class_eval do
8
8
  metaclass.class_eval(&block)
9
9
  self
10
10
  end
11
-
11
+
12
12
  def respond_to method, *args
13
13
  respond_to?(method) ? send(method, *args) : nil
14
14
  end
15
15
 
16
+ def try method, *args, &block
17
+ self && self.send(method, *args, &block)
18
+ end
19
+
16
20
  public :extend
17
21
  # def copy
18
22
  # Marshal.load(Marshal.dump self) # Stub
@@ -122,7 +122,7 @@ class OpenObject < Hash
122
122
  r
123
123
  end
124
124
  end
125
-
125
+
126
126
  # support :extract_options for OpenObject (Rails integration)
127
127
  def extractable_options?; true end
128
128
 
@@ -8,5 +8,5 @@ module RubyExt; end
8
8
  open_constructor
9
9
  tuple
10
10
  callbacks
11
- miscellaneous
11
+ miscellaneous
12
12
  ).each{|f| require "ruby_ext/more/#{f}"}
@@ -1,172 +1,212 @@
1
1
  module RubyExt::Callbacks
2
2
  class AbstractCallback
3
- attr_accessor :terminator
4
-
5
3
  attr_reader :executor
6
- def executor= executor
4
+ def executor= executor
7
5
  @executor = executor.must_be.a Symbol, Proc
8
6
  end
9
-
7
+
10
8
  attr_reader :conditions
11
9
  def conditions= conditions
12
10
  @conditions = {}
13
11
  conditions.each do |k, v|
14
- @conditions[k.to_sym] = if v.is_a? Symbol
15
- v.to_s
12
+ @conditions[k] = if v.is_a? Symbol
13
+ v
16
14
  elsif v.is_a? Array
17
- v.collect{|e| e.to_s}
15
+ raise "method names must be symbols (#{v})!" unless v.all?{|e| e.is_a? Symbol}
16
+ v
18
17
  else
19
18
  v
20
19
  end
21
20
  end
22
21
  @conditions
23
22
  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
23
+
24
+ def run? target, data
38
25
  if cond = conditions[:if]
39
- evaluate_if(cond, target, inf)
26
+ evaluate_if(cond, target, data)
40
27
  elsif cond = conditions[:unless]
41
- !evaluate_if(cond, target, inf)
28
+ !evaluate_if(cond, target, data)
42
29
  elsif cond = conditions[:only]
43
- evaluate_only(cond, inf)
30
+ evaluate_only(cond, data)
44
31
  elsif cond = conditions[:except]
45
- !evaluate_only(cond, inf)
32
+ !evaluate_only(cond, data)
46
33
  else
47
34
  true
48
35
  end
49
36
  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
-
37
+
59
38
  alias_method :deep_clone, :clone
60
-
39
+
61
40
  protected
62
- def evaluate_if cond, target, inf
63
- if cond.is_a? String
41
+ def evaluate_if cond, target, data
42
+ if cond.is_a? Symbol
64
43
  target.send cond
65
44
  elsif cond.is_a? Proc
66
- cond.call target, inf
45
+ cond.call target, data
67
46
  else
68
47
  must_be.never_called
69
48
  end
70
49
  end
71
-
72
- def evaluate_only cond, inf
73
- method = inf[:method].to_s
74
- if cond.is_a? String
50
+
51
+ def evaluate_only cond, data
52
+ method = data[:method]
53
+ method.must_be.a Symbol if method
54
+ if cond.is_a? Symbol
75
55
  cond == method
76
56
  elsif cond.is_a? Array
77
57
  cond.include? method
58
+ else
59
+ must_be.never_called
78
60
  end
79
61
  end
80
62
  end
81
63
 
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
64
+ class BeforeCallback < AbstractCallback
65
+ attr_accessor :terminator
66
+
67
+ def build_block target, data, &block
68
+ -> do
69
+ if run? target, data
70
+ block.call if run target, data
71
+ else
72
+ block.call
91
73
  end
74
+ end
75
+ end
92
76
 
93
- the_next.call unless terminate? target, result
77
+ def run target, data
78
+ callback_result = if executor.is_a? Symbol
79
+ target.send executor
80
+ elsif executor.is_a? Proc
81
+ executor.call target
82
+ else
83
+ must_be.never_called
94
84
  end
85
+
86
+ !terminate?(target, callback_result)
95
87
  end
88
+
89
+ protected
90
+ def terminate? target, result
91
+ unless terminator.nil?
92
+ if terminator.is_a? Proc
93
+ terminator.call target, result
94
+ else
95
+ result == terminator
96
+ end
97
+ else
98
+ false
99
+ end
100
+ end
96
101
  end
97
102
 
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
103
+ class AfterCallback < AbstractCallback
104
+ def build_block target, data, &block
105
+ -> do
106
+ if run? target, data
107
+ result = block.call
108
+ run target, data
109
+ result
105
110
  else
106
- must_be.never_called
111
+ block.call
107
112
  end
108
- end
113
+ end
114
+ end
115
+
116
+ def run target, data
117
+ if executor.is_a? Symbol
118
+ target.send executor
119
+ elsif executor.is_a? Proc
120
+ executor.call target
121
+ else
122
+ must_be.never_called
123
+ end
109
124
  end
110
125
  end
111
126
 
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
127
+ class AroundCallback < AbstractCallback
128
+ def build_block target, data, &block
129
+ -> do
130
+ if run? target, data
131
+ run target, data, &block
119
132
  else
120
- must_be.never_called
133
+ block.call
121
134
  end
122
-
123
- the_next.call unless terminate? target, result
124
- end
135
+ end
136
+ end
137
+
138
+ def run target, data, &block
139
+ if executor.is_a? Symbol
140
+ target.send executor, &block
141
+ elsif executor.is_a? Proc
142
+ executor.call target, block
143
+ else
144
+ must_be.never_called
145
+ end
146
+ end
147
+ end
148
+
149
+ def run_before_callbacks callback_name, data = {}
150
+ callback_name.must_be.a Symbol
151
+ self.class.callbacks[callback_name].try :each do |callback|
152
+ if callback.is_a? BeforeCallback
153
+ return false unless callback.run self, data
154
+ end
155
+ end
156
+ true
157
+ end
158
+
159
+ def run_after_callbacks callback_name, data = {}
160
+ callback_name.must_be.a Symbol
161
+ self.class.callbacks[callback_name].try :each do |callback|
162
+ callback.run self, data if callback.is_a? AfterCallback
125
163
  end
126
164
  end
127
165
 
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
166
+ def run_callbacks callback_name, data = {}, &block
167
+ callback_name.must_be.a Symbol
168
+ if callbacks = self.class.callbacks[callback_name]
169
+ chain = block || -> {}
170
+ chain = callbacks.reverse.reduce chain do |chain, callback|
171
+ callback.build_block self, data, &chain
138
172
  end
173
+ chain.call
174
+ else
175
+ block.call if block
139
176
  end
140
- chain_head.call
141
177
  end
142
178
 
143
179
  module ClassMethods
144
180
  inheritable_accessor :callbacks, {}
145
-
146
- def set_callback callback_name, type, *executor_or_options, &block
181
+
182
+ def set_callback callback_name, type, *executor_or_options, &block
183
+ callback_name.must_be.a Symbol
184
+ type.must_be.a Symbol
185
+
147
186
  # parsing arguments
148
- type, callback_name = type.to_s, callback_name.to_s
149
- opt = executor_or_options.extract_options!
187
+ opt = executor_or_options.extract_options!
150
188
  "You can't provide both method name and block for filter!" if block and !executor_or_options.empty?
151
189
  executor = block || executor_or_options.first
152
-
153
- type.must_be.in %w{before around after}
190
+
191
+ type.must_be.in [:before, :around, :after]
154
192
  executor.must_be.defined
155
-
193
+
156
194
  # creating callback
195
+ callback = AbstractCallback.new
157
196
  callback = case type
158
- when 'before' then BeforeCallback.new
159
- when 'around' then AroundCallback.new
160
- when 'after' then AfterCallback.new
161
- end
197
+ when :before then BeforeCallback.new
198
+ when :around then AroundCallback.new
199
+ when :after then AfterCallback.new
200
+ end
162
201
 
163
202
  callback.executor = executor
164
- callback.terminator = opt.delete :terminator
203
+ callback.terminator = opt.delete :terminator if type == :before
165
204
  callback.conditions = opt
166
-
167
- callbacks[callback_name] ||= []
168
- callbacks[callback_name] << callback
205
+
206
+ (self.callbacks[callback_name] ||= []) << callback
207
+ # callbacks.send(type) << callback
208
+ # (callbacks[callback_name][type] ||= []) << callback
169
209
  end
170
-
210
+
171
211
  end
172
212
  end
@@ -8,7 +8,7 @@ Module.class_eval do
8
8
  def cache_method_with_params *methods
9
9
  DeclarativeCache.cache_method_with_params self, *methods
10
10
  end
11
-
11
+
12
12
  def clear_cache obj
13
13
  obj.instance_variables.each do |iv|
14
14
  obj.send :remove_instance_variable, iv if iv =~ /_cache$/ or iv =~ /_cache_check$/
@@ -7,7 +7,7 @@ describe 'Object' do
7
7
  class RespondTest
8
8
  def test; 2 end
9
9
  end
10
-
10
+
11
11
  r = RespondTest.new
12
12
  r.respond_to(:not_exist).should be_nil
13
13
  r.respond_to(:test).should == 2
@@ -2,35 +2,45 @@ require 'more/spec_helper'
2
2
 
3
3
  describe "Callbacks" do
4
4
  before :all do
5
- class BasicCallbacksSpec
5
+ module CallbacksSpec; end
6
+ class CallbacksSpec::Basic
6
7
  inherit RubyExt::Callbacks
7
8
 
8
- set_callback :callback_name, :before, :before_callback
9
- set_callback :callback_name, :after, :after_callback
10
- set_callback :callback_name, :around, :around_callback
9
+ set_callback :save, :before, :before_save
10
+ set_callback :save, :around, :around_save
11
+ set_callback :save, :after, :after_save
11
12
 
12
13
  protected
13
- def around_callback
14
- around_callback_called
14
+ def around_save
15
+ around_save_called
15
16
  yield
16
17
  end
17
18
  end
18
19
  end
19
-
20
+ after(:all){remove_constants :CallbacksSpec}
21
+
20
22
  it "basic" do
21
- o = BasicCallbacksSpec.new
22
- o.should_receive :before_callback
23
- o.should_receive :around_callback_called
24
- o.should_receive :after_callback
25
- o.run_callbacks(:callback_name){"result"}.should == "result"
23
+ o = CallbacksSpec::Basic.new
24
+ o.should_receive :before_save
25
+ o.should_receive :around_save_called
26
+ o.should_receive :after_save
27
+ o.run_callbacks(:save){"result"}.should == "result"
28
+ end
29
+
30
+ it "should be possible to call before & after separatelly (in this mode :around is not available)" do
31
+ o = CallbacksSpec::Basic.new
32
+ o.should_receive :before_save
33
+ o.run_before_callbacks(:save)
34
+ o.should_receive :after_save
35
+ o.run_after_callbacks(:save)
26
36
  end
27
37
 
28
38
  it "blocks" do
29
- class BlockCallbacksSpec
39
+ class CallbacksSpec::Blocks
30
40
  inherit RubyExt::Callbacks
31
-
32
- set_callback(:callback_name, :before){|controller| controller.result << :before}
33
- set_callback :callback_name, :around do |controller, block|
41
+
42
+ set_callback(:save, :before){|controller| controller.result << :before}
43
+ set_callback :save, :around do |controller, block|
34
44
  begin
35
45
  controller.result << :around_begin
36
46
  block.call
@@ -38,118 +48,143 @@ describe "Callbacks" do
38
48
  controller.result << :around_end
39
49
  end
40
50
  end
41
- set_callback(:callback_name, :after){|controller| controller.result << :after}
51
+ set_callback(:save, :after){|controller| controller.result << :after}
42
52
 
43
53
  def result
44
54
  @result ||= []
45
55
  end
46
56
  end
47
-
48
- o = BlockCallbacksSpec.new
49
- o.run_callbacks(:callback_name){"result"}.should == "result"
57
+
58
+ o = CallbacksSpec::Blocks.new
59
+ o.run_callbacks(:save){"result"}.should == "result"
50
60
  o.result.should == [:before, :around_begin, :after, :around_end]
51
61
  end
52
62
 
63
+ it "execution order" do
64
+ class CallbacksSpec::ExecutionOrder
65
+ inherit RubyExt::Callbacks
66
+
67
+ # order is important, don't change it
68
+ set_callback :save, :before, :before1
69
+ set_callback :save, :after, :after1
70
+ set_callback :save, :around, :around1
71
+ set_callback :save, :before, :before2
72
+
73
+ protected
74
+ def around1
75
+ around1_called
76
+ yield
77
+ end
78
+ end
79
+
80
+ o = CallbacksSpec::ExecutionOrder.new
81
+ o.should_receive(:before1).ordered.once
82
+ o.should_receive(:around1_called).ordered.once
83
+ o.should_receive(:before2).ordered.once
84
+ o.should_receive(:after1).ordered.once
85
+ o.run_callbacks :save
86
+ end
87
+
53
88
  it "inheritance" do
54
- class InheritedCallbacksSpec < BasicCallbacksSpec
55
- set_callback :callback_name, :before, :before_callback2
89
+ class CallbacksSpec::Inheritance < CallbacksSpec::Basic
90
+ set_callback :save, :before, :before_save2
56
91
  end
57
-
58
- o = InheritedCallbacksSpec.new
59
- o.should_receive :before_callback
60
- o.should_receive :before_callback2
61
- o.should_receive :around_callback_called
62
- o.should_receive :after_callback
63
- o.run_callbacks(:callback_name){"result"}.should == "result"
92
+
93
+ o = CallbacksSpec::Inheritance.new
94
+ o.should_receive :before_save
95
+ o.should_receive :before_save2
96
+ o.should_receive :around_save_called
97
+ o.should_receive :after_save
98
+ o.run_callbacks(:save){"result"}.should == "result"
64
99
  end
65
-
100
+
66
101
  it 'terminator' do
67
- class CallbackTerminatorSpec
102
+ class CallbacksSpec::Terminator
68
103
  inherit RubyExt::Callbacks
69
104
 
70
- set_callback :callback_name, :before, :before_callback, terminator: false
71
- set_callback :callback_name, :before, :before_callback2
105
+ set_callback :save, :before, :before_save, terminator: false
106
+ set_callback :save, :before, :before_save2
72
107
 
73
108
  def method
74
- run_callbacks :callback_name do
109
+ run_callbacks :save do
75
110
  "result"
76
111
  end
77
112
  end
78
113
 
79
114
  protected
80
- def before_callback
81
- false
115
+ def before_save
116
+ false
82
117
  end
83
118
  end
84
-
85
- o = CallbackTerminatorSpec.new
86
- o.should_not_receive :before_callback2
87
- o.run_callbacks(:callback_name){"result"}.should_not == "result"
119
+
120
+ o = CallbacksSpec::Terminator.new
121
+ o.should_not_receive :before_save2
122
+ o.run_callbacks(:save){"result"}.should_not == "result"
88
123
  end
89
-
124
+
90
125
  it 'conditions' do
91
- class CallbackConditionsSpec
126
+ class CallbacksSpec::Conditions
92
127
  inherit RubyExt::Callbacks
93
128
 
94
- set_callback :callback_name, :before, :before_callback, only: :another_method
129
+ set_callback :save, :before, :before_save, only: :another_method
95
130
  end
96
-
97
- o = CallbackConditionsSpec.new
98
- o.should_not_receive :before_callback
99
- o.run_callbacks(:callback_name, method: :method){"result"}.should == 'result'
100
-
101
- o = CallbackConditionsSpec.new
102
- o.should_receive :before_callback
103
- o.run_callbacks(:callback_name, method: :another_method){"result"}.should == 'result'
131
+
132
+ o = CallbacksSpec::Conditions.new
133
+ o.should_not_receive :before_save
134
+ o.run_callbacks(:save, method: :method){"result"}.should == 'result'
135
+
136
+ o = CallbacksSpec::Conditions.new
137
+ o.should_receive :before_save
138
+ o.run_callbacks(:save, method: :another_method){"result"}.should == 'result'
104
139
  end
105
-
140
+
106
141
  it "if, unless conditions" do
107
142
  c = RubyExt::Callbacks::AbstractCallback.new
108
143
  c.conditions = {if: lambda{|target, inf| true}}
109
144
  c.run?(nil, {}).should be_true
110
-
145
+
111
146
  c.conditions = {if: lambda{|target, inf| false}}
112
147
  c.run?(nil, {}).should be_false
113
-
148
+
114
149
  c.conditions = {unless: lambda{|target, inf| true}}
115
150
  c.run?(nil, {}).should be_false
116
-
151
+
117
152
  c.conditions = {unless: lambda{|target, inf| false}}
118
153
  c.run?(nil, {}).should be_true
119
154
  end
120
-
155
+
121
156
  it "only, except conditions" do
122
157
  c = RubyExt::Callbacks::AbstractCallback.new
123
158
  c.conditions = {only: :a}
124
159
  c.run?(nil, {method: :a}).should be_true
125
-
160
+
126
161
  c.conditions = {only: :b}
127
162
  c.run?(nil, {method: :a}).should be_false
128
-
163
+
129
164
  c.conditions = {except: :a}
130
165
  c.run?(nil, {method: :a}).should be_false
131
-
166
+
132
167
  c.conditions = {except: :b}
133
168
  c.run?(nil, {method: :a}).should be_true
134
-
169
+
135
170
  c.conditions = {only: :a}
136
171
  c.run?(nil, {method: :a}).should be_true
137
172
  end
138
-
139
-
173
+
174
+
140
175
  it "around callback should be able to change result value" do
141
- class ChangeResultValueSpec
176
+ class CallbacksSpec::ChangeResult
142
177
  inherit RubyExt::Callbacks
143
-
144
- set_callback :callback_name, :around, :around_callback
145
-
146
- def around_callback
178
+
179
+ set_callback :save, :around, :around_save
180
+
181
+ def around_save
147
182
  yield
148
183
  'another result'
149
184
  end
150
185
  end
151
-
152
- o = ChangeResultValueSpec.new
153
- o.run_callbacks(:callback_name){"result"}.should == 'another result'
186
+
187
+ o = CallbacksSpec::ChangeResult.new
188
+ o.run_callbacks(:save){"result"}.should == 'another result'
154
189
  end
155
190
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_ext
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-08-20 00:00:00.000000000Z
12
+ date: 2011-08-23 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description:
15
15
  email: