ruby_ext 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
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: