simple_controller 0.1.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +64 -6
- data/lib/simple_controller/base.rb +2 -0
- data/lib/simple_controller/base/context.rb +27 -0
- data/lib/simple_controller/base/core.rb +3 -1
- data/lib/simple_controller/router.rb +4 -50
- data/lib/simple_controller/router/context.rb +38 -0
- data/lib/simple_controller/router/core.rb +61 -0
- data/lib/simple_controller/router/mapper.rb +19 -19
- data/lib/simple_controller/router/route.rb +7 -9
- data/lib/simple_controller/version.rb +1 -1
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 524340d2ca7c377417e63196f002bf3d6c26e2ed
|
4
|
+
data.tar.gz: 9d7cefb26e4bd4821643eff5979143d5d113820e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ed3f6ed15a1a6567923ffd324fc15e4b550cba0a23be0455a8a26ad066f65e4396ff42f0eda1183d88068b0664b743ab987ff755eadf0db8db2644eaab60a23
|
7
|
+
data.tar.gz: 05e9b2d919c96ca1355fc364c7bcdd3b91dfd85920df263432f7d693070efc01b110e08e7c6cb7dc7945dc16cacdae01664f0690570ffd9d5ebfa2eb34078001
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -42,11 +42,10 @@ It works like a Rails Controller, but has only has the following features:
|
|
42
42
|
- `action_name`
|
43
43
|
|
44
44
|
## Router
|
45
|
-
|
45
|
+
An **optional** router is provided to decouple controller classes from identifiers.
|
46
46
|
|
47
47
|
```ruby
|
48
|
-
class Router < SimpleController::Router
|
49
|
-
end
|
48
|
+
class Router < SimpleController::Router; end
|
50
49
|
|
51
50
|
# Router.instance is a singleton for ease of use
|
52
51
|
Router.instance.draw do
|
@@ -71,9 +70,68 @@ Router.call("threes/multiply", number: 6) # calls ThreesController.call(:multipl
|
|
71
70
|
Router.instance.call("threes/multiply", number: 6) # same as above
|
72
71
|
```
|
73
72
|
|
74
|
-
To
|
73
|
+
To customize the controller class:
|
75
74
|
```ruby
|
76
|
-
Router.instance.
|
77
|
-
|
75
|
+
Router.instance.parse_controller_path do |controller_path|
|
76
|
+
# similar to default implementation
|
77
|
+
"#{controller_name}_suffix_controller".classify.constantize
|
78
|
+
end
|
78
79
|
Router.call("threes/multiply", number: 6) # calls ThreesSuffixController.call(:multiply, number: 6)
|
80
|
+
```
|
81
|
+
|
82
|
+
Routers add the following Rails features to the Controllers:
|
83
|
+
- `params[:action]` and `params[:controller]`
|
84
|
+
- `controller_path` and `controller_name`
|
85
|
+
|
86
|
+
## Post-Process
|
87
|
+
Inspired by [`rails/sprockets` Processors](https://github.com/rails/sprockets#using-processors), Routes can have processor suffixes to ensure that controller endpoints
|
88
|
+
are [composable](https://en.wikipedia.org/wiki/Function_composition_(computer_science)). For example, given:
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
class FoldersController < FileSystemController
|
92
|
+
def two_readmes
|
93
|
+
dir = create_new_directory
|
94
|
+
dir.add_files Router.call('files/readme'), Router.call('files/readme')
|
95
|
+
dir.path
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class FilesController < FileSystemController
|
100
|
+
def readme
|
101
|
+
write_new_file_and_return_path
|
102
|
+
end
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
And the [Router](#router) is set up, `FoldersController#two_readmes` generates a directory of `FilesController#readme`s. Processors add the ability to do these calls:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
# calls the `s3_key` processor
|
110
|
+
Router.call('files/readme.s3_key')
|
111
|
+
# equivalent to:
|
112
|
+
FilesController.call(:readme, {}, { processors: [:s3_key] })
|
113
|
+
|
114
|
+
# calls the `zip` processor then the `s3_key` processor
|
115
|
+
Router.call('folders/two_readmes.s3_key.zip')
|
116
|
+
# equivalent to (NOTE the reverse order to the processor suffixes):
|
117
|
+
FoldersController.call(:two_readmes, {}, { processors: [:zip, :s3_key] })
|
118
|
+
```
|
119
|
+
|
120
|
+
The processors (`zip` and `s3_key`) can be defined and implemented in a common Parent controller, in this case:
|
121
|
+
```ruby
|
122
|
+
class FileSystemController < SimpleController::Base
|
123
|
+
# output => "path_to_file_or_directory"
|
124
|
+
# processors => some combination of [:zip, :s3_key]
|
125
|
+
def post_process(output, processors)
|
126
|
+
processors.each do |processor|
|
127
|
+
case processor
|
128
|
+
when :zip
|
129
|
+
output = zip_directory_and_return_path_of_zip(output)
|
130
|
+
when :s3_key
|
131
|
+
output = upload_file_path_to_amazon_s3_and_return_the_s3_key(output)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
output
|
135
|
+
end
|
136
|
+
end
|
79
137
|
```
|
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'simple_controller/base/core'
|
2
|
+
require 'simple_controller/base/context'
|
2
3
|
require 'simple_controller/base/callbacks'
|
3
4
|
|
4
5
|
module SimpleController
|
5
6
|
class Base
|
6
7
|
include Core
|
7
8
|
include Callbacks # included last to wrap method
|
9
|
+
include Context
|
8
10
|
end
|
9
11
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module SimpleController
|
2
|
+
class Base
|
3
|
+
module Context
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
attr_reader :context
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(action_name, params={}, context={})
|
11
|
+
@context ||= OpenStruct.new context
|
12
|
+
|
13
|
+
super(action_name, params)
|
14
|
+
end
|
15
|
+
|
16
|
+
def call_action(*args)
|
17
|
+
post_process super, context.processors || []
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def post_process(output, processors)
|
23
|
+
output
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -4,12 +4,14 @@ module SimpleController
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
attr_reader :params, :action_name
|
7
|
+
attr_reader :params, :action_name, :controller_path, :controller_name
|
8
8
|
end
|
9
9
|
|
10
10
|
def call(action_name, params={})
|
11
11
|
@params ||= ActiveSupport::HashWithIndifferentAccess.new(params)
|
12
12
|
@action_name ||= action_name.to_s
|
13
|
+
@controller_path ||= params[:controller]
|
14
|
+
@controller_name ||= controller_path.split("/").last if controller_path
|
13
15
|
|
14
16
|
call_action
|
15
17
|
end
|
@@ -1,55 +1,9 @@
|
|
1
|
-
require 'simple_controller/router/
|
1
|
+
require 'simple_controller/router/core'
|
2
|
+
require 'simple_controller/router/context'
|
2
3
|
|
3
4
|
module SimpleController
|
4
5
|
class Router
|
5
|
-
|
6
|
-
|
7
|
-
include ActiveSupport::Callbacks
|
8
|
-
define_callbacks :call
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
@route_mapping = {}
|
12
|
-
end
|
13
|
-
|
14
|
-
def call(route_path, params={})
|
15
|
-
@route_path = route_path.to_s
|
16
|
-
@route = @route_mapping[@route_path]
|
17
|
-
|
18
|
-
raise "#{self.class} route for '#{@route_path}' not found" unless route
|
19
|
-
|
20
|
-
run_callbacks(:call) do
|
21
|
-
@route.call params, controller_name_block
|
22
|
-
end
|
23
|
-
ensure
|
24
|
-
@route_path = nil
|
25
|
-
@route = nil
|
26
|
-
end
|
27
|
-
|
28
|
-
def route_paths
|
29
|
-
route_mapping.keys
|
30
|
-
end
|
31
|
-
|
32
|
-
def draw(&block)
|
33
|
-
mapper = Mapper.new(self)
|
34
|
-
mapper.instance_eval(&block)
|
35
|
-
end
|
36
|
-
|
37
|
-
def add_route(route_path, route)
|
38
|
-
@route_mapping[route_path] = route
|
39
|
-
end
|
40
|
-
|
41
|
-
def parse_controller_name(&block)
|
42
|
-
@controller_name_block = block
|
43
|
-
end
|
44
|
-
|
45
|
-
class << self
|
46
|
-
def instance
|
47
|
-
@instance ||= new
|
48
|
-
end
|
49
|
-
|
50
|
-
def call(*args)
|
51
|
-
instance.call(*args)
|
52
|
-
end
|
53
|
-
end
|
6
|
+
include Core
|
7
|
+
include Context
|
54
8
|
end
|
55
9
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module SimpleController
|
2
|
+
class Router
|
3
|
+
module Context
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
attr_reader :context
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(route_path, params={})
|
11
|
+
route_path = parse_route_path(route_path.to_s)
|
12
|
+
|
13
|
+
super(route_path, params)
|
14
|
+
ensure
|
15
|
+
@context = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def _call(route)
|
21
|
+
route.call params, context, controller_path_block
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse_route_path(route_path)
|
25
|
+
processors = []
|
26
|
+
|
27
|
+
until (extension = File.extname(route_path)).empty?
|
28
|
+
route_path = route_path.chomp(extension)
|
29
|
+
processors << extension[1..-1].to_sym
|
30
|
+
end
|
31
|
+
|
32
|
+
@context = { processors: processors }
|
33
|
+
|
34
|
+
route_path
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'simple_controller/router/route'
|
2
|
+
require 'simple_controller/router/mapper'
|
3
|
+
|
4
|
+
module SimpleController
|
5
|
+
class Router
|
6
|
+
module Core
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
attr_reader :route_mapping, :route_path, :params, :controller_path_block
|
11
|
+
end
|
12
|
+
def initialize
|
13
|
+
@route_mapping = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(route_path, params={})
|
17
|
+
@route_path = route_path.to_s
|
18
|
+
@params = params
|
19
|
+
|
20
|
+
route = @route_mapping[@route_path]
|
21
|
+
raise "#{self.class} route for '#{@route_path}' not found" unless route
|
22
|
+
_call(route)
|
23
|
+
ensure
|
24
|
+
@route_path = @params = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def route_paths
|
28
|
+
route_mapping.keys
|
29
|
+
end
|
30
|
+
|
31
|
+
def draw(&block)
|
32
|
+
mapper = Mapper.new(self)
|
33
|
+
mapper.instance_eval(&block)
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_route(route_path, controller_path, action)
|
38
|
+
@route_mapping[route_path] = Route.new(controller_path, action)
|
39
|
+
end
|
40
|
+
|
41
|
+
def parse_controller_path(&block)
|
42
|
+
@controller_path_block = block
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
def _call(route)
|
47
|
+
route.call params, controller_path_block
|
48
|
+
end
|
49
|
+
|
50
|
+
module ClassMethods
|
51
|
+
def instance
|
52
|
+
@instance ||= new
|
53
|
+
end
|
54
|
+
|
55
|
+
def call(*args)
|
56
|
+
instance.call(*args)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -1,45 +1,41 @@
|
|
1
|
-
require 'simple_controller/router/route'
|
2
|
-
|
3
1
|
module SimpleController
|
4
2
|
class Router
|
5
3
|
class Mapper
|
6
|
-
attr_reader :router, :namespaces, :
|
4
|
+
attr_reader :router, :namespaces, :controller_path
|
7
5
|
|
8
|
-
def initialize(router, namespaces=[],
|
9
|
-
@router, @namespaces, @
|
6
|
+
def initialize(router, namespaces=[], controller_path=nil)
|
7
|
+
@router, @namespaces, @controller_path = router, namespaces, controller_path
|
10
8
|
end
|
11
9
|
|
12
10
|
def namespace(namespace, &block)
|
13
11
|
@namespaces << namespace
|
14
12
|
|
15
|
-
mapper = self.class.new(router, namespaces,
|
13
|
+
mapper = self.class.new(router, namespaces, controller_path)
|
16
14
|
mapper.instance_eval(&block)
|
17
15
|
ensure
|
18
16
|
@namespaces.pop
|
19
17
|
end
|
20
18
|
|
21
|
-
def controller(
|
22
|
-
raise "can't have multiple controller scopes" if self.
|
19
|
+
def controller(controller_path, options={}, &block)
|
20
|
+
raise "can't have multiple controller scopes" if self.controller_path
|
23
21
|
|
24
|
-
mapper = self.class.new(router, namespaces,
|
22
|
+
mapper = self.class.new(router, namespaces, controller_path)
|
25
23
|
Array(options[:actions]).each { |action| mapper.match(action) }
|
26
24
|
|
27
25
|
mapper.instance_eval(&block) if block_given?
|
28
26
|
end
|
29
27
|
|
30
28
|
def match(arg)
|
31
|
-
route_path,
|
29
|
+
route_path, controller_name, action_name = parse_match_arg(arg)
|
32
30
|
|
33
31
|
route_parts = [route_path]
|
34
|
-
route_parts.unshift(self.
|
32
|
+
route_parts.unshift(self.controller_path) if self.controller_path
|
35
33
|
route_parts.unshift(*namespaces)
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
action_name = partition.last
|
35
|
+
controller_path_parts = [self.controller_path || controller_name]
|
36
|
+
controller_path_parts.unshift(*namespaces)
|
41
37
|
|
42
|
-
router.add_route join_parts(route_parts),
|
38
|
+
router.add_route join_parts(route_parts), join_parts(controller_path_parts), action_name
|
43
39
|
end
|
44
40
|
|
45
41
|
protected
|
@@ -54,14 +50,18 @@ module SimpleController
|
|
54
50
|
|
55
51
|
def parse_match_arg(arg)
|
56
52
|
if arg.class == Hash
|
53
|
+
# match "threes/dividing" => "threes#divide"
|
54
|
+
# match subtracting: "subtract"
|
57
55
|
raise "takes only one option" unless arg.size == 1
|
58
56
|
route_path = arg.keys.first.to_s
|
59
|
-
|
57
|
+
controller_name, _, action_name = arg.values.first.to_s.rpartition("#")
|
60
58
|
else
|
59
|
+
# match :threes
|
60
|
+
# match "threes/multiply"
|
61
61
|
route_path = arg.to_s
|
62
|
-
|
62
|
+
controller_name, _, action_name = route_path.rpartition("/")
|
63
63
|
end
|
64
|
-
[route_path,
|
64
|
+
[route_path, controller_name, action_name]
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
@@ -1,19 +1,17 @@
|
|
1
1
|
module SimpleController
|
2
2
|
class Router
|
3
3
|
class Route
|
4
|
-
attr_reader :
|
5
|
-
attr_accessor :controller_name_block
|
4
|
+
attr_reader :controller_path, :action_name
|
6
5
|
|
7
|
-
def initialize(
|
8
|
-
@
|
6
|
+
def initialize(controller_path, action_name)
|
7
|
+
@controller_path, @action_name = controller_path, action_name
|
9
8
|
end
|
10
9
|
|
11
|
-
def
|
12
|
-
|
13
|
-
end
|
10
|
+
def call(params, context, controller_path_block)
|
11
|
+
controller_class = controller_path_block ? controller_path_block.call(controller_path) : "#{controller_path}_controller".classify.constantize
|
14
12
|
|
15
|
-
|
16
|
-
|
13
|
+
params = { 'controller' => controller_path, 'action' => action_name }.reverse_merge(params)
|
14
|
+
controller_class.call action_name, params, context
|
17
15
|
end
|
18
16
|
end
|
19
17
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple_controller
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Chung
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -34,6 +34,7 @@ files:
|
|
34
34
|
- ".gitignore"
|
35
35
|
- ".rspec"
|
36
36
|
- ".travis.yml"
|
37
|
+
- CHANGELOG.md
|
37
38
|
- Gemfile
|
38
39
|
- LICENSE.txt
|
39
40
|
- README.md
|
@@ -43,9 +44,12 @@ files:
|
|
43
44
|
- lib/simple_controller.rb
|
44
45
|
- lib/simple_controller/base.rb
|
45
46
|
- lib/simple_controller/base/callbacks.rb
|
47
|
+
- lib/simple_controller/base/context.rb
|
46
48
|
- lib/simple_controller/base/core.rb
|
47
49
|
- lib/simple_controller/engine.rb
|
48
50
|
- lib/simple_controller/router.rb
|
51
|
+
- lib/simple_controller/router/context.rb
|
52
|
+
- lib/simple_controller/router/core.rb
|
49
53
|
- lib/simple_controller/router/mapper.rb
|
50
54
|
- lib/simple_controller/router/route.rb
|
51
55
|
- lib/simple_controller/version.rb
|
@@ -70,7 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
74
|
version: '0'
|
71
75
|
requirements: []
|
72
76
|
rubyforge_project:
|
73
|
-
rubygems_version: 2.
|
77
|
+
rubygems_version: 2.5.1
|
74
78
|
signing_key:
|
75
79
|
specification_version: 4
|
76
80
|
summary: Rails Controllers, but general purpose.
|