rails-workflow 1.4.5.4 → 1.4.6.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +23 -0
- data/Gemfile +2 -1
- data/Rakefile +4 -4
- data/bin/console +3 -3
- data/lib/active_support/overloads.rb +13 -6
- data/lib/workflow.rb +12 -279
- data/lib/workflow/adapters/active_record.rb +57 -50
- data/lib/workflow/adapters/active_record_validations.rb +25 -19
- data/lib/workflow/adapters/adapter.rb +23 -0
- data/lib/workflow/adapters/remodel.rb +8 -9
- data/lib/workflow/callbacks.rb +60 -45
- data/lib/workflow/callbacks/callback.rb +23 -37
- data/lib/workflow/callbacks/method_callback.rb +12 -0
- data/lib/workflow/callbacks/proc_callback.rb +23 -0
- data/lib/workflow/callbacks/string_callback.rb +12 -0
- data/lib/workflow/callbacks/transition_callback.rb +88 -78
- data/lib/workflow/callbacks/transition_callbacks/method_caller.rb +53 -0
- data/lib/workflow/callbacks/transition_callbacks/proc_caller.rb +60 -0
- data/lib/workflow/configuration.rb +1 -0
- data/lib/workflow/definition.rb +73 -0
- data/lib/workflow/errors.rb +37 -6
- data/lib/workflow/event.rb +30 -15
- data/lib/workflow/helper_method_configurator.rb +100 -0
- data/lib/workflow/specification.rb +45 -22
- data/lib/workflow/state.rb +45 -36
- data/lib/workflow/transition_context.rb +5 -4
- data/lib/workflow/transitions.rb +94 -0
- data/lib/workflow/version.rb +2 -1
- data/rails-workflow.gemspec +18 -18
- data/tags.markdown +31 -0
- metadata +13 -5
- data/lib/workflow/callbacks/transition_callbacks/method_wrapper.rb +0 -102
- data/lib/workflow/callbacks/transition_callbacks/proc_wrapper.rb +0 -48
- data/lib/workflow/draw.rb +0 -79
data/lib/workflow/state.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Workflow
|
2
3
|
# Represents one state for the defined workflow,
|
3
4
|
# with a list of {Workflow::Event}s that can transition to
|
@@ -11,35 +12,45 @@ module Workflow
|
|
11
12
|
# @return [Array] Array of {Workflow::Event}s defined for this state.
|
12
13
|
# @!attribute [r] meta
|
13
14
|
# @return [Hash] Extra information defined for this state.
|
14
|
-
|
15
|
+
# @!attribute [r] tags
|
16
|
+
# @return [Array] Tags for this state.
|
17
|
+
attr_reader :name, :events, :meta, :tags
|
15
18
|
|
16
19
|
# @api private
|
17
20
|
# For creating {Workflow::State} objects please see {Specification#state}
|
18
|
-
# @param [Symbol] name
|
19
|
-
# @param [Fixnum] sequence
|
20
|
-
# @param [Hash] meta
|
21
|
-
def initialize(name, sequence, meta: {})
|
22
|
-
@name
|
21
|
+
# @param [Symbol] name Name of the state being created. Must be unique within its workflow.
|
22
|
+
# @param [Fixnum] sequence Sort location among states on this workflow.
|
23
|
+
# @param [Hash] meta Optional metadata for this state.
|
24
|
+
def initialize(name, sequence, tags: [], meta: {})
|
25
|
+
@name = name.to_sym
|
26
|
+
@sequence = sequence
|
27
|
+
@events = []
|
28
|
+
@meta = meta
|
29
|
+
@tags = [tags].flatten
|
30
|
+
unless @tags.reject { |t| t.is_a? Symbol }
|
31
|
+
raise WorkflowDefinitionError, "Tags can only include symbols, state: #{name}"
|
32
|
+
end
|
23
33
|
end
|
24
34
|
|
25
35
|
# Returns the event with the given name.
|
26
36
|
# @param [Symbol] name name of event to find
|
27
37
|
# @return [Workflow::Event] The event with the given name, or `nil`
|
28
38
|
def find_event(name)
|
29
|
-
events.find{|t| t.name == name}
|
39
|
+
events.find { |t| t.name == name }
|
30
40
|
end
|
31
41
|
|
32
42
|
# Define an event on this specification.
|
33
|
-
# Must be called within the scope of the block within a call to {#state}.
|
43
|
+
# Must be called within the scope of the block within a call to {Workflow::Specification#state}.
|
34
44
|
#
|
35
45
|
# @param [Symbol] name The name of the event
|
36
|
-
# @param [Symbol] to
|
37
|
-
#
|
46
|
+
# @param [Symbol] to Optional name of {Workflow::State} this event will transition to.
|
47
|
+
# Must be omitted if a block is provided.
|
48
|
+
# @param [Hash] meta Optional hash of metadata to be stored on the event object.
|
38
49
|
# @yield [] Transitions definition for this event.
|
39
50
|
# @return [nil]
|
40
51
|
#
|
41
|
-
|
42
|
-
#workflow do
|
52
|
+
# ```ruby
|
53
|
+
# workflow do
|
43
54
|
# state :new do
|
44
55
|
# on :review, to: :being_reviewed
|
45
56
|
#
|
@@ -58,21 +69,10 @@ module Workflow
|
|
58
69
|
# state :kitchen
|
59
70
|
# state :the_bar
|
60
71
|
# state :the_diner
|
61
|
-
#end
|
62
|
-
|
72
|
+
# end
|
73
|
+
# ```
|
63
74
|
def on(name, to: nil, meta: {}, &transitions)
|
64
|
-
|
65
|
-
raise Errors::WorkflowDefinitionError.new("Event target can only be received in the method call or the block, not both.")
|
66
|
-
end
|
67
|
-
|
68
|
-
unless to || block_given?
|
69
|
-
raise Errors::WorkflowDefinitionError.new("No event target given for event #{name}")
|
70
|
-
end
|
71
|
-
|
72
|
-
if find_event(name)
|
73
|
-
raise Errors::WorkflowDefinitionError.new("Already defined an event [#{name}] for state[#{self.name}]")
|
74
|
-
end
|
75
|
-
|
75
|
+
check_can_add_transition!(name, to: to, &transitions)
|
76
76
|
event = Workflow::Event.new(name, meta: meta)
|
77
77
|
|
78
78
|
if to
|
@@ -81,14 +81,24 @@ module Workflow
|
|
81
81
|
event.instance_eval(&transitions)
|
82
82
|
end
|
83
83
|
|
84
|
-
|
85
|
-
raise Errors::
|
84
|
+
unless event.valid?
|
85
|
+
raise Errors::NoTransitionsDefinedError.new(self, event)
|
86
86
|
end
|
87
87
|
|
88
88
|
events << event
|
89
89
|
nil
|
90
90
|
end
|
91
91
|
|
92
|
+
private def check_can_add_transition!(name, to: nil)
|
93
|
+
raise Errors::DualEventDefinitionError if to && block_given?
|
94
|
+
|
95
|
+
unless to || block_given?
|
96
|
+
raise Errors::WorkflowDefinitionError, "No event target given for event #{name}"
|
97
|
+
end
|
98
|
+
|
99
|
+
raise Errors::EventNameCollisionError.new(self, name) if find_event(name)
|
100
|
+
end
|
101
|
+
|
92
102
|
# @return [String] String representation of object
|
93
103
|
def inspect
|
94
104
|
"<State name=#{name.inspect} events(#{events.length})=#{events.inspect}>"
|
@@ -97,20 +107,19 @@ module Workflow
|
|
97
107
|
# Overloaded comparison operator. Workflow states are sorted according to the order
|
98
108
|
# in which they were defined.
|
99
109
|
#
|
100
|
-
# @param [Workflow::State]
|
110
|
+
# @param [Workflow::State] other state to be compared against.
|
101
111
|
# @return [Integer]
|
102
|
-
def <=>(
|
103
|
-
unless
|
104
|
-
|
105
|
-
end
|
106
|
-
self.sequence <=> other_state.send(:sequence)
|
112
|
+
def <=>(other)
|
113
|
+
raise Errors::StateComparisonError, other unless other.is_a?(State)
|
114
|
+
sequence <=> other.send(:sequence)
|
107
115
|
end
|
108
116
|
|
109
117
|
private
|
118
|
+
|
110
119
|
# @api private
|
111
120
|
# @!attribute [r] sequence
|
112
|
-
# @return [Fixnum] The position of this state within the
|
121
|
+
# @return [Fixnum] The position of this state within the
|
122
|
+
# order it was defined for in its workflow.
|
113
123
|
attr_reader :sequence
|
114
|
-
|
115
124
|
end
|
116
125
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Workflow
|
2
3
|
# During transitions, an instance of this class can be found
|
3
4
|
# on the object as `transition_context`.
|
@@ -30,20 +31,20 @@ module Workflow
|
|
30
31
|
# If you pass fewer parameters, the later ones will simply be nil.
|
31
32
|
class TransitionContext
|
32
33
|
attr_reader :from, :to, :event, :event_args, :attributes, :named_arguments
|
33
|
-
def initialize(from:, to:, event:, event_args:,
|
34
|
+
def initialize(from:, to:, event:, event_args:, **args)
|
34
35
|
@from = from
|
35
36
|
@to = to
|
36
37
|
@event = event
|
37
38
|
@event_args = event_args
|
38
|
-
@attributes = attributes
|
39
|
-
@named_arguments = (named_arguments || []).zip(event_args).to_h
|
39
|
+
@attributes = args[:attributes] || {}
|
40
|
+
@named_arguments = (args[:named_arguments] || []).zip(event_args).to_h
|
40
41
|
end
|
41
42
|
|
42
43
|
def values
|
43
44
|
[from, to, event, event_args.dup, attributes.dup]
|
44
45
|
end
|
45
46
|
|
46
|
-
def
|
47
|
+
def respond_to_missing?(method, _include_private = false)
|
47
48
|
named_arguments.key?(method) || super
|
48
49
|
end
|
49
50
|
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Workflow
|
3
|
+
module Transitions
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
# @api private
|
7
|
+
# @!attribute [r] transition_context
|
8
|
+
# @return [Workflow::TransitionContext] During transition, or nil if no transition is underway.
|
9
|
+
# During a state transition, contains transition-specific information:
|
10
|
+
# * The name of the {Workflow::State} being exited,
|
11
|
+
# * The name of the {Workflow::State} being entered,
|
12
|
+
# * The name of the {Workflow::Event} that was fired,
|
13
|
+
# * And whatever arguments were passed to the {Workflow#transition!} method.
|
14
|
+
included do
|
15
|
+
attr_reader :transition_context
|
16
|
+
end
|
17
|
+
|
18
|
+
# Initiates state transition via the named event
|
19
|
+
#
|
20
|
+
# @param [Symbol] name name of event to initiate
|
21
|
+
# @param [Array] args State transition arguments.
|
22
|
+
# @return [Symbol] The name of the new state, or `false` if the transition failed.
|
23
|
+
# TODO: connect args to documentation on how arguments are accessed during state transitions.
|
24
|
+
def transition!(name, *args, **attributes)
|
25
|
+
@transition_context = prepare_transition(name, args, attributes)
|
26
|
+
|
27
|
+
run_all_callbacks do
|
28
|
+
persist_workflow_state(@transition_context.to)
|
29
|
+
end
|
30
|
+
ensure
|
31
|
+
@transition_context = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
# Stop the current transition and set the reason for the abort.
|
35
|
+
#
|
36
|
+
# @param [String] reason Optional reason for halting transition.
|
37
|
+
# @return [nil]
|
38
|
+
def halt(reason = nil)
|
39
|
+
@halted_because = reason
|
40
|
+
@halted = true
|
41
|
+
throw :abort
|
42
|
+
end
|
43
|
+
|
44
|
+
# Sets halt reason and raises [TransitionHaltedError] error.
|
45
|
+
#
|
46
|
+
# @param [String] reason Optional reason for halting
|
47
|
+
# @return [nil]
|
48
|
+
def halt!(reason = nil)
|
49
|
+
@halted_because = reason
|
50
|
+
@halted = true
|
51
|
+
raise Errors::TransitionHaltedError, reason
|
52
|
+
end
|
53
|
+
|
54
|
+
# Deprecated. Check for false return value from {#transition!}
|
55
|
+
# @return [Boolean] true if the last transition was halted by one of the transition callbacks.
|
56
|
+
def halted?
|
57
|
+
@halted
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns the reason given to a call to {#halt} or {#halt!}, if any.
|
61
|
+
# @return [String] The reason the transition was aborted.
|
62
|
+
attr_reader :halted_because
|
63
|
+
|
64
|
+
# load_workflow_state and persist_workflow_state
|
65
|
+
# can be overriden to handle the persistence of the workflow state.
|
66
|
+
#
|
67
|
+
# Default (non ActiveRecord) implementation stores the current state
|
68
|
+
# in a variable.
|
69
|
+
#
|
70
|
+
# Default ActiveRecord implementation uses a 'workflow_state' database column.
|
71
|
+
def load_workflow_state
|
72
|
+
@workflow_state if instance_variable_defined? :@workflow_state
|
73
|
+
end
|
74
|
+
|
75
|
+
def persist_workflow_state(new_value)
|
76
|
+
@workflow_state = new_value
|
77
|
+
end
|
78
|
+
|
79
|
+
def prepare_transition(name, args, attributes)
|
80
|
+
event = current_state.find_event(name.to_sym)
|
81
|
+
raise Errors::NoTransitionAllowed.new(current_state, name) unless event
|
82
|
+
|
83
|
+
target = event.evaluate(self)
|
84
|
+
|
85
|
+
TransitionContext.new \
|
86
|
+
from: current_state.name,
|
87
|
+
to: target.name,
|
88
|
+
event: event.name,
|
89
|
+
event_args: args,
|
90
|
+
attributes: attributes,
|
91
|
+
named_arguments: workflow_spec.named_arguments
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/workflow/version.rb
CHANGED
data/rails-workflow.gemspec
CHANGED
@@ -1,41 +1,42 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'workflow/version'
|
5
6
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name =
|
7
|
+
spec.name = 'rails-workflow'
|
7
8
|
spec.version = Workflow::VERSION
|
8
|
-
spec.authors = [
|
9
|
-
spec.email = [
|
9
|
+
spec.authors = ['Tyler Gannon']
|
10
|
+
spec.email = ['tyler@aprilseven.co']
|
10
11
|
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
12
|
+
spec.summary = "A finite-state-machine-inspired API for managing state changes in ActiveModel objects. Based on Vladimir Dobriakov's Workflow gem (https://github.com/geekq/workflow)"
|
13
|
+
spec.description = 'Workflow specifically for ActiveModel objects.'
|
14
|
+
spec.homepage = 'https://tylergannon.github.io/rails-workflow/'
|
15
|
+
spec.license = 'MIT'
|
15
16
|
|
16
17
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
18
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
19
|
if spec.respond_to?(:metadata)
|
19
|
-
spec.metadata['allowed_push_host'] =
|
20
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
20
21
|
else
|
21
|
-
raise
|
22
|
-
|
22
|
+
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
23
|
+
'public gem pushes.'
|
23
24
|
end
|
24
25
|
|
25
|
-
spec.files
|
26
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
26
27
|
f.match(%r{^(test|spec|features|doc)/})
|
27
28
|
end
|
28
|
-
spec.bindir =
|
29
|
+
spec.bindir = 'exe'
|
29
30
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
30
|
-
spec.require_paths = [
|
31
|
+
spec.require_paths = ['lib']
|
31
32
|
spec.extra_rdoc_files = [
|
32
|
-
|
33
|
+
'README.markdown'
|
33
34
|
]
|
34
35
|
|
35
36
|
spec.add_dependency 'activerecord', '~> 5.0'
|
36
37
|
spec.add_dependency 'activesupport', '~> 5.0'
|
37
38
|
|
38
|
-
spec.add_development_dependency 'rdoc',
|
39
|
+
spec.add_development_dependency 'rdoc', ['>= 3.12']
|
39
40
|
spec.add_development_dependency 'sqlite3'
|
40
41
|
spec.add_development_dependency 'mocha'
|
41
42
|
spec.add_development_dependency 'yard'
|
@@ -44,8 +45,7 @@ Gem::Specification.new do |spec|
|
|
44
45
|
spec.add_development_dependency 'rake'
|
45
46
|
spec.add_development_dependency 'test-unit'
|
46
47
|
spec.add_development_dependency 'ruby-graphviz', ['~> 1.0.0']
|
47
|
-
spec.add_development_dependency
|
48
|
-
spec.add_development_dependency
|
48
|
+
spec.add_development_dependency 'bundler', '~> 1.13'
|
49
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
49
50
|
spec.required_ruby_version = '>= 2.3'
|
50
|
-
|
51
51
|
end
|
data/tags.markdown
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
---
|
2
|
+
layout: page
|
3
|
+
---
|
4
|
+
|
5
|
+
# Tagging States
|
6
|
+
|
7
|
+
Place your workflow states into groups by tagging them.
|
8
|
+
Also note the helper methods `initial?` and `terminal?`.
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
class Foo
|
12
|
+
include Workflow
|
13
|
+
state :new, tags: :bar do
|
14
|
+
on :complete, to: :completed
|
15
|
+
end
|
16
|
+
state :completed, tags: [:awesome, :congrats]
|
17
|
+
end
|
18
|
+
|
19
|
+
a = Foo.new
|
20
|
+
a.current_state.bar?
|
21
|
+
# => true
|
22
|
+
a.current_state.initial?
|
23
|
+
# => true
|
24
|
+
a.awesome?
|
25
|
+
# => false
|
26
|
+
a.transition! :complete
|
27
|
+
a.terminal?
|
28
|
+
# => true
|
29
|
+
a.awesome?
|
30
|
+
# => true
|
31
|
+
```
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-workflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.6.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tyler Gannon
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -201,6 +201,7 @@ extra_rdoc_files:
|
|
201
201
|
- README.markdown
|
202
202
|
files:
|
203
203
|
- ".gitignore"
|
204
|
+
- ".rubocop.yml"
|
204
205
|
- ".travis.yml"
|
205
206
|
- ".yardopts"
|
206
207
|
- Gemfile
|
@@ -219,22 +220,29 @@ files:
|
|
219
220
|
- lib/workflow.rb
|
220
221
|
- lib/workflow/adapters/active_record.rb
|
221
222
|
- lib/workflow/adapters/active_record_validations.rb
|
223
|
+
- lib/workflow/adapters/adapter.rb
|
222
224
|
- lib/workflow/adapters/remodel.rb
|
223
225
|
- lib/workflow/callbacks.rb
|
224
226
|
- lib/workflow/callbacks/callback.rb
|
227
|
+
- lib/workflow/callbacks/method_callback.rb
|
228
|
+
- lib/workflow/callbacks/proc_callback.rb
|
229
|
+
- lib/workflow/callbacks/string_callback.rb
|
225
230
|
- lib/workflow/callbacks/transition_callback.rb
|
226
|
-
- lib/workflow/callbacks/transition_callbacks/
|
227
|
-
- lib/workflow/callbacks/transition_callbacks/
|
231
|
+
- lib/workflow/callbacks/transition_callbacks/method_caller.rb
|
232
|
+
- lib/workflow/callbacks/transition_callbacks/proc_caller.rb
|
228
233
|
- lib/workflow/configuration.rb
|
229
|
-
- lib/workflow/
|
234
|
+
- lib/workflow/definition.rb
|
230
235
|
- lib/workflow/errors.rb
|
231
236
|
- lib/workflow/event.rb
|
237
|
+
- lib/workflow/helper_method_configurator.rb
|
232
238
|
- lib/workflow/specification.rb
|
233
239
|
- lib/workflow/state.rb
|
234
240
|
- lib/workflow/transition_context.rb
|
241
|
+
- lib/workflow/transitions.rb
|
235
242
|
- lib/workflow/version.rb
|
236
243
|
- orders_workflow.png
|
237
244
|
- rails-workflow.gemspec
|
245
|
+
- tags.markdown
|
238
246
|
homepage: https://tylergannon.github.io/rails-workflow/
|
239
247
|
licenses:
|
240
248
|
- MIT
|
@@ -1,102 +0,0 @@
|
|
1
|
-
module Workflow
|
2
|
-
module Callbacks
|
3
|
-
module TransitionCallbacks
|
4
|
-
# A {Workflow::Callbacks::TransitionCallback} that wraps an instance method
|
5
|
-
# With arity != 0.
|
6
|
-
# Because the wrapped method may not have been defined at the time the callback
|
7
|
-
# is defined, the string representing the method call is built at runtime
|
8
|
-
# rather than at compile time.
|
9
|
-
class MethodWrapper < ::Workflow::Callbacks::TransitionCallback
|
10
|
-
attr_reader :calling_class
|
11
|
-
|
12
|
-
# Builds a proc object that will correctly call the {#raw_proc}
|
13
|
-
# by inspecting its parameters and pulling arguments from the {Workflow::TransitionContext}
|
14
|
-
# object for the transition.
|
15
|
-
# Given an overloaded `==` operator so for {Workflow#skip_before_transition} and other
|
16
|
-
# `skip_transition` calls.
|
17
|
-
# @return [Type] description of returned object
|
18
|
-
def wrapper
|
19
|
-
cb_object = self
|
20
|
-
proc_string = build_proc(<<-EOF)
|
21
|
-
arguments = [
|
22
|
-
cb_object.send(:raw_proc).inspect,
|
23
|
-
cb_object.send(:name_arguments_string),
|
24
|
-
cb_object.send(:rest_param_string),
|
25
|
-
cb_object.send(:kw_arguments_string),
|
26
|
-
cb_object.send(:keyrest_string),
|
27
|
-
cb_object.send(:procedure_string)].compact.join(', ')
|
28
|
-
target.instance_eval("send(\#{arguments})")
|
29
|
-
EOF
|
30
|
-
_wrapper = eval(proc_string)
|
31
|
-
_wrapper.instance_exec(raw_proc, &OVERLOAD_EQUALITY_OPERATOR_PROC)
|
32
|
-
_wrapper
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
# A that is instanced_exec'd on a new proc object within {#wrapper}
|
38
|
-
#
|
39
|
-
# Enables comparison of two wrapper procs to determine if they wrap the same
|
40
|
-
# Method.
|
41
|
-
OVERLOAD_EQUALITY_OPERATOR_PROC = Proc.new do |method_name|
|
42
|
-
def method_name
|
43
|
-
method_name
|
44
|
-
end
|
45
|
-
|
46
|
-
# Equality operator overload.
|
47
|
-
# If other is a {Symbol}, matches this object against {#method_name} defined above.
|
48
|
-
# If other is a {Proc}:
|
49
|
-
# * If it responds to {#method_name}, matches the method names of the two objects.
|
50
|
-
# * Otherwise false
|
51
|
-
#
|
52
|
-
# @param [Symbol] other A method name to compare against.
|
53
|
-
# @param [Proc] other A proc to compare against.
|
54
|
-
# @return [Boolean] Whether the two should be considered equivalent
|
55
|
-
def ==(other)
|
56
|
-
case other
|
57
|
-
when ::Proc
|
58
|
-
if other.respond_to?(:raw_proc)
|
59
|
-
self.method_name == other.method_name
|
60
|
-
else
|
61
|
-
false
|
62
|
-
end
|
63
|
-
when ::Symbol
|
64
|
-
self.method_name == other
|
65
|
-
else
|
66
|
-
false
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def name_arguments_string
|
72
|
-
if name_params.any?
|
73
|
-
name_params.map{|name|
|
74
|
-
"name_proc.call(:#{name})"
|
75
|
-
}.join(', ')
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def procedure_string
|
80
|
-
'&callbacks' if around_callback?
|
81
|
-
end
|
82
|
-
|
83
|
-
# @return [UnboundMethod] Method representation from class {#calling_class}, named by {#raw_proc}
|
84
|
-
def callback_method
|
85
|
-
@meth ||= calling_class.instance_method(raw_proc)
|
86
|
-
end
|
87
|
-
|
88
|
-
# Parameter definition for the object. See {UnboundMethod#parameters}
|
89
|
-
#
|
90
|
-
# @return [Array] Parameters
|
91
|
-
def parameters
|
92
|
-
callback_method.parameters
|
93
|
-
end
|
94
|
-
|
95
|
-
# @return [Fixnum] Arity of the callback method
|
96
|
-
def arity
|
97
|
-
callback_method.arity
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|