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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 022feec11ef15f421596afc8ab71a0f69dd271ed
4
- data.tar.gz: e048c155d5ad1b659a0a5dd45eada31a64f46916
3
+ metadata.gz: 524340d2ca7c377417e63196f002bf3d6c26e2ed
4
+ data.tar.gz: 9d7cefb26e4bd4821643eff5979143d5d113820e
5
5
  SHA512:
6
- metadata.gz: 52542cc33f334c554d80e15dbb635993c2562e77b3ea3d7536ddd8ec2be80c28105e5cabd0e9d5774717965cdd78c1d7a4e20168e07d1518d847454336cdbf55
7
- data.tar.gz: eb967704ba637c82038b0ce0611fe8eecdf07d50320dead670c0123f9c7b4f53f4da0a3b10b71617e4d834350b5cf84207f11facffbf19b31a4a859ffac9acc9
6
+ metadata.gz: 6ed3f6ed15a1a6567923ffd324fc15e4b550cba0a23be0455a8a26ad066f65e4396ff42f0eda1183d88068b0664b743ab987ff755eadf0db8db2644eaab60a23
7
+ data.tar.gz: 05e9b2d919c96ca1355fc364c7bcdd3b91dfd85920df263432f7d693070efc01b110e08e7c6cb7dc7945dc16cacdae01664f0690570ffd9d5ebfa2eb34078001
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ # SimpleController Breaking Changes
2
+ ## 1.0.0
3
+ - rename `controller_name` to `controller_path` to match Rails convention
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
- A router is provided to decouple controller classes from identifiers.
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 custom namespace the controller:
73
+ To customize the controller class:
75
74
  ```ruby
76
- Router.instance.parse_controller_name {|controller_name| "#{controller_name}_suffix_controller".classify.constantize }
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/mapper'
1
+ require 'simple_controller/router/core'
2
+ require 'simple_controller/router/context'
2
3
 
3
4
  module SimpleController
4
5
  class Router
5
- attr_reader :route_mapping, :route, :route_path, :controller_name_block
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, :controller_name
4
+ attr_reader :router, :namespaces, :controller_path
7
5
 
8
- def initialize(router, namespaces=[], controller_name=nil)
9
- @router, @namespaces, @controller_name = router, namespaces, controller_name
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, controller_name)
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(controller_name, options={}, &block)
22
- raise "can't have multiple controller scopes" if self.controller_name
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, controller_name)
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, partition = parse_match_arg(arg)
29
+ route_path, controller_name, action_name = parse_match_arg(arg)
32
30
 
33
31
  route_parts = [route_path]
34
- route_parts.unshift(self.controller_name) if self.controller_name
32
+ route_parts.unshift(self.controller_path) if self.controller_path
35
33
  route_parts.unshift(*namespaces)
36
34
 
37
- controller_name_parts = [self.controller_name || partition.first]
38
- controller_name_parts.unshift(*namespaces)
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), Route.new(join_parts(controller_name_parts), action_name)
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
- partition = arg.values.first.to_s.rpartition("#")
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
- partition = route_path.rpartition("/")
62
+ controller_name, _, action_name = route_path.rpartition("/")
63
63
  end
64
- [route_path, partition]
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 :controller_name, :action_name
5
- attr_accessor :controller_name_block
4
+ attr_reader :controller_path, :action_name
6
5
 
7
- def initialize(controller_name, action_name)
8
- @controller_name, @action_name = controller_name, action_name
6
+ def initialize(controller_path, action_name)
7
+ @controller_path, @action_name = controller_path, action_name
9
8
  end
10
9
 
11
- def controller(controller_name_block=nil)
12
- controller_name_block ? controller_name_block.call(controller_name) : "#{controller_name}_controller".classify.constantize
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
- def call(params, controller_name_block=nil)
16
- controller(controller_name_block).call action_name, params
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
@@ -1,3 +1,3 @@
1
1
  module SimpleController
2
- VERSION = "0.1.1"
2
+ VERSION = "1.0.0"
3
3
  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.1.1
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: 2015-12-15 00:00:00.000000000 Z
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.4.5.1
77
+ rubygems_version: 2.5.1
74
78
  signing_key:
75
79
  specification_version: 4
76
80
  summary: Rails Controllers, but general purpose.