conductor-rails 0.0.9
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 +14 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/Guardfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +170 -0
- data/Rakefile +7 -0
- data/conductor-rails.gemspec +27 -0
- data/lib/conductor.rb +14 -0
- data/lib/conductor/action_runner.rb +29 -0
- data/lib/conductor/base.rb +37 -0
- data/lib/conductor/collection.rb +30 -0
- data/lib/conductor/deferred_export.rb +19 -0
- data/lib/conductor/definition.rb +31 -0
- data/lib/conductor/errors/undefined_conductor.rb +7 -0
- data/lib/conductor/errors/undefined_inherited_method.rb +7 -0
- data/lib/conductor/export.rb +19 -0
- data/lib/conductor/exporter.rb +63 -0
- data/lib/conductor/integrations/action_controller.rb +59 -0
- data/lib/conductor/version.rb +3 -0
- data/spec/conductor/base_spec.rb +9 -0
- data/spec/conductor/collection_spec.rb +16 -0
- data/spec/conductor/definition_spec.rb +56 -0
- data/spec/conductor/integrations/action_controller_spec.rb +56 -0
- data/spec/conductor_spec.rb +11 -0
- data/spec/spec_helper.rb +30 -0
- metadata +176 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e08ac7a5fbda29faff8fea890a3d5c89e7c20b6f
|
4
|
+
data.tar.gz: cf53ed64daad089b9cc52afe2b5d1bea8ff3b2e7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e05715dcdac187330c1d47930da223209d0694c8fc6a96885f8d1aa2dca535fb89631a1fda4ad6cb7ba15bf877b01451f200096cb70db5d55241007c3961f9c3
|
7
|
+
data.tar.gz: 18da39c9855b5fd4eba3ee7de9933bd99a44b2ab283b7851512df232e23941534f9482ce166f13d87b8874fb67ed4f6fe0fc120bc2fee6132c70a863b236b35a
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
2
|
+
watch(%r{^spec/.+_spec\.rb$})
|
3
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
4
|
+
watch(%r{^lib/conductor/(.+)\.rb$}) { |m| "spec/lib/conductor/#{m[1]}_spec.rb" }
|
5
|
+
watch('spec/spec_helper.rb') { "spec" }
|
6
|
+
end
|
7
|
+
|
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,170 @@
|
|
1
|
+
# 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 'conductor-rails'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
Define a Conductor
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
class PagesConductor < Conductor::Base
|
24
|
+
|
25
|
+
# pass it a value directly
|
26
|
+
export :page, "Hello World"
|
27
|
+
|
28
|
+
# delegate to a block for compilation
|
29
|
+
export :meta do
|
30
|
+
"some computed value"
|
31
|
+
end
|
32
|
+
|
33
|
+
# optionally pass arguments from the computed action to the computed value
|
34
|
+
export :foo do |args|
|
35
|
+
"some computed value with arguments"
|
36
|
+
end
|
37
|
+
|
38
|
+
# blocks are executed in the context of the conductor instance, so...
|
39
|
+
export :bar do
|
40
|
+
bar_conductor
|
41
|
+
end
|
42
|
+
|
43
|
+
# ... delegates to ...
|
44
|
+
def bar_conductor
|
45
|
+
end
|
46
|
+
|
47
|
+
# exports are exported in the same order they are established, but you can override that order...
|
48
|
+
order :foo, :page, :meta, :bar
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
Bind it to a Rails Controller
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
class PagesController < ApplicationController
|
56
|
+
conductor :pages, only: [:show]
|
57
|
+
# ...
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
Export computed values via `conductor.exports`
|
62
|
+
```ruby
|
63
|
+
class PagesController < ApplicationController
|
64
|
+
# ...
|
65
|
+
def show
|
66
|
+
@page = conductor.exports
|
67
|
+
end
|
68
|
+
end
|
69
|
+
```
|
70
|
+
or export multiple computed values
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
class PagesController < ApplicationController
|
74
|
+
# ...
|
75
|
+
def show
|
76
|
+
@page, @meta = conductor.exports # => exports in the established order
|
77
|
+
end
|
78
|
+
end
|
79
|
+
```
|
80
|
+
explicitly declare which exports to export, and in which order
|
81
|
+
```ruby
|
82
|
+
class PagesController < ApplicationController
|
83
|
+
# ...
|
84
|
+
def show
|
85
|
+
@meta, @page = conductor.exports(:meta, :page)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
```
|
89
|
+
Pass arguments to the export block
|
90
|
+
```ruby
|
91
|
+
class PagesController < ApplicationController
|
92
|
+
# ...
|
93
|
+
def show
|
94
|
+
@address = conductor.exports(:address, "111 Main St.")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class PagesConductor < Conductor::Base
|
99
|
+
export :address do |street|
|
100
|
+
"#{street} Medford, OR 97501"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
```
|
104
|
+
|
105
|
+
Like Controller filters, conductors are inherited and override (or skip) established conductors
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
class PagesController < ApplicationController
|
109
|
+
conductor :pages, only: [:show]
|
110
|
+
# ...
|
111
|
+
end
|
112
|
+
|
113
|
+
class AdminPagesController < PagesController
|
114
|
+
unset_conductor :pages
|
115
|
+
# ...
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
Extend an existing conductor, while keeping it's established constraints. Extending conductor exports (e.g. AdminPagesConductor) will be added down the export chain
|
120
|
+
```ruby
|
121
|
+
class AdminPagesController < PagesController
|
122
|
+
conductor :admin_pages, extend: :pages
|
123
|
+
|
124
|
+
def show
|
125
|
+
@meta, @page, @admins = conductor.exports(:meta, :page, :admins) # => all values available
|
126
|
+
end
|
127
|
+
|
128
|
+
# ...
|
129
|
+
end
|
130
|
+
```
|
131
|
+
|
132
|
+
Or entirely replace an inherited conductor, while keeping it's established constraints
|
133
|
+
```ruby
|
134
|
+
class AdminPagesController < PagesController
|
135
|
+
conductor :admin_pages, replace: :pages
|
136
|
+
|
137
|
+
def show
|
138
|
+
@meta, @page = conductor.exports(:meta, :page) # => nil
|
139
|
+
@admins = conductor.exports(:admin) # => some value
|
140
|
+
end
|
141
|
+
# ...
|
142
|
+
end
|
143
|
+
```
|
144
|
+
|
145
|
+
If you need to access a specific conductor, with a conflicting named exports, conductor methods are automatically scoped via a prefix. You can continue to access the entire export collection via the root `conductor`
|
146
|
+
```ruby
|
147
|
+
class PagesController < ApplicationController
|
148
|
+
conductor :pages
|
149
|
+
# ...
|
150
|
+
end
|
151
|
+
|
152
|
+
class AdminPagesController < PagesController
|
153
|
+
conductor :admin_pages
|
154
|
+
|
155
|
+
def show
|
156
|
+
@page = pages_conductor.exports(:page)
|
157
|
+
@admin_page = admin_pages_conductor.exports(:page)
|
158
|
+
@admin_page = conductor.exports(:page) # => exports the latest established export (AdminPages)
|
159
|
+
end
|
160
|
+
# ...
|
161
|
+
end
|
162
|
+
```
|
163
|
+
|
164
|
+
## Contributing
|
165
|
+
|
166
|
+
1. Fork it ( https://github.com/[my-github-username]/conductor/fork )
|
167
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
168
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
169
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
170
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'conductor/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "conductor-rails"
|
8
|
+
spec.version = Conductor::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/conductor-rails"
|
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_dependency "rails", "~> 4.1.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.0"
|
24
|
+
spec.add_development_dependency "guard", "~> 2.10.0"
|
25
|
+
spec.add_development_dependency "guard-rspec", "~> 4.3.1"
|
26
|
+
spec.add_development_dependency "pry-byebug"
|
27
|
+
end
|
data/lib/conductor.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "conductor/version"
|
2
|
+
require "conductor/errors/undefined_inherited_method"
|
3
|
+
require "conductor/errors/undefined_conductor"
|
4
|
+
require "conductor/base"
|
5
|
+
require "conductor/definition"
|
6
|
+
require "conductor/collection"
|
7
|
+
require "conductor/action_runner"
|
8
|
+
require "conductor/exporter"
|
9
|
+
require "conductor/export"
|
10
|
+
require "conductor/integrations/action_controller"
|
11
|
+
require "conductor/deferred_export"
|
12
|
+
|
13
|
+
module Conductor
|
14
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Conductor
|
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,37 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Conductor
|
4
|
+
class Base
|
5
|
+
def initialize(controller)
|
6
|
+
@controller = controller
|
7
|
+
@params = controller.params
|
8
|
+
end
|
9
|
+
|
10
|
+
def export(*args)
|
11
|
+
Exporter.new(self).export(args)
|
12
|
+
end
|
13
|
+
|
14
|
+
def exports
|
15
|
+
self.class.exports
|
16
|
+
end
|
17
|
+
|
18
|
+
def export_keys
|
19
|
+
exports.map(&:id)
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
attr_reader :controller, :params
|
25
|
+
|
26
|
+
def self.export(id, value=nil, &block)
|
27
|
+
@exports ||= []
|
28
|
+
|
29
|
+
callback = value.nil? ? block : Proc.new { value }
|
30
|
+
@exports << DeferredExport.new( id: id, callback: callback )
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.exports
|
34
|
+
@exports ||= []
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "delegate"
|
2
|
+
|
3
|
+
module Conductor
|
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,19 @@
|
|
1
|
+
module Conductor
|
2
|
+
class DeferredExport
|
3
|
+
attr_reader :id
|
4
|
+
|
5
|
+
def initialize(options={})
|
6
|
+
@id = options.fetch(:id)
|
7
|
+
@callback = options.fetch(:callback)
|
8
|
+
@context = options.fetch(:context, self)
|
9
|
+
end
|
10
|
+
|
11
|
+
def export(export_value=nil)
|
12
|
+
context.instance_eval { @callback.call export_value }
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
attr_reader :context
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Conductor
|
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,19 @@
|
|
1
|
+
module Conductor
|
2
|
+
class Export
|
3
|
+
attr_reader :id, :value, :context
|
4
|
+
|
5
|
+
def initialize(options={})
|
6
|
+
@id = options.fetch(:id)
|
7
|
+
@value = options.fetch(:value)
|
8
|
+
@context = options.fetch(:context)
|
9
|
+
end
|
10
|
+
|
11
|
+
def export(export_value=nil)
|
12
|
+
if value.is_a? Proc
|
13
|
+
context.instance_eval { value.call exported_value }
|
14
|
+
else
|
15
|
+
value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Conductor
|
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
|
18
|
+
|
19
|
+
def output
|
20
|
+
@output ||= begin
|
21
|
+
selected_exports.to_a.each_with_object([]) do |export, exports|
|
22
|
+
exports << export.export(requested_export_value)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def selected_exports
|
28
|
+
requested_export_keys.map do |key|
|
29
|
+
exports.find { |export| export.id == key }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def exports
|
34
|
+
conductor.exports
|
35
|
+
end
|
36
|
+
|
37
|
+
def export_keys
|
38
|
+
conductor.export_keys
|
39
|
+
end
|
40
|
+
|
41
|
+
def requested_export_keys
|
42
|
+
key_value(arguments)[0]
|
43
|
+
end
|
44
|
+
|
45
|
+
def requested_export_value
|
46
|
+
key_value(arguments)[1]
|
47
|
+
end
|
48
|
+
|
49
|
+
def key_value(args)
|
50
|
+
return [export_keys, nil] if empty? args
|
51
|
+
return [[args[0]], args[1]] if setter? args
|
52
|
+
return [args, nil]
|
53
|
+
end
|
54
|
+
|
55
|
+
def empty?(args)
|
56
|
+
args.empty?
|
57
|
+
end
|
58
|
+
|
59
|
+
def setter?(args)
|
60
|
+
args[0].is_a? Symbol and !args[1].is_a? Symbol
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Conductor
|
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, Conductor::ActionController
|
59
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Conductor
|
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 "conductor/definition"
|
3
|
+
|
4
|
+
class HandleNameConductor
|
5
|
+
end
|
6
|
+
|
7
|
+
class FooBarConductor
|
8
|
+
end
|
9
|
+
|
10
|
+
module Conductor
|
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,56 @@
|
|
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
|
+
context "@foo" do
|
16
|
+
subject { controller.instance_variable_get :@foo }
|
17
|
+
it { is_expected.to eq "Hello World" }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "@foo_a" do
|
21
|
+
subject { controller.instance_variable_get :@foo_a }
|
22
|
+
it { is_expected.to eq "Hello World" }
|
23
|
+
end
|
24
|
+
|
25
|
+
context "@foo_b" do
|
26
|
+
subject { controller.instance_variable_get :@foo_b }
|
27
|
+
it { is_expected.to eq "Hello World" }
|
28
|
+
end
|
29
|
+
|
30
|
+
context "@bar" do
|
31
|
+
subject { controller.instance_variable_get :@bar }
|
32
|
+
it { is_expected.to eq "Goodbye Moon" }
|
33
|
+
end
|
34
|
+
|
35
|
+
context "@bar_a" do
|
36
|
+
subject { controller.instance_variable_get :@bar_a }
|
37
|
+
it { is_expected.to eq "Goodbye Moon" }
|
38
|
+
end
|
39
|
+
|
40
|
+
context "@bar_b" do
|
41
|
+
subject { controller.instance_variable_get :@bar_b }
|
42
|
+
it { is_expected.to eq "Goodbye Moon" }
|
43
|
+
end
|
44
|
+
|
45
|
+
context "@meme" do
|
46
|
+
subject { controller.instance_variable_get :@meme }
|
47
|
+
it { is_expected.to eq "Me me" }
|
48
|
+
end
|
49
|
+
|
50
|
+
context "@omg" do
|
51
|
+
subject { controller.instance_variable_get :@omg }
|
52
|
+
it { is_expected.to eq "LMAO..." }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Conductor do
|
4
|
+
it 'has a version number' do
|
5
|
+
expect(Conductor::VERSION).not_to be nil
|
6
|
+
end
|
7
|
+
|
8
|
+
it "binds to ActionController::Base" do
|
9
|
+
expect(ActionController::Base.ancestors).to include(Conductor::ActionController)
|
10
|
+
end
|
11
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
require "rails"
|
3
|
+
require "action_controller"
|
4
|
+
require 'conductor'
|
5
|
+
require "pry"
|
6
|
+
|
7
|
+
class DummyController < ActionController::Base
|
8
|
+
def params
|
9
|
+
{ action: :index }
|
10
|
+
end
|
11
|
+
|
12
|
+
def index
|
13
|
+
@foo = conductor.export(:foo)
|
14
|
+
@bar = conductor.export(:bar)
|
15
|
+
@foo_a, @bar_a, @meme = conductor.export
|
16
|
+
@bar_b, @foo_b = conductor.export(:bar, :foo)
|
17
|
+
@omg = conductor.export(:omg, "LMAO")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class TestMultiExportConductor < Conductor::Base
|
22
|
+
export :foo, "Hello World"
|
23
|
+
export :bar, "Goodbye Moon"
|
24
|
+
export :meme do
|
25
|
+
"Me me"
|
26
|
+
end
|
27
|
+
export :omg do |lol|
|
28
|
+
"#{lol}..."
|
29
|
+
end
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: conductor-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.9
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adam Cuppy
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-07 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.1.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.1.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.7'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.0.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.0.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: guard
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.10.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.10.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: guard-rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 4.3.1
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 4.3.1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry-byebug
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description:
|
112
|
+
email:
|
113
|
+
- adam@codingzeal.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- ".travis.yml"
|
120
|
+
- Gemfile
|
121
|
+
- Guardfile
|
122
|
+
- LICENSE.txt
|
123
|
+
- README.md
|
124
|
+
- Rakefile
|
125
|
+
- conductor-rails.gemspec
|
126
|
+
- lib/conductor.rb
|
127
|
+
- lib/conductor/action_runner.rb
|
128
|
+
- lib/conductor/base.rb
|
129
|
+
- lib/conductor/collection.rb
|
130
|
+
- lib/conductor/deferred_export.rb
|
131
|
+
- lib/conductor/definition.rb
|
132
|
+
- lib/conductor/errors/undefined_conductor.rb
|
133
|
+
- lib/conductor/errors/undefined_inherited_method.rb
|
134
|
+
- lib/conductor/export.rb
|
135
|
+
- lib/conductor/exporter.rb
|
136
|
+
- lib/conductor/integrations/action_controller.rb
|
137
|
+
- lib/conductor/version.rb
|
138
|
+
- spec/conductor/base_spec.rb
|
139
|
+
- spec/conductor/collection_spec.rb
|
140
|
+
- spec/conductor/definition_spec.rb
|
141
|
+
- spec/conductor/integrations/action_controller_spec.rb
|
142
|
+
- spec/conductor_spec.rb
|
143
|
+
- spec/spec_helper.rb
|
144
|
+
homepage: https://github.com/acuppy/conductor-rails
|
145
|
+
licenses:
|
146
|
+
- MIT
|
147
|
+
metadata: {}
|
148
|
+
post_install_message:
|
149
|
+
rdoc_options: []
|
150
|
+
require_paths:
|
151
|
+
- lib
|
152
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - ">="
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '0'
|
162
|
+
requirements: []
|
163
|
+
rubyforge_project:
|
164
|
+
rubygems_version: 2.2.2
|
165
|
+
signing_key:
|
166
|
+
specification_version: 4
|
167
|
+
summary: DRY-up Rails controllers by leveraging interchangeable conductors to export
|
168
|
+
data
|
169
|
+
test_files:
|
170
|
+
- spec/conductor/base_spec.rb
|
171
|
+
- spec/conductor/collection_spec.rb
|
172
|
+
- spec/conductor/definition_spec.rb
|
173
|
+
- spec/conductor/integrations/action_controller_spec.rb
|
174
|
+
- spec/conductor_spec.rb
|
175
|
+
- spec/spec_helper.rb
|
176
|
+
has_rdoc:
|