simple_controller 0.1.0 → 0.1.1

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: 20f1e8a4f6f58fa76e1ee3679e43aae283a7fd4e
4
- data.tar.gz: 43d4c9d22826ae45ad8b8dac49e7a3b8b4de47c6
3
+ metadata.gz: 022feec11ef15f421596afc8ab71a0f69dd271ed
4
+ data.tar.gz: e048c155d5ad1b659a0a5dd45eada31a64f46916
5
5
  SHA512:
6
- metadata.gz: a11908aca45ebbfa600a58167c38b1cbbc6d84983bee759f3c0120fcbac25c716e2ce8450d2553edb69321389be53b871802d842148c4e077ec87a7dffd516a6
7
- data.tar.gz: 0af55254de294c9d72731feedb60f05f455982e14839f7943b5a794fe7dd4b607b5c5c39c741dc08a7efd4d10c49fefc6493fcce1ed1d6a55d3d4f5c39c944de
6
+ metadata.gz: 52542cc33f334c554d80e15dbb635993c2562e77b3ea3d7536ddd8ec2be80c28105e5cabd0e9d5774717965cdd78c1d7a4e20168e07d1518d847454336cdbf55
7
+ data.tar.gz: eb967704ba637c82038b0ce0611fe8eecdf07d50320dead670c0123f9c7b4f53f4da0a3b10b71617e4d834350b5cf84207f11facffbf19b31a4a859ffac9acc9
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ /.idea/*
data/README.md CHANGED
@@ -39,4 +39,41 @@ UserController.new.call(:touch, user_id: 1) # => same as above
39
39
  It works like a Rails Controller, but has only has the following features:
40
40
  - Callbacks
41
41
  - `params`
42
- - `action_name`
42
+ - `action_name`
43
+
44
+ ## Router
45
+ A router is provided to decouple controller classes from identifiers.
46
+
47
+ ```ruby
48
+ class Router < SimpleController::Router
49
+ end
50
+
51
+ # Router.instance is a singleton for ease of use
52
+ Router.instance.draw do
53
+ match "threes/multiply"
54
+ match "threes/dividing" => "threes#divide"
55
+
56
+ controller :threes do
57
+ match :add
58
+ match subtracting: "subtract"
59
+ end
60
+ # custom syntax
61
+ controller :threes, actions: %i[power]
62
+
63
+ namespace :some_namespace do
64
+ match :magic
65
+ end
66
+
67
+ # no other Rails-like syntax is available
68
+ end
69
+
70
+ Router.call("threes/multiply", number: 6) # calls ThreesController.call(:multiply, number: 6)
71
+ Router.instance.call("threes/multiply", number: 6) # same as above
72
+ ```
73
+
74
+ To custom namespace the controller:
75
+ ```ruby
76
+ Router.instance.parse_controller_name {|controller_name| "#{controller_name}_suffix_controller".classify.constantize }
77
+
78
+ Router.call("threes/multiply", number: 6) # calls ThreesSuffixController.call(:multiply, number: 6)
79
+ ```
@@ -0,0 +1,190 @@
1
+ # based on: https://github.com/rails/rails/blob/d2876141d08341ec67cf6a11a073d1acfb920de7/actionpack/lib/abstract_controller/callbacks.rb
2
+ module SimpleController
3
+ class Base
4
+ module Callbacks
5
+ extend ActiveSupport::Concern
6
+
7
+ # Uses ActiveSupport::Callbacks as the base functionality. For
8
+ # more details on the whole callback system, read the documentation
9
+ # for ActiveSupport::Callbacks.
10
+ include ActiveSupport::Callbacks
11
+
12
+ included do
13
+ define_callbacks :call_action
14
+ end
15
+
16
+ # Override SimpleController::Base's call to run the
17
+ # call callbacks around the normal behavior.
18
+ def call_action(*args)
19
+ run_callbacks(:call_action) do
20
+ super
21
+ end
22
+ end
23
+
24
+ module ClassMethods
25
+ # If +:only+ or +:except+ are used, convert the options into the
26
+ # +:if+ and +:unless+ options of ActiveSupport::Callbacks.
27
+ #
28
+ # The basic idea is that <tt>:only => :index</tt> gets converted to
29
+ # <tt>:if => proc {|c| c.action_name == "index" }</tt>.
30
+ #
31
+ # Note that <tt>:only</tt> has priority over <tt>:if</tt> in case they
32
+ # are used together.
33
+ #
34
+ # only: :index, if: -> { true } # the :if option will be ignored.
35
+ #
36
+ # Note that <tt>:if</tt> has priority over <tt>:except</tt> in case they
37
+ # are used together.
38
+ #
39
+ # except: :index, if: -> { true } # the :except option will be ignored.
40
+ #
41
+ # ==== Options
42
+ # * <tt>only</tt> - The callback should be run only for this action
43
+ # * <tt>except</tt> - The callback should be run for all actions except this action
44
+ def _normalize_callback_options(options)
45
+ _normalize_callback_option(options, :only, :if)
46
+ _normalize_callback_option(options, :except, :unless)
47
+ end
48
+
49
+ def _normalize_callback_option(options, from, to) # :nodoc:
50
+ if from = options[from]
51
+ from = Array(from).map {|o| "action_name == '#{o}'"}.join(" || ")
52
+ options[to] = Array(options[to]).unshift(from)
53
+ end
54
+ end
55
+
56
+ # Take callback names and an optional callback proc, normalize them,
57
+ # then call the block with each callback. This allows us to abstract
58
+ # the normalization across several methods that use it.
59
+ #
60
+ # ==== Parameters
61
+ # * <tt>callbacks</tt> - An array of callbacks, with an optional
62
+ # options hash as the last parameter.
63
+ # * <tt>block</tt> - A proc that should be added to the callbacks.
64
+ #
65
+ # ==== Block Parameters
66
+ # * <tt>name</tt> - The callback to be added
67
+ # * <tt>options</tt> - A hash of options to be used when adding the callback
68
+ def _insert_callbacks(callbacks, block = nil)
69
+ options = callbacks.extract_options!
70
+ _normalize_callback_options(options)
71
+ callbacks.push(block) if block
72
+ callbacks.each do |callback|
73
+ yield callback, options
74
+ end
75
+ end
76
+
77
+ ##
78
+ # :method: before_action
79
+ #
80
+ # :call-seq: before_action(names, block)
81
+ #
82
+ # Append a callback before actions. See _insert_callbacks for parameter details.
83
+
84
+ ##
85
+ # :method: prepend_before_action
86
+ #
87
+ # :call-seq: prepend_before_action(names, block)
88
+ #
89
+ # Prepend a callback before actions. See _insert_callbacks for parameter details.
90
+
91
+ ##
92
+ # :method: skip_before_action
93
+ #
94
+ # :call-seq: skip_before_action(names)
95
+ #
96
+ # Skip a callback before actions. See _insert_callbacks for parameter details.
97
+
98
+ ##
99
+ # :method: append_before_action
100
+ #
101
+ # :call-seq: append_before_action(names, block)
102
+ #
103
+ # Append a callback before actions. See _insert_callbacks for parameter details.
104
+
105
+ ##
106
+ # :method: after_action
107
+ #
108
+ # :call-seq: after_action(names, block)
109
+ #
110
+ # Append a callback after actions. See _insert_callbacks for parameter details.
111
+
112
+ ##
113
+ # :method: prepend_after_action
114
+ #
115
+ # :call-seq: prepend_after_action(names, block)
116
+ #
117
+ # Prepend a callback after actions. See _insert_callbacks for parameter details.
118
+
119
+ ##
120
+ # :method: skip_after_action
121
+ #
122
+ # :call-seq: skip_after_action(names)
123
+ #
124
+ # Skip a callback after actions. See _insert_callbacks for parameter details.
125
+
126
+ ##
127
+ # :method: append_after_action
128
+ #
129
+ # :call-seq: append_after_action(names, block)
130
+ #
131
+ # Append a callback after actions. See _insert_callbacks for parameter details.
132
+
133
+ ##
134
+ # :method: around_action
135
+ #
136
+ # :call-seq: around_action(names, block)
137
+ #
138
+ # Append a callback around actions. See _insert_callbacks for parameter details.
139
+
140
+ ##
141
+ # :method: prepend_around_action
142
+ #
143
+ # :call-seq: prepend_around_action(names, block)
144
+ #
145
+ # Prepend a callback around actions. See _insert_callbacks for parameter details.
146
+
147
+ ##
148
+ # :method: skip_around_action
149
+ #
150
+ # :call-seq: skip_around_action(names)
151
+ #
152
+ # Skip a callback around actions. See _insert_callbacks for parameter details.
153
+
154
+ ##
155
+ # :method: append_around_action
156
+ #
157
+ # :call-seq: append_around_action(names, block)
158
+ #
159
+ # Append a callback around actions. See _insert_callbacks for parameter details.
160
+
161
+ # set up before_action, prepend_before_action, skip_before_action, etc.
162
+ # for each of before, after, and around.
163
+ [:before, :after, :around].each do |callback|
164
+ define_method "#{callback}_action" do |*names, &blk|
165
+ _insert_callbacks(names, blk) do |name, options|
166
+ set_callback(:call_action, callback, name, options)
167
+ end
168
+ end
169
+
170
+ define_method "prepend_#{callback}_action" do |*names, &blk|
171
+ _insert_callbacks(names, blk) do |name, options|
172
+ set_callback(:call_action, callback, name, options.merge(:prepend => true))
173
+ end
174
+ end
175
+
176
+ # Skip a before, after or around callback. See _insert_callbacks
177
+ # for details on the allowed parameters.
178
+ define_method "skip_#{callback}_action" do |*names|
179
+ _insert_callbacks(names) do |name, options|
180
+ skip_callback(:call_action, callback, name, options)
181
+ end
182
+ end
183
+
184
+ # *_action is the same as append_*_action
185
+ alias_method :"append_#{callback}_action", :"#{callback}_action"
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,30 @@
1
+ module SimpleController
2
+ class Base
3
+ module Core
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ attr_reader :params, :action_name
8
+ end
9
+
10
+ def call(action_name, params={})
11
+ @params ||= ActiveSupport::HashWithIndifferentAccess.new(params)
12
+ @action_name ||= action_name.to_s
13
+
14
+ call_action
15
+ end
16
+
17
+ protected
18
+
19
+ def call_action
20
+ public_send action_name
21
+ end
22
+
23
+ module ClassMethods
24
+ def call(*args)
25
+ new.call *args
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,5 +1,5 @@
1
- require 'simple_controller/core'
2
- require 'simple_controller/callbacks'
1
+ require 'simple_controller/base/core'
2
+ require 'simple_controller/base/callbacks'
3
3
 
4
4
  module SimpleController
5
5
  class Base
@@ -0,0 +1,68 @@
1
+ require 'simple_controller/router/route'
2
+
3
+ module SimpleController
4
+ class Router
5
+ class Mapper
6
+ attr_reader :router, :namespaces, :controller_name
7
+
8
+ def initialize(router, namespaces=[], controller_name=nil)
9
+ @router, @namespaces, @controller_name = router, namespaces, controller_name
10
+ end
11
+
12
+ def namespace(namespace, &block)
13
+ @namespaces << namespace
14
+
15
+ mapper = self.class.new(router, namespaces, controller_name)
16
+ mapper.instance_eval(&block)
17
+ ensure
18
+ @namespaces.pop
19
+ end
20
+
21
+ def controller(controller_name, options={}, &block)
22
+ raise "can't have multiple controller scopes" if self.controller_name
23
+
24
+ mapper = self.class.new(router, namespaces, controller_name)
25
+ Array(options[:actions]).each { |action| mapper.match(action) }
26
+
27
+ mapper.instance_eval(&block) if block_given?
28
+ end
29
+
30
+ def match(arg)
31
+ route_path, partition = parse_match_arg(arg)
32
+
33
+ route_parts = [route_path]
34
+ route_parts.unshift(self.controller_name) if self.controller_name
35
+ route_parts.unshift(*namespaces)
36
+
37
+ controller_name_parts = [self.controller_name || partition.first]
38
+ controller_name_parts.unshift(*namespaces)
39
+
40
+ action_name = partition.last
41
+
42
+ router.add_route join_parts(route_parts), Route.new(join_parts(controller_name_parts), action_name)
43
+ end
44
+
45
+ protected
46
+ def join_parts(parts)
47
+ parts.map do |part|
48
+ s = part.to_s.dup
49
+ s.chomp!("/")
50
+ s.slice!(0) if part[0] == "/"
51
+ s
52
+ end.join("/")
53
+ end
54
+
55
+ def parse_match_arg(arg)
56
+ if arg.class == Hash
57
+ raise "takes only one option" unless arg.size == 1
58
+ route_path = arg.keys.first.to_s
59
+ partition = arg.values.first.to_s.rpartition("#")
60
+ else
61
+ route_path = arg.to_s
62
+ partition = route_path.rpartition("/")
63
+ end
64
+ [route_path, partition]
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,20 @@
1
+ module SimpleController
2
+ class Router
3
+ class Route
4
+ attr_reader :controller_name, :action_name
5
+ attr_accessor :controller_name_block
6
+
7
+ def initialize(controller_name, action_name)
8
+ @controller_name, @action_name = controller_name, action_name
9
+ end
10
+
11
+ def controller(controller_name_block=nil)
12
+ controller_name_block ? controller_name_block.call(controller_name) : "#{controller_name}_controller".classify.constantize
13
+ end
14
+
15
+ def call(params, controller_name_block=nil)
16
+ controller(controller_name_block).call action_name, params
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,55 @@
1
+ require 'simple_controller/router/mapper'
2
+
3
+ module SimpleController
4
+ 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
54
+ end
55
+ end
@@ -1,3 +1,3 @@
1
1
  module SimpleController
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -5,11 +5,13 @@ require "simple_controller/version"
5
5
 
6
6
  require 'active_support/callbacks'
7
7
  require 'active_support/hash_with_indifferent_access'
8
+ require 'active_support/inflector'
8
9
 
9
10
  if autoload && defined?(Rails)
10
11
  require 'simple_controller/engine'
11
12
  else
12
13
  require 'simple_controller/base'
14
+ require 'simple_controller/router'
13
15
  end
14
16
 
15
17
 
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.0
4
+ version: 0.1.1
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-10-07 00:00:00.000000000 Z
11
+ date: 2015-12-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -42,9 +42,12 @@ files:
42
42
  - bin/setup
43
43
  - lib/simple_controller.rb
44
44
  - lib/simple_controller/base.rb
45
- - lib/simple_controller/callbacks.rb
46
- - lib/simple_controller/core.rb
45
+ - lib/simple_controller/base/callbacks.rb
46
+ - lib/simple_controller/base/core.rb
47
47
  - lib/simple_controller/engine.rb
48
+ - lib/simple_controller/router.rb
49
+ - lib/simple_controller/router/mapper.rb
50
+ - lib/simple_controller/router/route.rb
48
51
  - lib/simple_controller/version.rb
49
52
  - simple_controller.gemspec
50
53
  homepage: https://github.com/FinalCAD/simple_controller
@@ -1,188 +0,0 @@
1
- # based on: https://github.com/rails/rails/blob/d2876141d08341ec67cf6a11a073d1acfb920de7/actionpack/lib/abstract_controller/callbacks.rb
2
- module SimpleController
3
- module Callbacks
4
- extend ActiveSupport::Concern
5
-
6
- # Uses ActiveSupport::Callbacks as the base functionality. For
7
- # more details on the whole callback system, read the documentation
8
- # for ActiveSupport::Callbacks.
9
- include ActiveSupport::Callbacks
10
-
11
- included do
12
- define_callbacks :call_action
13
- end
14
-
15
- # Override SimpleController::Base's call to run the
16
- # call callbacks around the normal behavior.
17
- def call_action(*args)
18
- run_callbacks(:call_action) do
19
- super
20
- end
21
- end
22
-
23
- module ClassMethods
24
- # If +:only+ or +:except+ are used, convert the options into the
25
- # +:if+ and +:unless+ options of ActiveSupport::Callbacks.
26
- #
27
- # The basic idea is that <tt>:only => :index</tt> gets converted to
28
- # <tt>:if => proc {|c| c.action_name == "index" }</tt>.
29
- #
30
- # Note that <tt>:only</tt> has priority over <tt>:if</tt> in case they
31
- # are used together.
32
- #
33
- # only: :index, if: -> { true } # the :if option will be ignored.
34
- #
35
- # Note that <tt>:if</tt> has priority over <tt>:except</tt> in case they
36
- # are used together.
37
- #
38
- # except: :index, if: -> { true } # the :except option will be ignored.
39
- #
40
- # ==== Options
41
- # * <tt>only</tt> - The callback should be run only for this action
42
- # * <tt>except</tt> - The callback should be run for all actions except this action
43
- def _normalize_callback_options(options)
44
- _normalize_callback_option(options, :only, :if)
45
- _normalize_callback_option(options, :except, :unless)
46
- end
47
-
48
- def _normalize_callback_option(options, from, to) # :nodoc:
49
- if from = options[from]
50
- from = Array(from).map {|o| "action_name == '#{o}'"}.join(" || ")
51
- options[to] = Array(options[to]).unshift(from)
52
- end
53
- end
54
-
55
- # Take callback names and an optional callback proc, normalize them,
56
- # then call the block with each callback. This allows us to abstract
57
- # the normalization across several methods that use it.
58
- #
59
- # ==== Parameters
60
- # * <tt>callbacks</tt> - An array of callbacks, with an optional
61
- # options hash as the last parameter.
62
- # * <tt>block</tt> - A proc that should be added to the callbacks.
63
- #
64
- # ==== Block Parameters
65
- # * <tt>name</tt> - The callback to be added
66
- # * <tt>options</tt> - A hash of options to be used when adding the callback
67
- def _insert_callbacks(callbacks, block = nil)
68
- options = callbacks.extract_options!
69
- _normalize_callback_options(options)
70
- callbacks.push(block) if block
71
- callbacks.each do |callback|
72
- yield callback, options
73
- end
74
- end
75
-
76
- ##
77
- # :method: before_action
78
- #
79
- # :call-seq: before_action(names, block)
80
- #
81
- # Append a callback before actions. See _insert_callbacks for parameter details.
82
-
83
- ##
84
- # :method: prepend_before_action
85
- #
86
- # :call-seq: prepend_before_action(names, block)
87
- #
88
- # Prepend a callback before actions. See _insert_callbacks for parameter details.
89
-
90
- ##
91
- # :method: skip_before_action
92
- #
93
- # :call-seq: skip_before_action(names)
94
- #
95
- # Skip a callback before actions. See _insert_callbacks for parameter details.
96
-
97
- ##
98
- # :method: append_before_action
99
- #
100
- # :call-seq: append_before_action(names, block)
101
- #
102
- # Append a callback before actions. See _insert_callbacks for parameter details.
103
-
104
- ##
105
- # :method: after_action
106
- #
107
- # :call-seq: after_action(names, block)
108
- #
109
- # Append a callback after actions. See _insert_callbacks for parameter details.
110
-
111
- ##
112
- # :method: prepend_after_action
113
- #
114
- # :call-seq: prepend_after_action(names, block)
115
- #
116
- # Prepend a callback after actions. See _insert_callbacks for parameter details.
117
-
118
- ##
119
- # :method: skip_after_action
120
- #
121
- # :call-seq: skip_after_action(names)
122
- #
123
- # Skip a callback after actions. See _insert_callbacks for parameter details.
124
-
125
- ##
126
- # :method: append_after_action
127
- #
128
- # :call-seq: append_after_action(names, block)
129
- #
130
- # Append a callback after actions. See _insert_callbacks for parameter details.
131
-
132
- ##
133
- # :method: around_action
134
- #
135
- # :call-seq: around_action(names, block)
136
- #
137
- # Append a callback around actions. See _insert_callbacks for parameter details.
138
-
139
- ##
140
- # :method: prepend_around_action
141
- #
142
- # :call-seq: prepend_around_action(names, block)
143
- #
144
- # Prepend a callback around actions. See _insert_callbacks for parameter details.
145
-
146
- ##
147
- # :method: skip_around_action
148
- #
149
- # :call-seq: skip_around_action(names)
150
- #
151
- # Skip a callback around actions. See _insert_callbacks for parameter details.
152
-
153
- ##
154
- # :method: append_around_action
155
- #
156
- # :call-seq: append_around_action(names, block)
157
- #
158
- # Append a callback around actions. See _insert_callbacks for parameter details.
159
-
160
- # set up before_action, prepend_before_action, skip_before_action, etc.
161
- # for each of before, after, and around.
162
- [:before, :after, :around].each do |callback|
163
- define_method "#{callback}_action" do |*names, &blk|
164
- _insert_callbacks(names, blk) do |name, options|
165
- set_callback(:call_action, callback, name, options)
166
- end
167
- end
168
-
169
- define_method "prepend_#{callback}_action" do |*names, &blk|
170
- _insert_callbacks(names, blk) do |name, options|
171
- set_callback(:call_action, callback, name, options.merge(:prepend => true))
172
- end
173
- end
174
-
175
- # Skip a before, after or around callback. See _insert_callbacks
176
- # for details on the allowed parameters.
177
- define_method "skip_#{callback}_action" do |*names|
178
- _insert_callbacks(names) do |name, options|
179
- skip_callback(:call_action, callback, name, options)
180
- end
181
- end
182
-
183
- # *_action is the same as append_*_action
184
- alias_method :"append_#{callback}_action", :"#{callback}_action"
185
- end
186
- end
187
- end
188
- end
@@ -1,28 +0,0 @@
1
- module SimpleController
2
- module Core
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- attr_reader :params, :action_name
7
- end
8
-
9
- def call(action_name, params={})
10
- @params ||= ActiveSupport::HashWithIndifferentAccess.new(params)
11
- @action_name ||= action_name.to_s
12
-
13
- call_action
14
- end
15
-
16
- protected
17
-
18
- def call_action
19
- public_send action_name
20
- end
21
-
22
- module ClassMethods
23
- def call(*args)
24
- new.call *args
25
- end
26
- end
27
- end
28
- end