ribbon-plugins 0.1.0
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.
- checksums.yaml +7 -0
- data/lib/ribbon/plugins/around_stack.rb +63 -0
- data/lib/ribbon/plugins/block_stack.rb +15 -0
- data/lib/ribbon/plugins/errors.rb +6 -0
- data/lib/ribbon/plugins/plugin.rb +53 -0
- data/lib/ribbon/plugins/version.rb +5 -0
- data/lib/ribbon/plugins.rb +89 -0
- metadata +70 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 230fbea0e698049dd095f097a6d977eca0e17359
|
4
|
+
data.tar.gz: 65c29190976d2a231e41493ad9840dbf9bdf90f3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6635638f54be4b62c15e4e988f60636d2e37d2bbb0d8686f785e2cba13a11a994d7f7a51dc664085f8cd021de9a2920a66c6a9531276b1c188cd9e7979537e8f
|
7
|
+
data.tar.gz: c70c4dec948b31c09c49e8bf61be462386095da0bce1ae5d3032b7951a46f77ec660932a3fd0a0bc7f6477f432f4c3b8b1bb0b446302477aa62bf5584298064b
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class Ribbon::Plugins
|
2
|
+
class AroundStack
|
3
|
+
attr_reader :subject
|
4
|
+
|
5
|
+
def initialize(subject)
|
6
|
+
@subject = subject.to_sym
|
7
|
+
@_stack = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def push(&block)
|
11
|
+
raise Errors::Error, "Must pass block" unless block_given?
|
12
|
+
|
13
|
+
AroundWrapper.new(subject, &block).tap { |wrapper|
|
14
|
+
@_stack.push(wrapper)
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(*args, &block)
|
19
|
+
raise Errors::Error, "Must pass block" unless block_given?
|
20
|
+
call_stack = @_stack.dup
|
21
|
+
|
22
|
+
inner_most = WrappedBlock.new(&block)
|
23
|
+
call_stack.unshift(inner_most)
|
24
|
+
|
25
|
+
outer_most = call_stack.pop
|
26
|
+
outer_most.call(call_stack, *args)
|
27
|
+
end
|
28
|
+
|
29
|
+
class AroundWrapper
|
30
|
+
attr_reader :subject, :block
|
31
|
+
|
32
|
+
def initialize(subject, &block)
|
33
|
+
@subject = subject
|
34
|
+
@block = block
|
35
|
+
end
|
36
|
+
|
37
|
+
def call(call_stack, *args)
|
38
|
+
wrapped = call_stack.pop
|
39
|
+
raise Errors::Error, 'call stack too short' unless wrapped
|
40
|
+
|
41
|
+
define_singleton_method("perform_#{subject}") { |*new_args|
|
42
|
+
args = new_args unless new_args.empty?
|
43
|
+
wrapped.call(call_stack, *args)
|
44
|
+
}
|
45
|
+
|
46
|
+
instance_exec(*args, &block)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class WrappedBlock
|
51
|
+
attr_reader :block
|
52
|
+
|
53
|
+
def initialize(&block)
|
54
|
+
@block = block
|
55
|
+
end
|
56
|
+
|
57
|
+
def call(call_stack, *args)
|
58
|
+
raise Errors::Error, 'receiving non-empty call stack' unless call_stack.empty?
|
59
|
+
block.call(*args)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end # AroundStack
|
63
|
+
end # Ribbon::Plugins
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class Ribbon::Plugins
|
2
|
+
class Plugin
|
3
|
+
class << self
|
4
|
+
def create(&block)
|
5
|
+
Class.new(Plugin).tap { |k| k.class_eval(&block) if block }
|
6
|
+
end
|
7
|
+
|
8
|
+
def method_missing(meth, *args, &block)
|
9
|
+
if /^(before|after|around)_(\w+)$/.match(meth.to_s)
|
10
|
+
_define_callback($1, $2, &block)
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def _define_callback(type, subject, &block)
|
17
|
+
_callbacks(type, subject).push(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def _callbacks(type, subject)
|
21
|
+
((@__callbacks ||= {})[type.to_sym] ||= {})[subject.to_sym] ||= _empty_stack_for(type, subject)
|
22
|
+
end
|
23
|
+
|
24
|
+
def _empty_stack_for(type, subject)
|
25
|
+
case type.to_sym
|
26
|
+
when :before, :after
|
27
|
+
BlockStack.new
|
28
|
+
when :around
|
29
|
+
AroundStack.new(subject)
|
30
|
+
else
|
31
|
+
raise Errors::Error, "Invalid type: #{type}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def before(subject, *args)
|
37
|
+
_callbacks(:before, subject).call(*args)
|
38
|
+
end
|
39
|
+
|
40
|
+
def after(subject, *args)
|
41
|
+
_callbacks(:after, subject).call(*args)
|
42
|
+
end
|
43
|
+
|
44
|
+
def around(subject, *args, &block)
|
45
|
+
_callbacks(:around, subject).call(*args, &block)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def _callbacks(type, subject)
|
50
|
+
self.class._callbacks(type, subject)
|
51
|
+
end
|
52
|
+
end # Plugin
|
53
|
+
end # Ribbon::Plugins
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'ribbon/plugins/version'
|
2
|
+
|
3
|
+
module Ribbon
|
4
|
+
class Plugins
|
5
|
+
autoload(:Errors, 'ribbon/plugins/errors')
|
6
|
+
autoload(:Plugin, 'ribbon/plugins/plugin')
|
7
|
+
autoload(:AroundStack, 'ribbon/plugins/around_stack')
|
8
|
+
autoload(:BlockStack, 'ribbon/plugins/block_stack')
|
9
|
+
|
10
|
+
def initialize(plugin_module=nil)
|
11
|
+
@_plugin_module = plugin_module
|
12
|
+
end
|
13
|
+
|
14
|
+
def add(plugin=nil, &block)
|
15
|
+
plugin = _load(plugin, &block)
|
16
|
+
_add_plugin(plugin.new)
|
17
|
+
end
|
18
|
+
|
19
|
+
def clear
|
20
|
+
@_plugins = []
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def before(subject, *args)
|
25
|
+
_plugins.reverse_each { |plugin| plugin.before(subject, *args) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def after(subject, *args)
|
29
|
+
_plugins.reverse_each { |plugin| plugin.after(subject, *args) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def around(subject, *args, &block)
|
33
|
+
_around_stack.call(subject, *args) { |subject, *args| block.call(*args) }
|
34
|
+
end
|
35
|
+
|
36
|
+
def perform(subject, *args, &block)
|
37
|
+
before(subject, *args)
|
38
|
+
around(subject, *args, &block)
|
39
|
+
after(subject, *args)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def _plugins
|
44
|
+
@_plugins ||= []
|
45
|
+
end
|
46
|
+
|
47
|
+
def _around_stack
|
48
|
+
@__around_stack ||= AroundStack.new(:block)
|
49
|
+
end
|
50
|
+
|
51
|
+
def _add_plugin(plugin)
|
52
|
+
_plugins.push(plugin)
|
53
|
+
_around_stack.push { |subject, *args|
|
54
|
+
plugin.around(subject, *args) {
|
55
|
+
perform_block
|
56
|
+
}
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def _load(plugin, &block)
|
61
|
+
if plugin
|
62
|
+
_load_plugin(plugin)
|
63
|
+
elsif block_given?
|
64
|
+
Plugin.create(&block)
|
65
|
+
else
|
66
|
+
raise Errors::LoadError, 'No plugin information provided'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def _load_plugin(plugin)
|
71
|
+
case plugin
|
72
|
+
when Class
|
73
|
+
plugin < Plugin && plugin or
|
74
|
+
raise Errors::LoadError, "Invalid plugin class: #{plugin.inspect} Must extend Plugin."
|
75
|
+
when Symbol, String
|
76
|
+
_load_plugin_by_name(plugin)
|
77
|
+
when Proc
|
78
|
+
Plugin.create(&plugin)
|
79
|
+
else
|
80
|
+
raise Errors::LoadError, "Invalid plugin identifier: #{plugin.inspect}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def _load_plugin_by_name(name)
|
85
|
+
@_plugin_module && @_plugin_module.const_get("#{name.upcase}Plugin") or
|
86
|
+
raise Errors::LoadError, "Cannot load plugin by name. No plugin module provided."
|
87
|
+
end
|
88
|
+
end # Plugins
|
89
|
+
end # Ribbon
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ribbon-plugins
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Robert Honer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.2'
|
20
|
+
- - '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.2.0
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.2'
|
30
|
+
- - '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.2.0
|
33
|
+
description: A flexible plugins framework.
|
34
|
+
email:
|
35
|
+
- robert@ribbonpayments.com
|
36
|
+
executables: []
|
37
|
+
extensions: []
|
38
|
+
extra_rdoc_files: []
|
39
|
+
files:
|
40
|
+
- lib/ribbon/plugins.rb
|
41
|
+
- lib/ribbon/plugins/around_stack.rb
|
42
|
+
- lib/ribbon/plugins/block_stack.rb
|
43
|
+
- lib/ribbon/plugins/errors.rb
|
44
|
+
- lib/ribbon/plugins/plugin.rb
|
45
|
+
- lib/ribbon/plugins/version.rb
|
46
|
+
homepage: http://github.com/ribbon/plugins
|
47
|
+
licenses:
|
48
|
+
- BSD
|
49
|
+
metadata: {}
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
requirements: []
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 2.2.2
|
67
|
+
signing_key:
|
68
|
+
specification_version: 4
|
69
|
+
summary: A flexible plugins framework.
|
70
|
+
test_files: []
|