cuprum-rails 0.1.0 → 0.2.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/CHANGELOG.md +145 -0
- data/DEVELOPMENT.md +20 -0
- data/README.md +356 -63
- data/lib/cuprum/rails/action.rb +32 -16
- data/lib/cuprum/rails/actions/create.rb +62 -15
- data/lib/cuprum/rails/actions/destroy.rb +23 -7
- data/lib/cuprum/rails/actions/edit.rb +23 -7
- data/lib/cuprum/rails/actions/index.rb +30 -10
- data/lib/cuprum/rails/actions/middleware/associations/cache.rb +112 -0
- data/lib/cuprum/rails/actions/middleware/associations/find.rb +23 -0
- data/lib/cuprum/rails/actions/middleware/associations/parent.rb +70 -0
- data/lib/cuprum/rails/actions/middleware/associations/query.rb +140 -0
- data/lib/cuprum/rails/actions/middleware/associations.rb +12 -0
- data/lib/cuprum/rails/actions/middleware/log_request.rb +126 -0
- data/lib/cuprum/rails/actions/middleware/log_result.rb +51 -0
- data/lib/cuprum/rails/actions/middleware/resources/find.rb +44 -0
- data/lib/cuprum/rails/actions/middleware/resources/query.rb +91 -0
- data/lib/cuprum/rails/actions/middleware/resources.rb +11 -0
- data/lib/cuprum/rails/actions/middleware.rb +13 -0
- data/lib/cuprum/rails/actions/new.rb +16 -4
- data/lib/cuprum/rails/actions/parameter_validation.rb +60 -0
- data/lib/cuprum/rails/actions/resource_action.rb +119 -42
- data/lib/cuprum/rails/actions/show.rb +23 -7
- data/lib/cuprum/rails/actions/update.rb +70 -22
- data/lib/cuprum/rails/actions.rb +11 -7
- data/lib/cuprum/rails/collection.rb +27 -47
- data/lib/cuprum/rails/command.rb +3 -1
- data/lib/cuprum/rails/commands/destroy_one.rb +10 -6
- data/lib/cuprum/rails/commands/find_many.rb +8 -1
- data/lib/cuprum/rails/commands/find_matching.rb +1 -1
- data/lib/cuprum/rails/commands/find_one.rb +8 -0
- data/lib/cuprum/rails/commands/insert_one.rb +17 -6
- data/lib/cuprum/rails/commands/update_one.rb +16 -5
- data/lib/cuprum/rails/constraints/parameters_contract.rb +14 -0
- data/lib/cuprum/rails/constraints.rb +10 -0
- data/lib/cuprum/rails/controller.rb +12 -2
- data/lib/cuprum/rails/controllers/action.rb +100 -0
- data/lib/cuprum/rails/controllers/class_methods/actions.rb +33 -7
- data/lib/cuprum/rails/controllers/class_methods/configuration.rb +36 -0
- data/lib/cuprum/rails/controllers/class_methods/middleware.rb +88 -0
- data/lib/cuprum/rails/controllers/class_methods/validations.rb +2 -2
- data/lib/cuprum/rails/controllers/configuration.rb +41 -1
- data/lib/cuprum/rails/controllers/middleware.rb +59 -0
- data/lib/cuprum/rails/controllers.rb +2 -0
- data/lib/cuprum/rails/errors/invalid_parameters.rb +55 -0
- data/lib/cuprum/rails/errors/invalid_statement.rb +11 -0
- data/lib/cuprum/rails/errors/missing_parameter.rb +42 -0
- data/lib/cuprum/rails/errors/resource_error.rb +46 -0
- data/lib/cuprum/rails/errors.rb +6 -1
- data/lib/cuprum/rails/map_errors.rb +29 -1
- data/lib/cuprum/rails/query.rb +1 -1
- data/lib/cuprum/rails/repository.rb +12 -25
- data/lib/cuprum/rails/request.rb +149 -60
- data/lib/cuprum/rails/resource.rb +119 -85
- data/lib/cuprum/rails/responders/base_responder.rb +78 -0
- data/lib/cuprum/rails/responders/html/plural_resource.rb +9 -39
- data/lib/cuprum/rails/responders/html/rendering.rb +81 -0
- data/lib/cuprum/rails/responders/html/resource.rb +107 -0
- data/lib/cuprum/rails/responders/html/singular_resource.rb +9 -38
- data/lib/cuprum/rails/responders/html.rb +2 -0
- data/lib/cuprum/rails/responders/html_responder.rb +8 -52
- data/lib/cuprum/rails/responders/json/resource.rb +3 -3
- data/lib/cuprum/rails/responders/json_responder.rb +31 -16
- data/lib/cuprum/rails/responders/matching.rb +29 -27
- data/lib/cuprum/rails/responders/serialization.rb +11 -9
- data/lib/cuprum/rails/responders.rb +1 -0
- data/lib/cuprum/rails/responses/head_response.rb +24 -0
- data/lib/cuprum/rails/responses/html/redirect_back_response.rb +55 -0
- data/lib/cuprum/rails/responses/html/redirect_response.rb +19 -4
- data/lib/cuprum/rails/responses/html/render_response.rb +17 -5
- data/lib/cuprum/rails/responses/html.rb +6 -2
- data/lib/cuprum/rails/responses.rb +1 -0
- data/lib/cuprum/rails/result.rb +36 -0
- data/lib/cuprum/rails/routes.rb +36 -23
- data/lib/cuprum/rails/rspec/contract_helpers.rb +57 -0
- data/lib/cuprum/rails/rspec/contracts/action_contracts.rb +754 -0
- data/lib/cuprum/rails/rspec/contracts/actions/create_contracts.rb +289 -0
- data/lib/cuprum/rails/rspec/contracts/actions/destroy_contracts.rb +164 -0
- data/lib/cuprum/rails/rspec/contracts/actions/edit_contracts.rb +73 -0
- data/lib/cuprum/rails/rspec/contracts/actions/index_contracts.rb +108 -0
- data/lib/cuprum/rails/rspec/contracts/actions/new_contracts.rb +111 -0
- data/lib/cuprum/rails/rspec/contracts/actions/show_contracts.rb +72 -0
- data/lib/cuprum/rails/rspec/contracts/actions/update_contracts.rb +263 -0
- data/lib/cuprum/rails/rspec/contracts/actions.rb +8 -0
- data/lib/cuprum/rails/rspec/contracts/command_contracts.rb +479 -0
- data/lib/cuprum/rails/rspec/contracts/responder_contracts.rb +232 -0
- data/lib/cuprum/rails/rspec/contracts/routes_contracts.rb +363 -0
- data/lib/cuprum/rails/rspec/contracts/serializers_contracts.rb +70 -0
- data/lib/cuprum/rails/rspec/contracts.rb +8 -0
- data/lib/cuprum/rails/rspec/matchers/be_a_result_matcher.rb +64 -0
- data/lib/cuprum/rails/rspec/matchers.rb +41 -0
- data/lib/cuprum/rails/serializers/base_serializer.rb +60 -0
- data/lib/cuprum/rails/serializers/context.rb +84 -0
- data/lib/cuprum/rails/serializers/json/active_record_serializer.rb +2 -2
- data/lib/cuprum/rails/serializers/json/array_serializer.rb +9 -8
- data/lib/cuprum/rails/serializers/json/attributes_serializer.rb +95 -172
- data/lib/cuprum/rails/serializers/json/error_serializer.rb +2 -2
- data/lib/cuprum/rails/serializers/json/hash_serializer.rb +9 -8
- data/lib/cuprum/rails/serializers/json/identity_serializer.rb +3 -3
- data/lib/cuprum/rails/serializers/json/properties_serializer.rb +252 -0
- data/lib/cuprum/rails/serializers/json.rb +2 -1
- data/lib/cuprum/rails/serializers.rb +3 -1
- data/lib/cuprum/rails/version.rb +1 -1
- data/lib/cuprum/rails.rb +19 -16
- metadata +73 -131
- data/lib/cuprum/rails/controller_action.rb +0 -121
- data/lib/cuprum/rails/errors/missing_parameters.rb +0 -33
- data/lib/cuprum/rails/errors/missing_primary_key.rb +0 -46
- data/lib/cuprum/rails/errors/undefined_permitted_attributes.rb +0 -34
- data/lib/cuprum/rails/rspec/command_contract.rb +0 -460
- data/lib/cuprum/rails/rspec/define_route_contract.rb +0 -84
- data/lib/cuprum/rails/serializers/json/serializer.rb +0 -66
data/lib/cuprum/rails/request.rb
CHANGED
@@ -13,24 +13,29 @@ module Cuprum::Rails
|
|
13
13
|
].freeze
|
14
14
|
private_constant :FILTERED_HEADER_PREFIXES
|
15
15
|
|
16
|
-
FILTERED_PARAMS = %w[controller action].freeze
|
17
|
-
private_constant :FILTERED_PARAMS
|
18
|
-
|
19
16
|
# Generates a Request from a native Rails request.
|
20
17
|
#
|
21
|
-
# @param request [] The native request to build.
|
18
|
+
# @param request [ActionDispatch::Request] The native request to build.
|
22
19
|
#
|
23
20
|
# @return [Cuprum::Rails::Request] the generated request.
|
24
|
-
def build(request:
|
21
|
+
def build(request:, **options) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
22
|
+
body_params = request.request_parameters
|
23
|
+
query_params = request.query_parameters
|
24
|
+
path_params = filter_path_parameters(request.path_parameters)
|
25
|
+
|
25
26
|
new(
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
action_name: request.params['action']&.intern,
|
28
|
+
authorization: request.authorization,
|
29
|
+
body_params: body_params,
|
30
|
+
controller_name: request.params['controller'],
|
31
|
+
format: request.format.symbol,
|
32
|
+
headers: filter_headers(request.headers),
|
33
|
+
http_method: request.request_method_symbol,
|
34
|
+
params: body_params.merge(query_params).merge(path_params),
|
35
|
+
path: request.fullpath,
|
36
|
+
path_params: path_params,
|
37
|
+
query_params: query_params,
|
38
|
+
**options
|
34
39
|
)
|
35
40
|
end
|
36
41
|
|
@@ -42,64 +47,148 @@ module Cuprum::Rails
|
|
42
47
|
end
|
43
48
|
end
|
44
49
|
|
45
|
-
def
|
46
|
-
|
50
|
+
def filter_path_parameters(path_parameters)
|
51
|
+
path_parameters.except('action', 'controller')
|
52
|
+
end
|
53
|
+
|
54
|
+
def property(property_name)
|
55
|
+
define_method(property_name) do
|
56
|
+
@properties[property_name]
|
57
|
+
end
|
58
|
+
|
59
|
+
define_method(:"#{property_name}=") do |value|
|
60
|
+
@properties[property_name] = value
|
61
|
+
end
|
47
62
|
end
|
48
63
|
end
|
49
64
|
|
50
|
-
# @param
|
51
|
-
#
|
52
|
-
#
|
53
|
-
# @
|
54
|
-
#
|
55
|
-
# @
|
56
|
-
#
|
57
|
-
# @
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
@
|
70
|
-
@
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
65
|
+
# @param context [Object] the controller or request context.
|
66
|
+
#
|
67
|
+
# @option properties [Symbol] :action_name the name of the called action.
|
68
|
+
# @option properties [String, nil] :authorization the authorization header,
|
69
|
+
# if any.
|
70
|
+
# @option properties [Hash<String, Object>] :body_params the parameters from
|
71
|
+
# the request body.
|
72
|
+
# @option properties [String] :controller_name the name of the controller.
|
73
|
+
# @option properties [Symbol] :format the request format, e.g. :html or
|
74
|
+
# :json.
|
75
|
+
# @option properties [Hash<String, String>] :headers the request headers.
|
76
|
+
# @option properties [Boolean] :member_action true if the request is for a
|
77
|
+
# resource member action; otherwise false.
|
78
|
+
# @option properties [Symbol] :method the HTTP method used for the request.
|
79
|
+
# @option properties [Hash<String, Object>] :params the merged GET and POST
|
80
|
+
# parameters.
|
81
|
+
# @option properties [Hash<String, Object>] :query_params the query
|
82
|
+
# parameters.
|
83
|
+
def initialize(context: nil, **properties)
|
84
|
+
@context = context
|
85
|
+
@properties = properties
|
86
|
+
end
|
87
|
+
|
88
|
+
# @return [Object] the controller or request context.
|
89
|
+
attr_reader :context
|
90
|
+
|
91
|
+
# @return [Hash<Symbol, Object>] the properties of the request.
|
92
|
+
attr_reader :properties
|
93
|
+
|
94
|
+
# @!attribute action_name
|
95
|
+
# @return [Symbol] the name of the called action.
|
96
|
+
property :action_name
|
97
|
+
|
98
|
+
# @!attribute authorization
|
99
|
+
# @return [String, nil] the authorization header, if any.
|
100
|
+
property :authorization
|
101
|
+
|
102
|
+
# @!attribute body_params
|
103
|
+
# @return [Hash<String, Object>] the parameters from the request body.
|
104
|
+
property :body_params
|
105
|
+
alias body_parameters body_params
|
106
|
+
alias body_parameters= body_params=
|
107
|
+
|
108
|
+
# @!attribute controller_name
|
109
|
+
# @return [String] the name of the controller.
|
110
|
+
property :controller_name
|
111
|
+
|
112
|
+
# @!attribute format [Symbol]
|
113
|
+
# @return the request format, e.g. :html or :json.
|
114
|
+
property :format
|
115
|
+
|
116
|
+
# @!attribute headers
|
117
|
+
# @return [Hash<String, String>] the request headers.
|
118
|
+
property :headers
|
119
|
+
|
120
|
+
# @!attribute method
|
121
|
+
# @return [Symbol] the HTTP method used for the request.
|
122
|
+
property :http_method
|
123
|
+
|
124
|
+
# @!attribute params
|
125
|
+
# @return [Hash<String, Object>] The merged GET and POST parameters.
|
126
|
+
property :params
|
127
|
+
alias parameters params
|
128
|
+
alias parameters= params=
|
129
|
+
|
130
|
+
# @!attribute path
|
131
|
+
# @return [String] the relative path of the request, including params.
|
132
|
+
property :path
|
133
|
+
|
134
|
+
# @!attribute path_params
|
135
|
+
# @return [Hash<String, Object>] the path parameters.
|
136
|
+
property :path_params
|
137
|
+
alias path_parameters path_params
|
138
|
+
alias path_parameters= path_params=
|
139
|
+
|
140
|
+
# @!attribute query_params
|
141
|
+
# @return [Hash<String, Object>] the query parameters.
|
142
|
+
property :query_params
|
143
|
+
alias query_parameters query_params
|
144
|
+
alias query_parameters= query_params=
|
145
|
+
|
146
|
+
# @param property_name [String, Symbol] the name of the property.
|
147
|
+
#
|
148
|
+
# @return [Object] the value of the property
|
149
|
+
def [](property_name)
|
150
|
+
validate_property_name!(property_name)
|
151
|
+
|
152
|
+
@properties[property_name.intern]
|
76
153
|
end
|
77
154
|
|
78
|
-
# @
|
79
|
-
|
155
|
+
# @param property_name [String, Symbol] the name of the property.
|
156
|
+
# @param value [Object] the value to assign to the property.
|
157
|
+
def []=(property_name, value)
|
158
|
+
validate_property_name!(property_name)
|
159
|
+
|
160
|
+
@properties[property_name.intern] = value
|
161
|
+
end
|
80
162
|
|
81
|
-
# @return [
|
82
|
-
|
83
|
-
|
163
|
+
# @return [Boolean] true if the request is for a resource member action;
|
164
|
+
# otherwise false.
|
165
|
+
def member_action?
|
166
|
+
!!@properties[:member_action]
|
167
|
+
end
|
84
168
|
|
85
|
-
# @return [
|
86
|
-
|
169
|
+
# @return [ActionDispatch::Request::Session] the native session object.
|
170
|
+
def native_session
|
171
|
+
context&.session
|
172
|
+
end
|
87
173
|
|
88
|
-
|
89
|
-
attr_reader :headers
|
174
|
+
private
|
90
175
|
|
91
|
-
|
92
|
-
|
176
|
+
def validate_property_name!(name) # rubocop:disable Metrics/MethodLength
|
177
|
+
if name.nil?
|
178
|
+
raise ArgumentError,
|
179
|
+
"property name can't be blank",
|
180
|
+
caller(1..-1)
|
181
|
+
end
|
93
182
|
|
94
|
-
|
95
|
-
|
96
|
-
|
183
|
+
unless name.is_a?(String) || name.is_a?(Symbol)
|
184
|
+
raise ArgumentError,
|
185
|
+
'property name must be a String or a Symbol',
|
186
|
+
caller(1..-1)
|
187
|
+
end
|
97
188
|
|
98
|
-
|
99
|
-
attr_reader :path
|
189
|
+
return unless name.empty?
|
100
190
|
|
101
|
-
|
102
|
-
|
103
|
-
alias query_parameters query_params
|
191
|
+
raise ArgumentError, "property name can't be blank", caller(1..-1)
|
192
|
+
end
|
104
193
|
end
|
105
194
|
end
|
@@ -1,67 +1,85 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'cuprum/collections/resource'
|
4
|
+
|
3
5
|
require 'cuprum/rails'
|
6
|
+
require 'cuprum/rails/collection'
|
4
7
|
|
5
8
|
module Cuprum::Rails
|
6
9
|
# Value object representing a controller resource.
|
7
|
-
class Resource
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
class Resource < Cuprum::Collections::Resource
|
11
|
+
# Default actions for a plural resource.
|
12
|
+
PLURAL_ACTIONS = %w[create destroy edit index new show update].freeze
|
13
|
+
|
14
|
+
# Default actions for a singular resource.
|
15
|
+
SINGULAR_ACTIONS = %w[create destroy edit new show update].freeze
|
16
|
+
|
17
|
+
STRING_COLUMN_TYPES = Set.new(%i[string uuid]).freeze
|
18
|
+
private_constant :STRING_COLUMN_TYPES
|
19
|
+
|
20
|
+
# @overload initialize(entity_class: nil, name: nil, qualified_name: nil, singular_name: nil, **options)
|
21
|
+
# @param entity_class [Class, String] the class of entity represented by
|
22
|
+
# the resource.
|
23
|
+
# @param name [String] the name of the resource.
|
24
|
+
# @param qualified_name [String] a scoped name for the resource.
|
25
|
+
# @param routes [Cuprum::Rails::Routes] the routes defined for the
|
26
|
+
# resource.
|
27
|
+
# @param singular_name [String] the name of an entity in the resource.
|
28
|
+
# @param options [Hash] additional options for the resource.
|
16
29
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
@
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
# @return [Hash] additional options for the resource.
|
52
|
-
attr_reader :options
|
53
|
-
|
54
|
-
# @return [Class] class representing the resource items.
|
55
|
-
attr_reader :resource_class
|
30
|
+
# @option options actions [Array, Set] the defined actions for the
|
31
|
+
# resource.
|
32
|
+
# @option options base_path [String] the base url for the resource.
|
33
|
+
# @option options default_order [Hash] the default ordering for the
|
34
|
+
# resource items.
|
35
|
+
# @option options permitted_attributes [Array] list of attributes that can
|
36
|
+
# be set or changed by resourceful actions.
|
37
|
+
# @option options primary_key_name [String] the name of the primary key
|
38
|
+
# attribute. Defaults to 'id'.
|
39
|
+
# @option primary_key_type [Class, Stannum::Constraint] the type of
|
40
|
+
# the primary key attribute. Defaults to Integer.
|
41
|
+
# @option options plural [Boolean] if true, the resource represents a
|
42
|
+
# plural resource. Defaults to true. Can also be specified as :singular.
|
43
|
+
# @option primary_key_type [Class, Stannum::Constraint] the type of
|
44
|
+
# the primary key attribute. Defaults to Integer.
|
45
|
+
def initialize(routes: nil, **params)
|
46
|
+
validate_permitted_attributes(params[:permitted_attributes])
|
47
|
+
|
48
|
+
super(**params)
|
49
|
+
|
50
|
+
@routes = routes
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [Set] the defined actions for the resource.
|
54
|
+
def actions
|
55
|
+
@actions ||= Set.new(options.fetch(:actions, default_actions).map(&:to_s))
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Array<Resource>] the resource's ancestors, starting with the
|
59
|
+
# resource itself.
|
60
|
+
def ancestors
|
61
|
+
each_ancestor.to_a
|
62
|
+
end
|
56
63
|
|
57
64
|
# @return [String] the base url for the resource.
|
58
65
|
def base_path
|
59
66
|
@base_path ||=
|
60
67
|
options
|
61
|
-
.fetch(:base_path) {
|
68
|
+
.fetch(:base_path) { default_base_path }
|
62
69
|
.to_s
|
63
70
|
end
|
64
71
|
|
72
|
+
# Enumerates the resource's ancestors, starting with the resource itself.
|
73
|
+
#
|
74
|
+
# @yield_param [Resource] the current ancestor.
|
75
|
+
def each_ancestor(&block)
|
76
|
+
return enum_for(:each_ancestor) unless block_given?
|
77
|
+
|
78
|
+
parent&.each_ancestor(&block)
|
79
|
+
|
80
|
+
yield self
|
81
|
+
end
|
82
|
+
|
65
83
|
# @return [Hash] the default ordering for the resource items.
|
66
84
|
def default_order
|
67
85
|
@default_order ||= options.fetch(:default_order, {})
|
@@ -73,27 +91,32 @@ module Cuprum::Rails
|
|
73
91
|
@permitted_attributes ||= options.fetch(:permitted_attributes, nil)
|
74
92
|
end
|
75
93
|
|
76
|
-
# @return [
|
77
|
-
|
78
|
-
|
79
|
-
!@singular
|
80
|
-
end
|
81
|
-
|
82
|
-
# @return [String] the name of the primary key for the resource, if any.
|
83
|
-
def primary_key
|
84
|
-
@primary_key ||=
|
94
|
+
# @return [String] the name of the primary key attribute. Defaults to 'id'.
|
95
|
+
def primary_key_name
|
96
|
+
@primary_key_name ||=
|
85
97
|
options
|
86
|
-
.fetch(:
|
87
|
-
.
|
98
|
+
.fetch(:primary_key_name) { entity_class.primary_key }
|
99
|
+
.to_s
|
88
100
|
end
|
101
|
+
alias primary_key primary_key_name
|
89
102
|
|
90
|
-
# @return [
|
91
|
-
def
|
92
|
-
|
103
|
+
# @return [Cuprum::Rails::Resource] the parent resource, if any.
|
104
|
+
def parent
|
105
|
+
@parent ||= @options.fetch(:parent, nil)
|
106
|
+
end
|
93
107
|
|
94
|
-
|
108
|
+
# @return [Class, Stannum::Constraint] the type of the primary key
|
109
|
+
# attribute. Defaults to Integer.
|
110
|
+
def primary_key_type
|
111
|
+
@primary_key_type =
|
112
|
+
options
|
113
|
+
.fetch(:primary_key_type) do
|
114
|
+
key = entity_class.primary_key
|
115
|
+
column = entity_class.columns.find { |col| col.name == key }
|
95
116
|
|
96
|
-
|
117
|
+
STRING_COLUMN_TYPES.include?(column.type) ? String : Integer
|
118
|
+
end # rubocop:disable Style/MultilineBlockChain
|
119
|
+
.then { |value| value.is_a?(String) ? value.constantize : value }
|
97
120
|
end
|
98
121
|
|
99
122
|
# Generates the routes for the resource and injects the given wildcards.
|
@@ -105,41 +128,52 @@ module Cuprum::Rails
|
|
105
128
|
routes_without_wildcards.with_wildcards(wildcards)
|
106
129
|
end
|
107
130
|
|
108
|
-
|
109
|
-
|
110
|
-
def
|
111
|
-
|
131
|
+
private
|
132
|
+
|
133
|
+
def default_actions
|
134
|
+
singular? ? SINGULAR_ACTIONS : PLURAL_ACTIONS
|
112
135
|
end
|
113
136
|
|
114
|
-
|
115
|
-
|
116
|
-
@singular_resource_name ||=
|
117
|
-
options
|
118
|
-
.fetch(:singular_resource_name) do
|
119
|
-
resource_name.singularize
|
120
|
-
end
|
121
|
-
.to_s
|
137
|
+
def default_base_path
|
138
|
+
"#{parent_path}/#{(singular? ? name.singularize : name).underscore}"
|
122
139
|
end
|
123
140
|
|
124
|
-
def
|
125
|
-
return
|
141
|
+
def default_parent_path
|
142
|
+
return unless parent
|
126
143
|
|
127
|
-
|
128
|
-
|
129
|
-
|
144
|
+
return parent.base_path if parent.singular?
|
145
|
+
|
146
|
+
"#{parent.base_path}/:#{parent.singular_name}_id"
|
130
147
|
end
|
131
148
|
|
132
|
-
|
149
|
+
def parent_path
|
150
|
+
@parent_path || default_parent_path
|
151
|
+
end
|
152
|
+
|
153
|
+
def routes_options
|
154
|
+
{
|
155
|
+
base_path: base_path,
|
156
|
+
parent_path: parent_path
|
157
|
+
}
|
158
|
+
end
|
133
159
|
|
134
160
|
def routes_without_wildcards
|
135
161
|
return @routes if @routes
|
136
162
|
|
137
163
|
@routes =
|
138
164
|
if plural?
|
139
|
-
Cuprum::Rails::Routing::PluralRoutes.new(
|
165
|
+
Cuprum::Rails::Routing::PluralRoutes.new(**routes_options)
|
140
166
|
else
|
141
|
-
Cuprum::Rails::Routing::SingularRoutes.new(
|
167
|
+
Cuprum::Rails::Routing::SingularRoutes.new(**routes_options)
|
142
168
|
end
|
143
169
|
end
|
170
|
+
|
171
|
+
def validate_permitted_attributes(attributes)
|
172
|
+
return if attributes.nil? || attributes.is_a?(Array)
|
173
|
+
|
174
|
+
raise ArgumentError,
|
175
|
+
'keyword :permitted_attributes must be an Array or nil',
|
176
|
+
caller(1..-1)
|
177
|
+
end
|
144
178
|
end
|
145
179
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/rails/responders'
|
4
|
+
|
5
|
+
module Cuprum::Rails::Responders
|
6
|
+
# Abstract base class for defining responders.
|
7
|
+
class BaseResponder
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
# @param action_name [String, Symbol] the name of the action to match.
|
11
|
+
# @param controller [Cuprum::Rails::Controller] the called controller.
|
12
|
+
# @param member_action [Boolean] true if the action acts on a collection
|
13
|
+
# item, not on the collection as a whole.
|
14
|
+
# @param request [Cuprum::Rails::Request] the request to the controller.
|
15
|
+
def initialize(
|
16
|
+
action_name:,
|
17
|
+
controller:,
|
18
|
+
request:,
|
19
|
+
member_action: false,
|
20
|
+
**_options
|
21
|
+
)
|
22
|
+
@action_name = action_name
|
23
|
+
@controller = controller
|
24
|
+
@controller_name = controller.class.name
|
25
|
+
@member_action = !!member_action # rubocop:disable Style/DoubleNegation
|
26
|
+
@request = request
|
27
|
+
@resource = controller.class.resource
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [String, Symbol] the name of the action to match.
|
31
|
+
attr_reader :action_name
|
32
|
+
|
33
|
+
# @return [Cuprum::Rails::Controller] the called controller.
|
34
|
+
attr_reader :controller
|
35
|
+
|
36
|
+
# @return [String] the name of the called controller.
|
37
|
+
attr_reader :controller_name
|
38
|
+
|
39
|
+
# @return [Cuprum::Rails::Request] the request to the controller.
|
40
|
+
attr_reader :request
|
41
|
+
|
42
|
+
# @return [Cuprum::Rails::Resource] the resource for the controller.
|
43
|
+
attr_reader :resource
|
44
|
+
|
45
|
+
# @return [Cuprum::Result] the result of calling the action.
|
46
|
+
attr_reader :result
|
47
|
+
|
48
|
+
# Generates the response object for the result.
|
49
|
+
#
|
50
|
+
# @param result [Cuprum::Result] the result of the action call.
|
51
|
+
#
|
52
|
+
# @return [#call] the response object from the matching response clause.
|
53
|
+
def call(result)
|
54
|
+
@result = result
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [true, false] true if the action is a member action, otherwise
|
58
|
+
# false.
|
59
|
+
def member_action?
|
60
|
+
@member_action
|
61
|
+
end
|
62
|
+
|
63
|
+
# Helper for accessing the configured routes for the resource.
|
64
|
+
#
|
65
|
+
# Any wildcards from the path params will be applied to the routes.
|
66
|
+
#
|
67
|
+
# @return [Cuprum::Rails::Routes] the configured routes.
|
68
|
+
def routes
|
69
|
+
resource.routes.with_wildcards(routes_wildcards)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def routes_wildcards
|
75
|
+
request.path_params || {}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'cuprum/collections/errors/failed_validation'
|
4
4
|
|
5
5
|
require 'cuprum/rails/responders/html'
|
6
|
+
require 'cuprum/rails/responders/html/resource'
|
6
7
|
|
7
8
|
module Cuprum::Rails::Responders::Html
|
8
9
|
# Defines default responses for a plural RESTful resource.
|
@@ -18,45 +19,14 @@ module Cuprum::Rails::Responders::Html
|
|
18
19
|
# action name and passing the result value as assigned variables. For a
|
19
20
|
# failing result, redirects to either the show page or the index page for the
|
20
21
|
# resource, based on the resource's defined #routes.
|
21
|
-
class PluralResource < Cuprum::Rails::Responders::
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
match :success do
|
30
|
-
entity = result.value[resource.singular_resource_name]
|
31
|
-
|
32
|
-
redirect_to resource.routes.show_path(entity)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
action :destroy do
|
37
|
-
match :success do
|
38
|
-
redirect_to resource.routes.index_path
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
action :index do
|
43
|
-
match :failure do
|
44
|
-
redirect_to resource.routes.root_path
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
action :update do
|
49
|
-
match :failure, error: Cuprum::Collections::Errors::FailedValidation do
|
50
|
-
render :edit,
|
51
|
-
assigns: result.value.merge(errors: result.error.errors),
|
52
|
-
status: 422 # rubocop:disable Rails/HttpStatus
|
53
|
-
end
|
54
|
-
|
55
|
-
match :success do
|
56
|
-
entity = result.value[resource.singular_resource_name]
|
57
|
-
|
58
|
-
redirect_to resource.routes.show_path(entity)
|
59
|
-
end
|
22
|
+
class PluralResource < Cuprum::Rails::Responders::Html::Resource
|
23
|
+
def initialize(**options)
|
24
|
+
super
|
25
|
+
|
26
|
+
SleepingKingStudios::Tools::CoreTools.deprecate(
|
27
|
+
'Cuprum::Rails::Responders::Html::PluralResource',
|
28
|
+
message: 'use Cuprum::Rails::Responders::Html::Resource'
|
29
|
+
)
|
60
30
|
end
|
61
31
|
end
|
62
32
|
end
|