simple_resource_controller 0.1.5 → 0.2.2
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 +35 -0
- data/lib/simple_resource_controller/configurator.rb +1 -1
- data/lib/simple_resource_controller/controller/actions.rb +56 -0
- data/lib/simple_resource_controller/controller/config.rb +37 -0
- data/lib/simple_resource_controller/controller/implementation/format/api.rb +47 -0
- data/lib/simple_resource_controller/controller/implementation/format/html.rb +63 -0
- data/lib/simple_resource_controller/controller/implementation.rb +160 -0
- data/lib/simple_resource_controller/controller.rb +30 -285
- data/lib/simple_resource_controller/version.rb +1 -1
- data/simple_resource_controller.gemspec +7 -5
- metadata +52 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8362241a63c88604c893743e4dddc6e87ef4f51c036ac2f3d597af0a1857099d
|
|
4
|
+
data.tar.gz: 0f439681b0637be16b0f1194bf4545cc93b3cf10bdd8044502ff69470c967b7b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a20db372c476b423a58774cbb55fb0bb0b6ee518cc9bec64c94f4e405ba0f4a7617953971f4d3e7d1bacb40e8524ce3dd5c61fffea8ba05cf137d9b8fc284007
|
|
7
|
+
data.tar.gz: a93645e48f00c63fd7282dc7b8139532d7659197c7826e507e6b98bfc8202e20aa89dcecca5f03cad98cd1686a63bb091153d606a362a844fbd92b8180c440cc
|
data/README.md
CHANGED
|
@@ -63,6 +63,36 @@ class AnotherArticlesController < ApplicationController
|
|
|
63
63
|
end
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
### API examples
|
|
67
|
+
|
|
68
|
+
Gem suppports [jbuilder](https://github.com/rails/jbuilder) and [activemodel_serializer](https://github.com/rails-api/active_model_serializers) as API serializers
|
|
69
|
+
|
|
70
|
+
#### JBuilder
|
|
71
|
+
|
|
72
|
+
```ruby
|
|
73
|
+
resource_api jbuilder: true
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
But you will also need to add all view files for your actions, including `new` and `edit`.
|
|
77
|
+
|
|
78
|
+
**You can find example inside tests.**
|
|
79
|
+
|
|
80
|
+
#### ActiveModel::Serializer
|
|
81
|
+
|
|
82
|
+
Minimum config:
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
resource_api activemodel_serializer: { }
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
All options:
|
|
89
|
+
|
|
90
|
+
```ruby
|
|
91
|
+
resource_api activemodel_serializer: { record_serializer: MyArticleSerializer, error_serializer: MyErrorSerializer }
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**You can find example inside tests.**
|
|
95
|
+
|
|
66
96
|
### Controller configuration
|
|
67
97
|
|
|
68
98
|
The first required configuration is an action name.
|
|
@@ -394,6 +424,11 @@ This is my favorite one. The `responders` gem follows the next logic - if a reco
|
|
|
394
424
|
If you will get this exception - check your ActiveRecord callbacks, your code has some smells.
|
|
395
425
|
|
|
396
426
|
|
|
427
|
+
#### `error_serializer should be configured for the activemodel API`
|
|
428
|
+
|
|
429
|
+
You are trying to use the `resource_api` DSL to setup the activemodel_serializer, faced with the validation error in create or update action.
|
|
430
|
+
But didn't configured an error serializer: `resource_api activemodel_serializer: { error_serializer: MyErrorSerializer }`
|
|
431
|
+
|
|
397
432
|
## Contributing
|
|
398
433
|
|
|
399
434
|
Bug reports and pull requests are welcome on GitHub at https://github.com/c3gdlk/simple_resource_controller. This project is intended to be a safe, welcoming space for collaboration.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module SimpleResourceController
|
|
2
|
+
module Controller
|
|
3
|
+
module Actions
|
|
4
|
+
module Index
|
|
5
|
+
def index(options={}, &block)
|
|
6
|
+
respond_with collection, options, &block
|
|
7
|
+
end
|
|
8
|
+
alias :index! :index
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module Show
|
|
12
|
+
def show(options={}, &block)
|
|
13
|
+
respond_with resource, options, &block
|
|
14
|
+
end
|
|
15
|
+
alias :show! :show
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module New
|
|
19
|
+
def new(options={}, &block)
|
|
20
|
+
build_resource
|
|
21
|
+
respond_with resource, options, &block
|
|
22
|
+
end
|
|
23
|
+
alias :new! :new
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
module Create
|
|
27
|
+
def create(options={}, &block)
|
|
28
|
+
build_resource
|
|
29
|
+
save_resource_and_respond!(options, &block)
|
|
30
|
+
end
|
|
31
|
+
alias :create! :create
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
module Edit
|
|
35
|
+
def edit(options={}, &block)
|
|
36
|
+
respond_with resource, options, &block
|
|
37
|
+
end
|
|
38
|
+
alias :edit! :edit
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
module Update
|
|
42
|
+
def update(options={}, &block)
|
|
43
|
+
save_resource_and_respond!(options, &block)
|
|
44
|
+
end
|
|
45
|
+
alias :update! :update
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
module Destroy
|
|
49
|
+
def destroy(options={}, &block)
|
|
50
|
+
destroy_resource_and_respond!(options, &block)
|
|
51
|
+
end
|
|
52
|
+
alias :destroy! :destroy
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module SimpleResourceController
|
|
2
|
+
module Controller
|
|
3
|
+
module Config
|
|
4
|
+
def resource_class_config
|
|
5
|
+
@resource_class_config
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def resource_class(value)
|
|
9
|
+
@resource_class_config = value
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def resource_context_config
|
|
13
|
+
@resource_context_config
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def resource_context(*values)
|
|
17
|
+
@resource_context_config = values
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def paginate_collection_config
|
|
21
|
+
@paginate_collection_config
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def paginate_collection(value)
|
|
25
|
+
@paginate_collection_config = value
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def api_config
|
|
29
|
+
@api_config
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def resource_api(value)
|
|
33
|
+
@api_config = value
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module SimpleResourceController
|
|
2
|
+
module Controller
|
|
3
|
+
module Implementation
|
|
4
|
+
module Format
|
|
5
|
+
module Api
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def api_before_save_success_response_callback(options)
|
|
9
|
+
options[:status] ||= :created if action_name == "create"
|
|
10
|
+
|
|
11
|
+
if activemodel_serializer?
|
|
12
|
+
record_serializer = self.class.api_config.dig(:activemodel_serializer, :record_serializer)
|
|
13
|
+
options[:json] ||= resource
|
|
14
|
+
options[:serializer] ||= record_serializer
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def api_before_save_failure_response_callback(options)
|
|
19
|
+
if activemodel_serializer?
|
|
20
|
+
error_serializer = self.class.api_config.dig(:activemodel_serializer, :error_serializer)
|
|
21
|
+
|
|
22
|
+
raise "error_serializer should be configured for the activemodel API" unless error_serializer.present?
|
|
23
|
+
options[:json] ||= resource
|
|
24
|
+
options[:serializer] = error_serializer
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def api_before_destroy_response_callback(options)
|
|
29
|
+
if activemodel_serializer?
|
|
30
|
+
record_serializer = self.class.api_config.dig(:activemodel_serializer, :record_serializer)
|
|
31
|
+
options[:json] ||= resource
|
|
32
|
+
options[:serializer] ||= record_serializer
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def current_controller_api?
|
|
37
|
+
self.class.api_config.present?
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def activemodel_serializer?
|
|
41
|
+
current_controller_api? && self.class.api_config.dig(:activemodel_serializer).present?
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module SimpleResourceController
|
|
2
|
+
module Controller
|
|
3
|
+
module Implementation
|
|
4
|
+
module Format
|
|
5
|
+
module Html
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def html_before_save_success_response_callback(options)
|
|
9
|
+
options[:location] ||= after_save_redirect_path
|
|
10
|
+
setup_flash_messages(after_create_messages) if action_name == "create"
|
|
11
|
+
setup_flash_messages(after_update_messages) if action_name == "update"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def api_before_save_failure_response_callback(options)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def html_before_destroy_response_callback(options)
|
|
18
|
+
options[:location] ||= after_destroy_redirect_path
|
|
19
|
+
setup_flash_messages(after_destroy_messages)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# :nocov:
|
|
23
|
+
def after_save_redirect_path
|
|
24
|
+
raise NotImplementedError, "Need to implement the after_save_redirect_path method"
|
|
25
|
+
end
|
|
26
|
+
# :nocov:
|
|
27
|
+
|
|
28
|
+
# :nocov:
|
|
29
|
+
def after_destroy_redirect_path
|
|
30
|
+
raise NotImplementedError, "Need to implement the after_destroy_redirect_path method"
|
|
31
|
+
end
|
|
32
|
+
# :nocov:
|
|
33
|
+
|
|
34
|
+
def after_create_messages
|
|
35
|
+
after_save_messages
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def after_update_messages
|
|
39
|
+
after_save_messages
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def after_destroy_messages
|
|
43
|
+
nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def after_save_messages
|
|
47
|
+
nil
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def setup_flash_messages(messages)
|
|
51
|
+
return unless messages.present?
|
|
52
|
+
|
|
53
|
+
raise 'Messages should be specified with Hash' unless messages.is_a?(Hash)
|
|
54
|
+
|
|
55
|
+
messages.each do |key, message|
|
|
56
|
+
flash[key] = message
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
require_relative './implementation/format/api'
|
|
2
|
+
require_relative './implementation/format/html'
|
|
3
|
+
|
|
4
|
+
module SimpleResourceController
|
|
5
|
+
module Controller
|
|
6
|
+
module Implementation
|
|
7
|
+
include Format::Api
|
|
8
|
+
include Format::Html
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def collection
|
|
13
|
+
return instance_variable_get(:"@#{collection_name}") if instance_variable_get(:"@#{collection_name}").present?
|
|
14
|
+
instance_variable_set(:"@#{collection_name}", apply_scopes_and_pagination(association_chain))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def apply_scopes_and_pagination(chain)
|
|
18
|
+
if respond_to?(:apply_scopes, true)
|
|
19
|
+
chain = apply_scopes(chain)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
per_page = self.class.paginate_collection_config
|
|
23
|
+
|
|
24
|
+
if per_page.present?
|
|
25
|
+
raise 'Please install Kaminari' unless defined?(::Kaminari)
|
|
26
|
+
|
|
27
|
+
chain = chain.page(params[:page]).per(params[:per_page] || per_page)
|
|
28
|
+
else
|
|
29
|
+
chain = chain.all
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
chain
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def collection_name
|
|
36
|
+
resource_name.pluralize
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def resource_class_name
|
|
40
|
+
self.class.resource_class_config || self.class.name.split('::').last.gsub('Controller', '').singularize
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def resource_class
|
|
44
|
+
resource_class_name.constantize
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def resource_name
|
|
48
|
+
resource_class_name.split('::').last.underscore
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def resource_relation_name
|
|
52
|
+
resource_class_name.underscore.pluralize
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def association_chain
|
|
56
|
+
self.class.resource_context_config.present? ? association_chain_by_context : resource_class
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def association_chain_by_context
|
|
60
|
+
specified_scopes.reduce(default_context) do |context, scope|
|
|
61
|
+
raise "#{context.inspect} hasn't relation #{scope}" unless context.respond_to? scope
|
|
62
|
+
|
|
63
|
+
context.public_send(scope)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def default_context
|
|
68
|
+
context_method = self.class.resource_context_config.first
|
|
69
|
+
|
|
70
|
+
if self.respond_to? context_method, true
|
|
71
|
+
context = send(context_method)
|
|
72
|
+
elsif params["#{context_method}_id"].present?
|
|
73
|
+
class_name = context_method.to_s.classify
|
|
74
|
+
context_class = class_name.safe_constantize
|
|
75
|
+
|
|
76
|
+
if context_class.present?
|
|
77
|
+
context = context_class.find(params["#{context_method}_id"])
|
|
78
|
+
else
|
|
79
|
+
raise "Could not find model #{class_name} by param #{context_method}_id"
|
|
80
|
+
end
|
|
81
|
+
else
|
|
82
|
+
raise "Undefined context method #{context_method}"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def specified_scopes
|
|
89
|
+
if self.class.resource_context_config.size > 1
|
|
90
|
+
self.class.resource_context_config[1..-1]
|
|
91
|
+
else
|
|
92
|
+
[resource_relation_name.to_sym]
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def build_resource
|
|
97
|
+
return instance_variable_get(:"@#{resource_name}") if instance_variable_get(:"@#{resource_name}").present?
|
|
98
|
+
|
|
99
|
+
new_instance = association_chain.is_a?(ActiveRecord::Relation) ? association_chain.build : association_chain.new
|
|
100
|
+
instance_variable_set(:"@#{resource_name}", new_instance)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def resource
|
|
104
|
+
return instance_variable_get(:"@#{resource_name}") if instance_variable_get(:"@#{resource_name}").present?
|
|
105
|
+
instance_variable_set(:"@#{resource_name}", association_chain.find(params[:id]))
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def destroy_resource_and_respond!(options={}, &block)
|
|
109
|
+
resource.destroy
|
|
110
|
+
|
|
111
|
+
unless block_given?
|
|
112
|
+
if current_controller_api?
|
|
113
|
+
api_before_destroy_response_callback(options)
|
|
114
|
+
else
|
|
115
|
+
html_before_destroy_response_callback(options)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
respond_with resource, options, &block
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def save_resource_and_respond!(options={}, &block)
|
|
123
|
+
success = resource.update(permitted_params)
|
|
124
|
+
|
|
125
|
+
# process not saved result because of failed callback or another ActiveRecord magic
|
|
126
|
+
if resource.valid? && !success
|
|
127
|
+
resource.errors[:base] << resource_wasnt_saved_message
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
unless block_given?
|
|
131
|
+
if success
|
|
132
|
+
if current_controller_api?
|
|
133
|
+
api_before_save_success_response_callback(options)
|
|
134
|
+
else
|
|
135
|
+
html_before_save_success_response_callback(options)
|
|
136
|
+
end
|
|
137
|
+
else
|
|
138
|
+
if current_controller_api?
|
|
139
|
+
api_before_save_failure_response_callback(options)
|
|
140
|
+
else
|
|
141
|
+
api_before_save_failure_response_callback(options)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
respond_with resource, options, &block
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def resource_wasnt_saved_message
|
|
150
|
+
raise 'Too many Rails magic. Please check your code'
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# :nocov:
|
|
154
|
+
def permitted_params
|
|
155
|
+
raise NotImplementedError, "Need to implement the permitted_params method"
|
|
156
|
+
end
|
|
157
|
+
# :nocov:
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
@@ -1,303 +1,48 @@
|
|
|
1
|
+
require_relative './controller/actions'
|
|
2
|
+
require_relative './controller/config'
|
|
3
|
+
require_relative './controller/implementation'
|
|
4
|
+
|
|
1
5
|
module SimpleResourceController
|
|
2
6
|
module Controller
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
respond_with resource, options, &block
|
|
13
|
-
end
|
|
14
|
-
alias :show! :show
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
module New
|
|
18
|
-
def new(options={}, &block)
|
|
19
|
-
build_resource
|
|
20
|
-
respond_with resource, options, &block
|
|
21
|
-
end
|
|
22
|
-
alias :new! :new
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
module Create
|
|
26
|
-
def create(options={}, &block)
|
|
27
|
-
build_resource
|
|
28
|
-
success = save_resource_and_respond!(options, &block)
|
|
29
|
-
ensure
|
|
30
|
-
setup_flash_messages(after_create_messages) if success
|
|
31
|
-
end
|
|
32
|
-
alias :create! :create
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
module Edit
|
|
36
|
-
def edit(options={}, &block)
|
|
37
|
-
respond_with resource, options, &block
|
|
38
|
-
end
|
|
39
|
-
alias :edit! :edit
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
module Update
|
|
43
|
-
def update(options={}, &block)
|
|
44
|
-
success = save_resource_and_respond!(options, &block)
|
|
45
|
-
ensure
|
|
46
|
-
setup_flash_messages(after_update_messages) if success
|
|
47
|
-
end
|
|
48
|
-
alias :update! :update
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
module Destroy
|
|
52
|
-
def destroy(options={}, &block)
|
|
53
|
-
destroy_resource_and_respond!(options, &block)
|
|
54
|
-
ensure
|
|
55
|
-
setup_flash_messages(after_destroy_messages)
|
|
56
|
-
end
|
|
57
|
-
alias :destroy! :destroy
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
module CommonMethods
|
|
61
|
-
private
|
|
62
|
-
|
|
63
|
-
def collection
|
|
64
|
-
return instance_variable_get(:"@#{collection_name}") if instance_variable_get(:"@#{collection_name}").present?
|
|
65
|
-
instance_variable_set(:"@#{collection_name}", apply_scopes_and_pagination(association_chain))
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def apply_scopes_and_pagination(chain)
|
|
69
|
-
if respond_to?(:apply_scopes, true)
|
|
70
|
-
chain = apply_scopes(chain)
|
|
71
|
-
end
|
|
7
|
+
DEPENDENCIES_MAP = {
|
|
8
|
+
index: Actions::Index,
|
|
9
|
+
show: Actions::Show,
|
|
10
|
+
new: Actions::New,
|
|
11
|
+
create: Actions::Create,
|
|
12
|
+
edit: Actions::Edit,
|
|
13
|
+
update: Actions::Update,
|
|
14
|
+
destroy: Actions::Destroy
|
|
15
|
+
}.freeze
|
|
72
16
|
|
|
73
|
-
|
|
17
|
+
HELPER_METHODS = [:resource, :collection].freeze
|
|
74
18
|
|
|
75
|
-
|
|
76
|
-
raise 'Please install Kaminari' unless defined?(Kaminari)
|
|
19
|
+
ALL_ACTIONS_ALIAS = :crud
|
|
77
20
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
chain
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def collection_name
|
|
87
|
-
resource_name.pluralize
|
|
21
|
+
def self.build(controller_class, actions)
|
|
22
|
+
unless actions.include?(ALL_ACTIONS_ALIAS)
|
|
23
|
+
raise 'Unknown action name' unless (actions - DEPENDENCIES_MAP.keys).size.zero?
|
|
88
24
|
end
|
|
89
25
|
|
|
90
|
-
|
|
91
|
-
self.class.resource_class_config || self.class.name.split('::').last.gsub('Controller', '').singularize
|
|
92
|
-
end
|
|
26
|
+
controller_class.extend Config
|
|
93
27
|
|
|
94
|
-
|
|
95
|
-
resource_class_name.constantize
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def resource_name
|
|
99
|
-
resource_class_name.split('::').last.underscore
|
|
100
|
-
end
|
|
28
|
+
loaded_modules = [Implementation]
|
|
101
29
|
|
|
102
|
-
|
|
103
|
-
|
|
30
|
+
if actions.include?(ALL_ACTIONS_ALIAS)
|
|
31
|
+
loaded_modules += DEPENDENCIES_MAP.values
|
|
32
|
+
else
|
|
33
|
+
loaded_modules += actions.map { |action_name| DEPENDENCIES_MAP[action_name] }
|
|
104
34
|
end
|
|
105
35
|
|
|
106
|
-
|
|
107
|
-
|
|
36
|
+
loaded_modules.uniq.each do |loaded_module|
|
|
37
|
+
controller_class.include loaded_module
|
|
108
38
|
end
|
|
109
39
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
raise "#{context.inspect} hasn't relation #{scope}" unless context.respond_to? scope
|
|
113
|
-
|
|
114
|
-
context.public_send(scope)
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def default_context
|
|
119
|
-
context_method = self.class.resource_context_config.first
|
|
120
|
-
|
|
121
|
-
if self.respond_to? context_method, true
|
|
122
|
-
context = send(context_method)
|
|
123
|
-
elsif params["#{context_method}_id"].present?
|
|
124
|
-
class_name = context_method.to_s.classify
|
|
125
|
-
context_class = class_name.safe_constantize
|
|
126
|
-
|
|
127
|
-
if context_class.present?
|
|
128
|
-
context = context_class.find(params["#{context_method}_id"])
|
|
129
|
-
else
|
|
130
|
-
raise "Could not find model #{class_name} by param #{context_method}_id"
|
|
131
|
-
end
|
|
132
|
-
else
|
|
133
|
-
raise "Undefined context method #{context_method}"
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
context
|
|
40
|
+
HELPER_METHODS.each do |method_name|
|
|
41
|
+
controller_class.helper_method method_name
|
|
137
42
|
end
|
|
138
43
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
self.class.resource_context_config[1..-1]
|
|
142
|
-
else
|
|
143
|
-
[resource_relation_name.to_sym]
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def build_resource
|
|
148
|
-
return instance_variable_get(:"@#{resource_name}") if instance_variable_get(:"@#{resource_name}").present?
|
|
149
|
-
|
|
150
|
-
new_instance = association_chain.is_a?(ActiveRecord::Relation) ? association_chain.build : association_chain.new
|
|
151
|
-
instance_variable_set(:"@#{resource_name}", new_instance)
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
def resource
|
|
155
|
-
return instance_variable_get(:"@#{resource_name}") if instance_variable_get(:"@#{resource_name}").present?
|
|
156
|
-
instance_variable_set(:"@#{resource_name}", association_chain.find(params[:id]))
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
def destroy_resource_and_respond!(options={}, &block)
|
|
160
|
-
resource.destroy
|
|
161
|
-
|
|
162
|
-
unless block_given? || options[:location].present?
|
|
163
|
-
options[:location] = after_destroy_redirect_path
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
respond_with resource, options, &block
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
def save_resource_and_respond!(options={}, &block)
|
|
170
|
-
result = resource.update(permitted_params)
|
|
171
|
-
|
|
172
|
-
# process not saved result because of failed callback or another ActiveRecord magic
|
|
173
|
-
if resource.valid? && !result.present?
|
|
174
|
-
resource.errors[:base] << resource_wasnt_saved_message
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
unless block_given? || options[:location].present?
|
|
178
|
-
options[:location] = after_save_redirect_path
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
respond_with resource, options, &block
|
|
182
|
-
|
|
183
|
-
result
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
def resource_wasnt_saved_message
|
|
187
|
-
raise 'Too many Rails magic. Please check your code'
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
def after_create_messages
|
|
191
|
-
after_save_messages
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
def after_update_messages
|
|
195
|
-
after_save_messages
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
def after_destroy_messages
|
|
199
|
-
nil
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
def after_save_messages
|
|
203
|
-
nil
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
def setup_flash_messages(messages)
|
|
207
|
-
return unless messages.present?
|
|
208
|
-
|
|
209
|
-
raise 'Messages should be specified with Hash' unless messages.is_a?(Hash)
|
|
210
|
-
|
|
211
|
-
messages.each do |key, message|
|
|
212
|
-
flash[key] = message
|
|
213
|
-
end
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
# :nocov:
|
|
217
|
-
def after_save_redirect_path
|
|
218
|
-
raise 'Not Implemented'
|
|
219
|
-
end
|
|
220
|
-
# :nocov:
|
|
221
|
-
|
|
222
|
-
# :nocov:
|
|
223
|
-
def after_destroy_redirect_path
|
|
224
|
-
raise 'Not Implemented'
|
|
225
|
-
end
|
|
226
|
-
# :nocov:
|
|
227
|
-
|
|
228
|
-
# :nocov:
|
|
229
|
-
def permitted_params
|
|
230
|
-
raise 'Not Implemented'
|
|
231
|
-
end
|
|
232
|
-
# :nocov:
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
module Accessors
|
|
236
|
-
def resource_class_config
|
|
237
|
-
@resource_class_config
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
def resource_class(value)
|
|
241
|
-
@resource_class_config = value
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
def resource_context_config
|
|
245
|
-
@resource_context_config
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
def resource_context(*values)
|
|
249
|
-
@resource_context_config = values
|
|
250
|
-
end
|
|
251
|
-
|
|
252
|
-
def paginate_collection_config
|
|
253
|
-
@paginate_collection_config
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
def paginate_collection(value)
|
|
257
|
-
@paginate_collection_config = value
|
|
258
|
-
end
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
class ActionsBuilder
|
|
262
|
-
DEPENDENCIES_MAP = {
|
|
263
|
-
index: Index,
|
|
264
|
-
show: Show,
|
|
265
|
-
new: New,
|
|
266
|
-
create: Create,
|
|
267
|
-
edit: Edit,
|
|
268
|
-
update: Update,
|
|
269
|
-
destroy: Destroy
|
|
270
|
-
}.freeze
|
|
271
|
-
|
|
272
|
-
HELPER_METHODS = [:resource, :collection].freeze
|
|
273
|
-
|
|
274
|
-
ALL_ACTIONS_ALIAS = :crud
|
|
275
|
-
|
|
276
|
-
def self.build(controller_class, actions)
|
|
277
|
-
unless actions.include?(ALL_ACTIONS_ALIAS)
|
|
278
|
-
raise 'Unknown action name' unless (actions - DEPENDENCIES_MAP.keys).size.zero?
|
|
279
|
-
end
|
|
280
|
-
|
|
281
|
-
controller_class.extend Accessors
|
|
282
|
-
|
|
283
|
-
loaded_modules = [CommonMethods]
|
|
284
|
-
|
|
285
|
-
if actions.include?(ALL_ACTIONS_ALIAS)
|
|
286
|
-
loaded_modules += DEPENDENCIES_MAP.values
|
|
287
|
-
else
|
|
288
|
-
loaded_modules += actions.map { |action_name| DEPENDENCIES_MAP[action_name] }
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
loaded_modules.uniq.each do |loaded_module|
|
|
292
|
-
controller_class.include loaded_module
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
HELPER_METHODS.each do |method_name|
|
|
296
|
-
controller_class.helper_method method_name
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
controller_class.respond_to :html
|
|
300
|
-
end
|
|
44
|
+
controller_class.respond_to :html
|
|
45
|
+
controller_class.respond_to :json
|
|
301
46
|
end
|
|
302
47
|
end
|
|
303
48
|
end
|
|
@@ -19,11 +19,13 @@ Gem::Specification.new do |spec|
|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
20
20
|
spec.require_paths = ["lib"]
|
|
21
21
|
|
|
22
|
-
spec.add_development_dependency "bundler"
|
|
23
|
-
spec.add_development_dependency "rake"
|
|
22
|
+
spec.add_development_dependency "bundler"
|
|
23
|
+
spec.add_development_dependency "rake"
|
|
24
24
|
spec.add_development_dependency "rspec", "~> 3.0"
|
|
25
|
+
spec.add_development_dependency "jbuilder"
|
|
26
|
+
spec.add_development_dependency 'active_model_serializers', '~> 0.10.0'
|
|
25
27
|
|
|
26
|
-
spec.add_dependency "railties"
|
|
27
|
-
spec.add_dependency "actionpack"
|
|
28
|
-
spec.add_dependency "responders"
|
|
28
|
+
spec.add_dependency "railties"
|
|
29
|
+
spec.add_dependency "actionpack"
|
|
30
|
+
spec.add_dependency "responders"
|
|
29
31
|
end
|
metadata
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: simple_resource_controller
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Oleg Zaporozhchenko
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-01-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '0'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - "
|
|
24
|
+
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rake
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - "
|
|
31
|
+
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
33
|
+
version: '0'
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- - "
|
|
38
|
+
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
40
|
+
version: '0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: rspec
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -52,48 +52,76 @@ dependencies:
|
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '3.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: jbuilder
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: active_model_serializers
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 0.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: 0.10.0
|
|
55
83
|
- !ruby/object:Gem::Dependency
|
|
56
84
|
name: railties
|
|
57
85
|
requirement: !ruby/object:Gem::Requirement
|
|
58
86
|
requirements:
|
|
59
87
|
- - ">="
|
|
60
88
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '
|
|
89
|
+
version: '0'
|
|
62
90
|
type: :runtime
|
|
63
91
|
prerelease: false
|
|
64
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
93
|
requirements:
|
|
66
94
|
- - ">="
|
|
67
95
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '
|
|
96
|
+
version: '0'
|
|
69
97
|
- !ruby/object:Gem::Dependency
|
|
70
98
|
name: actionpack
|
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
|
72
100
|
requirements:
|
|
73
101
|
- - ">="
|
|
74
102
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '
|
|
103
|
+
version: '0'
|
|
76
104
|
type: :runtime
|
|
77
105
|
prerelease: false
|
|
78
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
107
|
requirements:
|
|
80
108
|
- - ">="
|
|
81
109
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '
|
|
110
|
+
version: '0'
|
|
83
111
|
- !ruby/object:Gem::Dependency
|
|
84
112
|
name: responders
|
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
|
86
114
|
requirements:
|
|
87
|
-
- -
|
|
115
|
+
- - ">="
|
|
88
116
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '
|
|
117
|
+
version: '0'
|
|
90
118
|
type: :runtime
|
|
91
119
|
prerelease: false
|
|
92
120
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
121
|
requirements:
|
|
94
|
-
- -
|
|
122
|
+
- - ">="
|
|
95
123
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '
|
|
124
|
+
version: '0'
|
|
97
125
|
description: This gem allows to write explicit resource controllers
|
|
98
126
|
email:
|
|
99
127
|
- c3.gdlk@gmail.com
|
|
@@ -114,6 +142,11 @@ files:
|
|
|
114
142
|
- lib/simple_resource_controller.rb
|
|
115
143
|
- lib/simple_resource_controller/configurator.rb
|
|
116
144
|
- lib/simple_resource_controller/controller.rb
|
|
145
|
+
- lib/simple_resource_controller/controller/actions.rb
|
|
146
|
+
- lib/simple_resource_controller/controller/config.rb
|
|
147
|
+
- lib/simple_resource_controller/controller/implementation.rb
|
|
148
|
+
- lib/simple_resource_controller/controller/implementation/format/api.rb
|
|
149
|
+
- lib/simple_resource_controller/controller/implementation/format/html.rb
|
|
117
150
|
- lib/simple_resource_controller/railtie.rb
|
|
118
151
|
- lib/simple_resource_controller/version.rb
|
|
119
152
|
- simple_resource_controller.gemspec
|
|
@@ -136,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
136
169
|
- !ruby/object:Gem::Version
|
|
137
170
|
version: '0'
|
|
138
171
|
requirements: []
|
|
139
|
-
rubygems_version: 3.
|
|
172
|
+
rubygems_version: 3.1.2
|
|
140
173
|
signing_key:
|
|
141
174
|
specification_version: 4
|
|
142
175
|
summary: Simple gem for resource controllers
|