action_conductor 0.2.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/.gitignore +15 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +122 -0
- data/Rakefile +7 -0
- data/action_conductor.gemspec +24 -0
- data/lib/action_conductor.rb +13 -0
- data/lib/action_conductor/action_runner.rb +29 -0
- data/lib/action_conductor/base.rb +33 -0
- data/lib/action_conductor/collection.rb +30 -0
- data/lib/action_conductor/deferred_export.rb +17 -0
- data/lib/action_conductor/definition.rb +31 -0
- data/lib/action_conductor/errors/undefined_conductor.rb +7 -0
- data/lib/action_conductor/errors/undefined_inherited_method.rb +7 -0
- data/lib/action_conductor/exporter.rb +71 -0
- data/lib/action_conductor/integrations/action_controller.rb +59 -0
- data/lib/action_conductor/version.rb +3 -0
- data/lib/generators/conductor_generator.rb +19 -0
- data/spec/action_conductor/base_spec.rb +9 -0
- data/spec/action_conductor/collection_spec.rb +16 -0
- data/spec/action_conductor/definition_spec.rb +56 -0
- data/spec/action_conductor/integrations/action_controller_spec.rb +48 -0
- data/spec/action_conductor_spec.rb +11 -0
- data/spec/spec_helper.rb +40 -0
- metadata +145 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: bb81761460837305b560a193300326b3bd21bdb6
|
|
4
|
+
data.tar.gz: 7bc65a7a2c70a4136c7a43c0aef1b83095ec07e6
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: f0bac2b3dcd4e2fb36b2fb3c95153762c25425efb6083f340a917efd658ed87892d10f861932ef9541170200d3a1f7c25ec5055da48e48766d307d8e9e344d62
|
|
7
|
+
data.tar.gz: 14bc14905a03f5d32d812ea891cf2eb3fb93df0c6925fd1a1126a4e8f61d34cdfa2516151d2bdd9ef50ae0d84c639fc1339bc02a1ef3824961bade742897b368
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2014 Adam Cuppy
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Action Conductor
|
|
2
|
+
[](https://travis-ci.org/acuppy/conductor)[](https://codeclimate.com/github/acuppy/conductor)
|
|
3
|
+
|
|
4
|
+
DRY-up Rails Controllers with conductors
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
Add this line to your application's Gemfile:
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
gem 'action_conductor'
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
And then execute:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
$ bundle
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
Define a Conductor in `app/conductors`
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
class PagesConductor < ActionConductor::Base
|
|
26
|
+
|
|
27
|
+
# pass it a value directly
|
|
28
|
+
export :page, "Hello World"
|
|
29
|
+
|
|
30
|
+
# delegate to a block for compilation
|
|
31
|
+
export :meta do
|
|
32
|
+
"some computed value"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# optionally pass arguments from the computed action to the computed value
|
|
36
|
+
export :foo do |args|
|
|
37
|
+
"some computed value with arguments"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# blocks are executed in the context of the conductor instance, so...
|
|
41
|
+
export :bar do
|
|
42
|
+
bar_conductor
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# ... delegates to ...
|
|
46
|
+
def bar_conductor
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Bind it to a Rails Controller
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
class PagesController < ApplicationController
|
|
55
|
+
conductor :pages
|
|
56
|
+
# ...
|
|
57
|
+
end
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Export computed values via `exports`
|
|
61
|
+
```ruby
|
|
62
|
+
class PagesController < ApplicationController
|
|
63
|
+
# ...
|
|
64
|
+
def show
|
|
65
|
+
@page = exports
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
```
|
|
69
|
+
or export multiple computed values
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
class PagesController < ApplicationController
|
|
73
|
+
# ...
|
|
74
|
+
def show
|
|
75
|
+
@page, @meta = exports # => exports in the established order
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
```
|
|
79
|
+
explicitly declare which exports to export, and in which order
|
|
80
|
+
```ruby
|
|
81
|
+
class PagesController < ApplicationController
|
|
82
|
+
# ...
|
|
83
|
+
def show
|
|
84
|
+
@meta, @page = exports(:meta, :page)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
```
|
|
88
|
+
Pass arguments to the export block
|
|
89
|
+
```ruby
|
|
90
|
+
class PagesController < ApplicationController
|
|
91
|
+
# ...
|
|
92
|
+
def show
|
|
93
|
+
@address = exports(:address, "111 Main St.")
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
class PagesConductor < ActionConductor::Base
|
|
98
|
+
export :address do |street|
|
|
99
|
+
"#{street} Medford, OR 97501"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
In case there is a competing `exports` method on the controller, you can access it through
|
|
105
|
+
the `conductor` instance
|
|
106
|
+
|
|
107
|
+
```ruby
|
|
108
|
+
class PagesController < ApplicationController
|
|
109
|
+
# ...
|
|
110
|
+
def show
|
|
111
|
+
@foo = conductor.exports(:foo)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Contributing
|
|
117
|
+
|
|
118
|
+
1. Fork it ( https://github.com/[my-github-username]/conductor/fork )
|
|
119
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
120
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
121
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
122
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'action_conductor/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "action_conductor"
|
|
8
|
+
spec.version = ActionConductor::VERSION
|
|
9
|
+
spec.authors = ["Adam Cuppy"]
|
|
10
|
+
spec.email = ["adam@codingzeal.com"]
|
|
11
|
+
spec.summary = %q{DRY-up Rails controllers by leveraging interchangeable conductors to export data}
|
|
12
|
+
spec.homepage = "https://github.com/acuppy/action_conductor"
|
|
13
|
+
spec.license = "MIT"
|
|
14
|
+
|
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
16
|
+
spec.test_files = spec.files.grep(%r{^(spec|features)/})
|
|
17
|
+
spec.require_paths = ["lib"]
|
|
18
|
+
|
|
19
|
+
spec.add_runtime_dependency 'rails', '~> 4.0', '>= 4.0.0'
|
|
20
|
+
|
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
|
23
|
+
spec.add_development_dependency 'rspec', '~> 3.0', '>= 3.0.0'
|
|
24
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require "action_conductor/version"
|
|
2
|
+
require "action_conductor/errors/undefined_inherited_method"
|
|
3
|
+
require "action_conductor/errors/undefined_conductor"
|
|
4
|
+
require "action_conductor/base"
|
|
5
|
+
require "action_conductor/definition"
|
|
6
|
+
require "action_conductor/collection"
|
|
7
|
+
require "action_conductor/action_runner"
|
|
8
|
+
require "action_conductor/exporter"
|
|
9
|
+
require "action_conductor/integrations/action_controller"
|
|
10
|
+
require "action_conductor/deferred_export"
|
|
11
|
+
|
|
12
|
+
module ActionConductor
|
|
13
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module ActionConductor
|
|
2
|
+
class ActionRunner
|
|
3
|
+
|
|
4
|
+
def initialize(options={})
|
|
5
|
+
@controller = options.fetch(:controller)
|
|
6
|
+
@conductors = options.fetch(:conductors)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def export(*options)
|
|
10
|
+
@exported ||= {}
|
|
11
|
+
@exported[options] ||= begin
|
|
12
|
+
exported = export_with_options(options)
|
|
13
|
+
exported.length == 1 ? exported.first : exported
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
attr_accessor :controller, :conductors
|
|
20
|
+
|
|
21
|
+
def export_with_options(options)
|
|
22
|
+
initialized_conductors.flat_map { |c| c.export(*options) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def initialized_conductors
|
|
26
|
+
@initialized_conductors ||= Collection.new(conductors.map { |c| c.new(controller) })
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module ActionConductor
|
|
2
|
+
class Base
|
|
3
|
+
def initialize(controller)
|
|
4
|
+
@controller = controller
|
|
5
|
+
@params = controller.params
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def export(*args)
|
|
9
|
+
Exporter.new(self).export(args)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def exports
|
|
13
|
+
self.class.exports
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def export_keys
|
|
17
|
+
exports.map(&:id)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
protected
|
|
21
|
+
|
|
22
|
+
attr_reader :controller, :params
|
|
23
|
+
|
|
24
|
+
def self.export(id, value=nil, &block)
|
|
25
|
+
callback = value.nil? ? block : Proc.new { value }
|
|
26
|
+
exports << DeferredExport.new(id, &callback)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.exports
|
|
30
|
+
@exports ||= []
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require "delegate"
|
|
2
|
+
|
|
3
|
+
module ActionConductor
|
|
4
|
+
class Collection < SimpleDelegator
|
|
5
|
+
|
|
6
|
+
attr_reader :conductors
|
|
7
|
+
|
|
8
|
+
def initialize(conductors = Array.new)
|
|
9
|
+
@conductors = conductors
|
|
10
|
+
super(@conductors)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def with_handle(handle)
|
|
14
|
+
conductors = selected_conductors_by_handle(handle)
|
|
15
|
+
|
|
16
|
+
if conductors.empty?
|
|
17
|
+
raise "No conductors with the handle: #{handle}"
|
|
18
|
+
else
|
|
19
|
+
conductors
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def selected_conductors_by_handle(handle)
|
|
26
|
+
return self if handle.nil?
|
|
27
|
+
self.class.new(conductors.select { |c| c.handle = handle })
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module ActionConductor
|
|
2
|
+
class DeferredExport
|
|
3
|
+
attr_reader :id
|
|
4
|
+
|
|
5
|
+
def initialize(id, &callback)
|
|
6
|
+
@id, @callback = id, callback
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def export(context, export_value=nil)
|
|
10
|
+
context.instance_exec(export_value, &callback)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
attr_reader :context, :callback
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module ActionConductor
|
|
2
|
+
class Definition
|
|
3
|
+
attr_reader :handle, :class_name
|
|
4
|
+
|
|
5
|
+
def initialize(configs={})
|
|
6
|
+
@handle = configs.fetch(:handle)
|
|
7
|
+
@actions = configs.fetch(:actions, [])
|
|
8
|
+
@class_name = configs.fetch(:class_name, @handle)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def klass
|
|
12
|
+
@conductor_klass ||= conductor_klass
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def actions
|
|
16
|
+
@actions ||= Set.new(@actions)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def conductor_klass
|
|
22
|
+
Object.const_get(conductor_klass_name)
|
|
23
|
+
rescue NameError
|
|
24
|
+
raise UndefinedConductor.new(conductor_klass_name)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def conductor_klass_name
|
|
28
|
+
"#{class_name.to_s.camelize}Conductor"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module ActionConductor
|
|
2
|
+
class Exporter
|
|
3
|
+
|
|
4
|
+
attr_reader :conductor
|
|
5
|
+
|
|
6
|
+
def initialize(conductor)
|
|
7
|
+
@conductor = conductor
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def export(arguments)
|
|
11
|
+
@arguments = arguments
|
|
12
|
+
output.length == 1 ? output.first : output
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
attr_reader :arguments, :context
|
|
18
|
+
|
|
19
|
+
def output
|
|
20
|
+
@output ||= begin
|
|
21
|
+
enumerable_exports do |deferred, exports|
|
|
22
|
+
exports << export_deferred(deferred)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def enumerable_exports(&block)
|
|
28
|
+
selected_exports.to_a.each_with_object([], &block)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def export_deferred(deferred)
|
|
32
|
+
deferred.export(conductor, requested_export_value)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def selected_exports
|
|
36
|
+
requested_export_keys.map do |key|
|
|
37
|
+
exports.find { |export| export.id == key }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def exports
|
|
42
|
+
conductor.exports
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def export_keys
|
|
46
|
+
conductor.export_keys
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def requested_export_keys
|
|
50
|
+
key_value(arguments)[0]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def requested_export_value
|
|
54
|
+
key_value(arguments)[1]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def key_value(args)
|
|
58
|
+
return [export_keys, nil] if empty? args
|
|
59
|
+
return [[args[0]], args[1]] if setter? args
|
|
60
|
+
return [args, nil]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def empty?(args)
|
|
64
|
+
args.empty?
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def setter?(args)
|
|
68
|
+
args[0].is_a? Symbol and !args[1].is_a? Symbol
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module ActionConductor
|
|
2
|
+
module ActionController
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
module ClassMethods
|
|
6
|
+
def conductor(handle, options={})
|
|
7
|
+
register_conductor define_conductor(handle, options)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def register_conductor(definition)
|
|
13
|
+
conductors << definition.klass
|
|
14
|
+
|
|
15
|
+
define_method "#{definition.handle}_conductor" do
|
|
16
|
+
self.conductor(definition.handle)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def define_conductor(handle, options={})
|
|
21
|
+
only_actions = options.fetch(:only) { self.action_methods.to_a }
|
|
22
|
+
except_actions = options.fetch(:except) { [] }
|
|
23
|
+
actions = only_actions - except_actions
|
|
24
|
+
|
|
25
|
+
Definition.new(handle: handle, actions: actions)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def conductors
|
|
29
|
+
@conductors ||= Collection.new
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def conductor(handle=nil)
|
|
34
|
+
@action_runner ||= {}
|
|
35
|
+
@action_runner[handle] ||=
|
|
36
|
+
ActionRunner.new( controller: self, conductors: conductors.with_handle(handle))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def exports(*args)
|
|
40
|
+
conductor.export(*args)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def conductors
|
|
46
|
+
_conductors = self.class.send(:conductors)
|
|
47
|
+
|
|
48
|
+
if _conductors.empty?
|
|
49
|
+
raise "No conductors have been defined"
|
|
50
|
+
else
|
|
51
|
+
_conductors
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
if defined? ActionController::Base
|
|
58
|
+
ActionController::Base.send :include, ActionConductor::ActionController
|
|
59
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'rails/generators'
|
|
2
|
+
require 'rails/generators/migration'
|
|
3
|
+
|
|
4
|
+
module ActionConductor
|
|
5
|
+
module Generators
|
|
6
|
+
class ConductorGenerator < ::Rails::Generators::Base
|
|
7
|
+
include Rails::Generators::Migration
|
|
8
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
9
|
+
|
|
10
|
+
def self.next_migration_number(path)
|
|
11
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def copy_migration
|
|
15
|
+
migration_template 'migration.rb', "db/migrate/create_.rb"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
module ActionConductor
|
|
4
|
+
describe Collection do
|
|
5
|
+
let(:conductor) { }
|
|
6
|
+
describe "#with_handle" do
|
|
7
|
+
context "no conductor found" do
|
|
8
|
+
pending
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
context "when conductors are found" do
|
|
12
|
+
pending
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "action_conductor/definition"
|
|
3
|
+
|
|
4
|
+
class HandleNameConductor
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class FooBarConductor
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module ActionConductor
|
|
11
|
+
describe Definition do
|
|
12
|
+
shared_examples_for "a definition class" do
|
|
13
|
+
let(:class_name) { nil }
|
|
14
|
+
let(:actions) { ["foo", "bar"] }
|
|
15
|
+
let(:arguments) do
|
|
16
|
+
{
|
|
17
|
+
handle: handle,
|
|
18
|
+
actions: actions
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
subject(:definition) { described_class.new arguments }
|
|
23
|
+
|
|
24
|
+
before do
|
|
25
|
+
arguments.update(class_name: class_name) if class_name
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it { expect(definition.handle).to eq handle }
|
|
29
|
+
it { expect(definition.klass).to eq conductor }
|
|
30
|
+
it { expect(definition.actions).to eq actions }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context "when conductor class doesn't exist" do
|
|
34
|
+
let(:handle) { "not_defind" }
|
|
35
|
+
|
|
36
|
+
subject(:definition) { described_class.new handle: handle }
|
|
37
|
+
|
|
38
|
+
it { expect { definition.klass }.to raise_error UndefinedConductor }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context "when class_name is assumed" do
|
|
42
|
+
it_behaves_like "a definition class" do
|
|
43
|
+
let(:handle) { "handle_name" }
|
|
44
|
+
let(:conductor) { HandleNameConductor }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context "when class_name is defined" do
|
|
49
|
+
it_behaves_like "a definition class" do
|
|
50
|
+
let(:handle) { "handle_name" }
|
|
51
|
+
let(:class_name) { "foo_bar" }
|
|
52
|
+
let(:conductor) { FooBarConductor }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe DummyController, "Integration ActionController::Base" do
|
|
4
|
+
describe ".conductor" do
|
|
5
|
+
subject(:controller) { DummyController.new }
|
|
6
|
+
|
|
7
|
+
before(:all) { DummyController.class_eval { conductor :test_multi_export } }
|
|
8
|
+
|
|
9
|
+
it { expect(subject).to respond_to :conductor }
|
|
10
|
+
it { expect(subject).to respond_to :exports }
|
|
11
|
+
|
|
12
|
+
context "when exporting" do
|
|
13
|
+
before { controller.index }
|
|
14
|
+
|
|
15
|
+
["@foo", "@foo_a", "@foo_b"].each do |var|
|
|
16
|
+
context var do
|
|
17
|
+
subject { controller.instance_variable_get var.to_sym }
|
|
18
|
+
it { is_expected.to eq "Hello World" }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
["@bar", "@bar_a", "@bar_b"].each do |var|
|
|
23
|
+
context var do
|
|
24
|
+
subject { controller.instance_variable_get var.to_sym }
|
|
25
|
+
it { is_expected.to eq "Goodbye Moon" }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
context "@meme" do
|
|
30
|
+
subject { controller.instance_variable_get :@meme }
|
|
31
|
+
it { is_expected.to eq "Me me" }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context "@omg" do
|
|
35
|
+
subject { controller.instance_variable_get :@omg }
|
|
36
|
+
it { is_expected.to eq "LMAO..." }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context "@my_method" do
|
|
40
|
+
subject { controller.instance_variable_get :@my_method }
|
|
41
|
+
it { is_expected.to eq "conductor method called" }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context "without explicitly defining the conductor" do
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ActionConductor do
|
|
4
|
+
it 'has a version number' do
|
|
5
|
+
expect(ActionConductor::VERSION).not_to be nil
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "binds to ActionController::Base" do
|
|
9
|
+
expect(ActionController::Base.ancestors).to include(ActionConductor::ActionController)
|
|
10
|
+
end
|
|
11
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
|
2
|
+
require "rails"
|
|
3
|
+
require "action_controller"
|
|
4
|
+
require 'action_conductor'
|
|
5
|
+
|
|
6
|
+
class DummyController < ActionController::Base
|
|
7
|
+
def params
|
|
8
|
+
{ action: :index }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def index
|
|
12
|
+
@foo = exports(:foo)
|
|
13
|
+
@bar = conductor.export(:bar)
|
|
14
|
+
@foo_a, @bar_a, @meme = conductor.export
|
|
15
|
+
@bar_b, @foo_b = conductor.export(:bar, :foo)
|
|
16
|
+
@omg = conductor.export(:omg, "LMAO")
|
|
17
|
+
@my_method = conductor.export(:my_method)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class TestMultiExportConductor < ActionConductor::Base
|
|
22
|
+
export :foo, "Hello World"
|
|
23
|
+
export :bar, "Goodbye Moon"
|
|
24
|
+
|
|
25
|
+
export :meme do
|
|
26
|
+
"Me me"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
export :omg do |lol|
|
|
30
|
+
"#{lol}..."
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
export :my_method do
|
|
34
|
+
my_method
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def my_method
|
|
38
|
+
"conductor method called"
|
|
39
|
+
end
|
|
40
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: action_conductor
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Adam Cuppy
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-03-10 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rails
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '4.0'
|
|
20
|
+
- - ">="
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: 4.0.0
|
|
23
|
+
type: :runtime
|
|
24
|
+
prerelease: false
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
requirements:
|
|
27
|
+
- - "~>"
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '4.0'
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 4.0.0
|
|
33
|
+
- !ruby/object:Gem::Dependency
|
|
34
|
+
name: bundler
|
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.7'
|
|
40
|
+
type: :development
|
|
41
|
+
prerelease: false
|
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '1.7'
|
|
47
|
+
- !ruby/object:Gem::Dependency
|
|
48
|
+
name: rake
|
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '10.0'
|
|
54
|
+
type: :development
|
|
55
|
+
prerelease: false
|
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '10.0'
|
|
61
|
+
- !ruby/object:Gem::Dependency
|
|
62
|
+
name: rspec
|
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '3.0'
|
|
68
|
+
- - ">="
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
version: 3.0.0
|
|
71
|
+
type: :development
|
|
72
|
+
prerelease: false
|
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
74
|
+
requirements:
|
|
75
|
+
- - "~>"
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '3.0'
|
|
78
|
+
- - ">="
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: 3.0.0
|
|
81
|
+
description:
|
|
82
|
+
email:
|
|
83
|
+
- adam@codingzeal.com
|
|
84
|
+
executables: []
|
|
85
|
+
extensions: []
|
|
86
|
+
extra_rdoc_files: []
|
|
87
|
+
files:
|
|
88
|
+
- ".gitignore"
|
|
89
|
+
- ".travis.yml"
|
|
90
|
+
- Gemfile
|
|
91
|
+
- LICENSE.txt
|
|
92
|
+
- README.md
|
|
93
|
+
- Rakefile
|
|
94
|
+
- action_conductor.gemspec
|
|
95
|
+
- lib/action_conductor.rb
|
|
96
|
+
- lib/action_conductor/action_runner.rb
|
|
97
|
+
- lib/action_conductor/base.rb
|
|
98
|
+
- lib/action_conductor/collection.rb
|
|
99
|
+
- lib/action_conductor/deferred_export.rb
|
|
100
|
+
- lib/action_conductor/definition.rb
|
|
101
|
+
- lib/action_conductor/errors/undefined_conductor.rb
|
|
102
|
+
- lib/action_conductor/errors/undefined_inherited_method.rb
|
|
103
|
+
- lib/action_conductor/exporter.rb
|
|
104
|
+
- lib/action_conductor/integrations/action_controller.rb
|
|
105
|
+
- lib/action_conductor/version.rb
|
|
106
|
+
- lib/generators/conductor_generator.rb
|
|
107
|
+
- spec/action_conductor/base_spec.rb
|
|
108
|
+
- spec/action_conductor/collection_spec.rb
|
|
109
|
+
- spec/action_conductor/definition_spec.rb
|
|
110
|
+
- spec/action_conductor/integrations/action_controller_spec.rb
|
|
111
|
+
- spec/action_conductor_spec.rb
|
|
112
|
+
- spec/spec_helper.rb
|
|
113
|
+
homepage: https://github.com/acuppy/action_conductor
|
|
114
|
+
licenses:
|
|
115
|
+
- MIT
|
|
116
|
+
metadata: {}
|
|
117
|
+
post_install_message:
|
|
118
|
+
rdoc_options: []
|
|
119
|
+
require_paths:
|
|
120
|
+
- lib
|
|
121
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
122
|
+
requirements:
|
|
123
|
+
- - ">="
|
|
124
|
+
- !ruby/object:Gem::Version
|
|
125
|
+
version: '0'
|
|
126
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - ">="
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '0'
|
|
131
|
+
requirements: []
|
|
132
|
+
rubyforge_project:
|
|
133
|
+
rubygems_version: 2.2.2
|
|
134
|
+
signing_key:
|
|
135
|
+
specification_version: 4
|
|
136
|
+
summary: DRY-up Rails controllers by leveraging interchangeable conductors to export
|
|
137
|
+
data
|
|
138
|
+
test_files:
|
|
139
|
+
- spec/action_conductor/base_spec.rb
|
|
140
|
+
- spec/action_conductor/collection_spec.rb
|
|
141
|
+
- spec/action_conductor/definition_spec.rb
|
|
142
|
+
- spec/action_conductor/integrations/action_controller_spec.rb
|
|
143
|
+
- spec/action_conductor_spec.rb
|
|
144
|
+
- spec/spec_helper.rb
|
|
145
|
+
has_rdoc:
|