action_handler 0.0.0 → 0.1.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 +4 -4
- data/README.md +7 -11
- data/lib/action_handler/args_maker.rb +36 -6
- data/lib/action_handler/config.rb +0 -8
- data/lib/action_handler/controller.rb +2 -3
- data/lib/action_handler/equip.rb +0 -4
- data/lib/action_handler/installer.rb +28 -9
- data/lib/action_handler/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06a9029c41b4a4ad4284e7e91f59724885da4f47b75b561cb30ed03f76734e19
|
4
|
+
data.tar.gz: ffbd72526d8bf9977a6807da8c10596db7b788d0596f50c558f216cc5af38f06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be995c1aea5765076ec538b25558a67c7105aa212aa9432e3bf1a83cd0b76dd6a94019dd121dcc6b00e130f6e554aa7c0997aab98bd10c52df9635fead2ce409
|
7
|
+
data.tar.gz: fccdd48b45bf653d32a27165945c45c6c174ec8ee872a356b22271ce4946a01f86dc1edcc39257b31426e8c23ce66b69e46d4900fd28e8abd775b59f60633a05
|
data/README.md
CHANGED
@@ -8,9 +8,9 @@ ActionHandler is a Rails plugin that helps you write controller functionalities
|
|
8
8
|
|
9
9
|
A handler is a controller-like class. Each public method can be an action method.
|
10
10
|
But unlike controllers, handlers inherit few methods by default.
|
11
|
-
|
11
|
+
Instead of using super class methods such as `params`, `sessions`, you can take them as arguments.
|
12
12
|
And you need to represent a response (data for views) as a single return value,
|
13
|
-
instead of
|
13
|
+
instead of assigning multiple instance variables.
|
14
14
|
|
15
15
|
```ruby
|
16
16
|
# Example
|
@@ -56,8 +56,7 @@ end
|
|
56
56
|
|
57
57
|
### Clean and clear structure
|
58
58
|
|
59
|
-
- In handlers, action methods take necessary inputs as arguments and
|
60
|
-
return output as a return value.
|
59
|
+
- In handlers, action methods take necessary inputs as arguments and represent output as a return value.
|
61
60
|
So easy to read and test.
|
62
61
|
- Handler is just a class, so you can set up any dependencies via `initialize` method.
|
63
62
|
|
@@ -67,7 +66,7 @@ end
|
|
67
66
|
just by declaring them as action method's arguments.
|
68
67
|
- You can define custom injectable arguments as well.
|
69
68
|
|
70
|
-
|
69
|
+
This feature is heavily inspired by [ActionArgs](https://github.com/asakusarb/action_args).
|
71
70
|
|
72
71
|
## Motivation
|
73
72
|
|
@@ -121,11 +120,8 @@ to use basic controller functionalities like `redirect_to` or custom arguments.
|
|
121
120
|
|
122
121
|
## Guides
|
123
122
|
|
124
|
-
|
123
|
+
- [Detail guides][wiki]
|
124
|
+
- [Example Rails app][example]
|
125
125
|
|
126
126
|
[wiki]: https://github.com/ryym/action_handler/wiki
|
127
|
-
|
128
|
-
TODO:
|
129
|
-
|
130
|
-
- Currently Unsupported controller features
|
131
|
-
- Where should handlers be placed?
|
127
|
+
[example]: https://github.com/ryym/action_handler/tree/master/examples/sample
|
@@ -1,18 +1,48 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionHandler
|
4
|
-
class
|
5
|
-
|
4
|
+
class ActionArgumentError < StandardError
|
5
|
+
def initialize(method, details)
|
6
|
+
super("Arguments of #{method.owner.name}##{method.name} is invalid: #{details}")
|
7
|
+
end
|
8
|
+
end
|
6
9
|
|
7
|
-
|
10
|
+
class ArgsMaker
|
11
|
+
def make_args(method, supplier, context: nil)
|
8
12
|
supplier_args = [context].compact
|
9
|
-
|
13
|
+
|
14
|
+
values = []
|
15
|
+
keywords = {}
|
16
|
+
|
17
|
+
method.parameters.each do |kind, name|
|
10
18
|
unless supplier.respond_to?(name)
|
11
|
-
raise
|
19
|
+
raise ActionHandler::ActionArgumentError.new(
|
20
|
+
method,
|
21
|
+
"parameter #{name} is not defined in #{supplier}",
|
22
|
+
)
|
12
23
|
end
|
13
24
|
|
14
|
-
|
25
|
+
case kind
|
26
|
+
when :req
|
27
|
+
values << supplier.send(name, *supplier_args)
|
28
|
+
when :keyreq
|
29
|
+
keywords[name] = supplier.send(name, *supplier_args)
|
30
|
+
when :opt, :key
|
31
|
+
raise ActionHandler::ActionArgumentError.new(method, <<~ERR)
|
32
|
+
Do not use optional arguments.
|
33
|
+
ActionHandler always injects arguments even if the value is nil,
|
34
|
+
so the optional values never be used.
|
35
|
+
ERR
|
36
|
+
when :rest, :keyrest
|
37
|
+
raise ActionHandler::ActionArgumentError.new(
|
38
|
+
method,
|
39
|
+
'rest arguments cannot be used',
|
40
|
+
)
|
41
|
+
end
|
15
42
|
end
|
43
|
+
|
44
|
+
values << keywords unless keywords.empty?
|
45
|
+
values
|
16
46
|
end
|
17
47
|
end
|
18
48
|
end
|
@@ -14,24 +14,16 @@ module ActionHandler
|
|
14
14
|
handler_class.instance_variable_set(CONFIG_VAR_NAME, config)
|
15
15
|
end
|
16
16
|
|
17
|
-
attr_reader :as_controller
|
18
17
|
attr_reader :action_methods
|
19
18
|
attr_reader :args_suppliers
|
20
19
|
attr_reader :custom_args
|
21
20
|
|
22
21
|
def initialize
|
23
|
-
@as_controller = nil
|
24
22
|
@action_methods = nil
|
25
23
|
@args_suppliers = []
|
26
24
|
@custom_args = {} # { method_name: proc }
|
27
25
|
end
|
28
26
|
|
29
|
-
def as_controller=(block)
|
30
|
-
raise ArgumentError, 'must be proc' unless block.is_a?(Proc)
|
31
|
-
|
32
|
-
@as_controller = block
|
33
|
-
end
|
34
|
-
|
35
27
|
def action_methods=(names)
|
36
28
|
raise ArgumentError, 'must be array' unless names.is_a?(Array)
|
37
29
|
|
@@ -10,9 +10,8 @@ module ActionHandler
|
|
10
10
|
end
|
11
11
|
|
12
12
|
module ControllerExtension
|
13
|
-
def use_handler
|
14
|
-
|
15
|
-
ActionHandler::Installer.new.install(handler, self)
|
13
|
+
def use_handler(&block)
|
14
|
+
ActionHandler::Installer.new.install(self, &block)
|
16
15
|
end
|
17
16
|
end
|
18
17
|
end
|
data/lib/action_handler/equip.rb
CHANGED
@@ -35,10 +35,6 @@ module ActionHandler
|
|
35
35
|
end
|
36
36
|
|
37
37
|
module HandlerExtension
|
38
|
-
def as_controller(&block)
|
39
|
-
ActionHandler::Config.get(self).as_controller = block
|
40
|
-
end
|
41
|
-
|
42
38
|
def action_methods(*method_names)
|
43
39
|
ActionHandler::Config.get(self).action_methods = method_names
|
44
40
|
end
|
@@ -3,6 +3,11 @@
|
|
3
3
|
require 'action_handler/args_maker'
|
4
4
|
require 'action_handler/response_evaluator'
|
5
5
|
|
6
|
+
# TODO: Add `controller_send` (to use controller methods like `send_data`)
|
7
|
+
|
8
|
+
# It is better if there is a way to return streaming response.
|
9
|
+
# (`self.response_body = ` or `response.stream.write`?)
|
10
|
+
|
6
11
|
module ActionHandler
|
7
12
|
class Installer
|
8
13
|
attr_reader :args_maker
|
@@ -16,23 +21,37 @@ module ActionHandler
|
|
16
21
|
@res_evaluator = res_evaluator
|
17
22
|
end
|
18
23
|
|
19
|
-
def install(
|
20
|
-
|
24
|
+
def install(ctrl_class, &block)
|
25
|
+
ctrl_class.instance_variable_set(:@_action_handler_factory, block)
|
26
|
+
|
27
|
+
installer = self
|
28
|
+
initializer = Module.new.tap do |m|
|
29
|
+
m.define_method(:initialize) do |*args|
|
30
|
+
super(*args)
|
31
|
+
factory = self.class.instance_variable_get(:@_action_handler_factory)
|
32
|
+
handler = factory.call(self)
|
33
|
+
installer.send(:setup, self, handler)
|
34
|
+
end
|
35
|
+
end
|
21
36
|
|
22
|
-
ctrl_class.
|
37
|
+
ctrl_class.prepend initializer
|
38
|
+
end
|
39
|
+
|
40
|
+
private def setup(ctrl, handler)
|
41
|
+
config = ActionHandler::Config.get(handler.class) || ActionHandler::Config.new
|
23
42
|
|
24
43
|
actions = action_methods(handler, config)
|
25
44
|
args_supplier = args_supplier(config)
|
26
45
|
|
27
46
|
actions.each do |name|
|
28
47
|
installer = self
|
29
|
-
|
48
|
+
|
49
|
+
# If we use `define_singleton_method`, methods don't work correctly.
|
50
|
+
# I don't know Rails internal details but
|
51
|
+
# Rails requires methods to be defined in a class.
|
52
|
+
ctrl.class.define_method(name) do
|
30
53
|
method = handler.method(name)
|
31
|
-
args = installer.args_maker.make_args(
|
32
|
-
method.parameters,
|
33
|
-
args_supplier,
|
34
|
-
context: self,
|
35
|
-
)
|
54
|
+
args = installer.args_maker.make_args(method, args_supplier, context: self)
|
36
55
|
res = method.call(*args)
|
37
56
|
installer.res_evaluator.evaluate(self, res)
|
38
57
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: action_handler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ryym
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-12-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -85,7 +85,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
85
85
|
requirements:
|
86
86
|
- - ">="
|
87
87
|
- !ruby/object:Gem::Version
|
88
|
-
version: '
|
88
|
+
version: '2.3'
|
89
89
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
90
|
requirements:
|
91
91
|
- - ">="
|