rest_framework 0.5.6 → 0.6.1
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/VERSION +1 -1
- data/lib/rest_framework/controller_mixins/base.rb +47 -33
- data/lib/rest_framework/controller_mixins/models.rb +61 -42
- data/lib/rest_framework/filters.rb +12 -9
- data/lib/rest_framework/routers.rb +1 -1
- data/lib/rest_framework/serializers.rb +2 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 33c45fc367d9899fa2e47ea4c042a46ed381986e9210bf4574b61d1301c60fcc
|
4
|
+
data.tar.gz: 225adc8d9b5380e7e403765d7ec21331a61c9a8c562013781571dc84037560d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7178418a52918caf797f2a96bd1d39a5e8291d154ba335122b590e5534cc02124f5203feb24dade1f5dcb84ac45b281a7e4fb30274be943025e2f7850bd1cfca
|
7
|
+
data.tar.gz: e4195747856948df06aa0c396812d6ea3bbd3d374318b3c9f7a60c55747ae62db25ef76fc59e0705fd1531822304c62a416151772d29877aa4b723852015f2db
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.1
|
@@ -45,6 +45,7 @@ module RESTFramework::BaseControllerMixin
|
|
45
45
|
page_query_param: "page",
|
46
46
|
page_size_query_param: "page_size",
|
47
47
|
max_page_size: nil,
|
48
|
+
rescue_unknown_format_with: :json,
|
48
49
|
serializer_class: nil,
|
49
50
|
serialize_to_json: true,
|
50
51
|
serialize_to_xml: true,
|
@@ -145,42 +146,55 @@ module RESTFramework::BaseControllerMixin
|
|
145
146
|
raise RESTFramework::NilPassedToAPIResponseError
|
146
147
|
end
|
147
148
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
format.json {
|
154
|
-
jkwargs = kwargs.merge(json_kwargs)
|
155
|
-
render(json: payload, layout: false, **jkwargs)
|
156
|
-
} if self.class.serialize_to_json
|
157
|
-
format.xml {
|
158
|
-
xkwargs = kwargs.merge(xml_kwargs)
|
159
|
-
render(xml: payload, layout: false, **xkwargs)
|
160
|
-
} if self.class.serialize_to_xml
|
161
|
-
# TODO: possibly support more formats here if supported?
|
162
|
-
end
|
163
|
-
format.html {
|
164
|
-
@payload = payload
|
149
|
+
# Flag to track if we had to rescue unknown format.
|
150
|
+
already_rescued_unknown_format = false
|
151
|
+
|
152
|
+
begin
|
153
|
+
respond_to do |format|
|
165
154
|
if payload == ""
|
166
|
-
|
167
|
-
|
155
|
+
format.json { head(:no_content) } if self.class.serialize_to_json
|
156
|
+
format.xml { head(:no_content) } if self.class.serialize_to_xml
|
168
157
|
else
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
rescue ActionView::MissingTemplate # fallback to rest_framework layout
|
179
|
-
hkwargs[:layout] = "rest_framework"
|
180
|
-
hkwargs[:html] = ""
|
181
|
-
render(**hkwargs)
|
158
|
+
format.json {
|
159
|
+
jkwargs = kwargs.merge(json_kwargs)
|
160
|
+
render(json: payload, layout: false, **jkwargs)
|
161
|
+
} if self.class.serialize_to_json
|
162
|
+
format.xml {
|
163
|
+
xkwargs = kwargs.merge(xml_kwargs)
|
164
|
+
render(xml: payload, layout: false, **xkwargs)
|
165
|
+
} if self.class.serialize_to_xml
|
166
|
+
# TODO: possibly support more formats here if supported?
|
182
167
|
end
|
183
|
-
|
168
|
+
format.html {
|
169
|
+
@payload = payload
|
170
|
+
if payload == ""
|
171
|
+
@json_payload = "" if self.class.serialize_to_json
|
172
|
+
@xml_payload = "" if self.class.serialize_to_xml
|
173
|
+
else
|
174
|
+
@json_payload = payload.to_json if self.class.serialize_to_json
|
175
|
+
@xml_payload = payload.to_xml if self.class.serialize_to_xml
|
176
|
+
end
|
177
|
+
@template_logo_text ||= "Rails REST Framework"
|
178
|
+
@title ||= self.controller_name.camelize
|
179
|
+
@route_groups ||= RESTFramework::Utils.get_routes(Rails.application.routes, request)
|
180
|
+
hkwargs = kwargs.merge(html_kwargs)
|
181
|
+
begin
|
182
|
+
render(**hkwargs)
|
183
|
+
rescue ActionView::MissingTemplate # fallback to rest_framework layout
|
184
|
+
hkwargs[:layout] = "rest_framework"
|
185
|
+
hkwargs[:html] = ""
|
186
|
+
render(**hkwargs)
|
187
|
+
end
|
188
|
+
}
|
189
|
+
end
|
190
|
+
rescue ActionController::UnknownFormat
|
191
|
+
if !already_rescued_unknown_format && rescue_format = self.class.rescue_unknown_format_with
|
192
|
+
request.format = rescue_format
|
193
|
+
already_rescued_unknown_format = true
|
194
|
+
retry
|
195
|
+
else
|
196
|
+
raise
|
197
|
+
end
|
184
198
|
end
|
185
199
|
end
|
186
200
|
end
|
@@ -59,7 +59,7 @@ module RESTFramework::BaseModelControllerMixin
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def _get_specific_action_config(action_config_key, generic_config_key)
|
62
|
-
action_config = self.class.send(action_config_key) || {}
|
62
|
+
action_config = self.class.send(action_config_key)&.with_indifferent_access || {}
|
63
63
|
action = self.action_name&.to_sym
|
64
64
|
|
65
65
|
# Index action should use :list serializer if :index is not provided.
|
@@ -68,38 +68,45 @@ module RESTFramework::BaseModelControllerMixin
|
|
68
68
|
return (action_config[action] if action) || self.class.send(generic_config_key)
|
69
69
|
end
|
70
70
|
|
71
|
-
# Get a list of fields for the current action.
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
71
|
+
# Get a list of fields for the current action. Returning `nil` indicates that anything should be
|
72
|
+
# accepted unless `fallback` is true, in which case we should fallback to this controller's model
|
73
|
+
# columns, or en empty array.
|
74
|
+
def get_fields(fallback: false)
|
75
|
+
fields = _get_specific_action_config(:action_fields, :fields)
|
76
|
+
|
77
|
+
if fallback
|
78
|
+
fields ||= self.get_model&.column_names || []
|
79
|
+
end
|
80
|
+
|
81
|
+
return fields
|
78
82
|
end
|
79
83
|
|
80
84
|
# Get a list of find_by fields for the current action.
|
81
85
|
def get_find_by_fields
|
82
|
-
return self.class.find_by_fields
|
86
|
+
return self.class.find_by_fields || self.get_fields
|
83
87
|
end
|
84
88
|
|
85
|
-
# Get a list of find_by fields for the current action.
|
89
|
+
# Get a list of find_by fields for the current action. Default to the model column names.
|
86
90
|
def get_filterset_fields
|
87
|
-
return self.class.filterset_fields
|
91
|
+
return self.class.filterset_fields || self.get_fields(fallback: true)
|
88
92
|
end
|
89
93
|
|
90
94
|
# Get a list of ordering fields for the current action.
|
91
95
|
def get_ordering_fields
|
92
|
-
return self.class.ordering_fields
|
96
|
+
return self.class.ordering_fields || self.get_fields
|
93
97
|
end
|
94
98
|
|
95
|
-
# Get a list of search fields for the current action.
|
99
|
+
# Get a list of search fields for the current action. Default to the model column names.
|
96
100
|
def get_search_fields
|
97
|
-
return self.class.search_fields
|
101
|
+
return self.class.search_fields || self.get_fields(fallback: true)
|
98
102
|
end
|
99
103
|
|
100
104
|
# Get a list of parameters allowed for the current action.
|
101
105
|
def get_allowed_parameters
|
102
|
-
return _get_specific_action_config(
|
106
|
+
return _get_specific_action_config(
|
107
|
+
:allowed_action_parameters,
|
108
|
+
:allowed_parameters,
|
109
|
+
) || self.fields
|
103
110
|
end
|
104
111
|
|
105
112
|
# Helper to get the configured serializer class, or `NativeSerializer` as a default.
|
@@ -117,14 +124,18 @@ module RESTFramework::BaseModelControllerMixin
|
|
117
124
|
# Filter the request body for keys in current action's allowed_parameters/fields config.
|
118
125
|
def get_body_params
|
119
126
|
return @_get_body_params ||= begin
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
127
|
+
# Filter the request body and map to strings. Return all params if we cannot resolve a list of
|
128
|
+
# allowed parameters or fields.
|
129
|
+
body_params = if allowed_params = self.get_allowed_parameters&.map(&:to_s)
|
130
|
+
request.request_parameters.select { |p| allowed_params.include?(p) }
|
131
|
+
else
|
132
|
+
request.request_parameters
|
133
|
+
end
|
124
134
|
|
125
|
-
# Add query params in place of missing body params, if configured.
|
135
|
+
# Add query params in place of missing body params, if configured. If fields are not defined,
|
136
|
+
# fallback to using columns for this particular feature.
|
126
137
|
if self.class.accept_generic_params_as_body_params
|
127
|
-
(
|
138
|
+
(self.get_fields(fallback: true) - body_params.keys).each do |k|
|
128
139
|
if (value = params[k])
|
129
140
|
body_params[k] = value
|
130
141
|
end
|
@@ -137,7 +148,7 @@ module RESTFramework::BaseModelControllerMixin
|
|
137
148
|
end
|
138
149
|
|
139
150
|
# Filter fields in exclude_body_fields.
|
140
|
-
(self.class.exclude_body_fields || []).each { |f| body_params.delete(f
|
151
|
+
(self.class.exclude_body_fields || []).each { |f| body_params.delete(f) }
|
141
152
|
|
142
153
|
body_params
|
143
154
|
end
|
@@ -181,13 +192,21 @@ module RESTFramework::BaseModelControllerMixin
|
|
181
192
|
|
182
193
|
# Get a single record by primary key or another column, if allowed.
|
183
194
|
def get_record
|
195
|
+
# Cache the result.
|
196
|
+
return @_get_record if @_get_record
|
197
|
+
|
184
198
|
recordset = self.get_recordset
|
185
|
-
find_by_fields = self.get_find_by_fields
|
186
199
|
find_by_key = self.get_model.primary_key
|
187
200
|
|
188
201
|
# Find by another column if it's permitted.
|
189
|
-
if
|
190
|
-
|
202
|
+
if find_by_param = self.class.find_by_query_param.presence
|
203
|
+
if find_by = params[find_by_param].presence
|
204
|
+
find_by_fields = self.get_find_by_fields&.map(&:to_s)
|
205
|
+
|
206
|
+
if !find_by_fields || find_by.in?(find_by_fields)
|
207
|
+
find_by_key = find_by
|
208
|
+
end
|
209
|
+
end
|
191
210
|
end
|
192
211
|
|
193
212
|
# Filter recordset, if configured.
|
@@ -196,18 +215,18 @@ module RESTFramework::BaseModelControllerMixin
|
|
196
215
|
end
|
197
216
|
|
198
217
|
# Return the record. Route key is always :id by Rails convention.
|
199
|
-
return recordset.find_by!(find_by_key => params[:id])
|
218
|
+
return @_get_record = recordset.find_by!(find_by_key => params[:id])
|
200
219
|
end
|
201
220
|
end
|
202
221
|
|
203
222
|
# Mixin for listing records.
|
204
223
|
module RESTFramework::ListModelMixin
|
205
224
|
def index
|
206
|
-
api_response(self.
|
225
|
+
api_response(self.index!)
|
207
226
|
end
|
208
227
|
|
209
|
-
def
|
210
|
-
@records
|
228
|
+
def index!
|
229
|
+
@records ||= self.get_filtered_data(self.get_recordset)
|
211
230
|
|
212
231
|
# Handle pagination, if enabled.
|
213
232
|
if self.class.paginator_class
|
@@ -224,11 +243,11 @@ end
|
|
224
243
|
# Mixin for showing records.
|
225
244
|
module RESTFramework::ShowModelMixin
|
226
245
|
def show
|
227
|
-
api_response(self.
|
246
|
+
api_response(self.show!)
|
228
247
|
end
|
229
248
|
|
230
|
-
def
|
231
|
-
@record
|
249
|
+
def show!
|
250
|
+
@record ||= self.get_record
|
232
251
|
return self.get_serializer_class.new(@record, controller: self).serialize
|
233
252
|
end
|
234
253
|
end
|
@@ -236,16 +255,16 @@ end
|
|
236
255
|
# Mixin for creating records.
|
237
256
|
module RESTFramework::CreateModelMixin
|
238
257
|
def create
|
239
|
-
api_response(self.
|
258
|
+
api_response(self.create!)
|
240
259
|
end
|
241
260
|
|
242
|
-
def
|
261
|
+
def create!
|
243
262
|
if self.get_recordset.respond_to?(:create!) && self.create_from_recordset
|
244
263
|
# Create with any properties inherited from the recordset.
|
245
|
-
@record
|
264
|
+
@record ||= self.get_recordset.create!(self.get_create_params)
|
246
265
|
else
|
247
266
|
# Otherwise, perform a "bare" create.
|
248
|
-
@record
|
267
|
+
@record ||= self.get_model.create!(self.get_create_params)
|
249
268
|
end
|
250
269
|
|
251
270
|
return self.get_serializer_class.new(@record, controller: self).serialize
|
@@ -255,11 +274,11 @@ end
|
|
255
274
|
# Mixin for updating records.
|
256
275
|
module RESTFramework::UpdateModelMixin
|
257
276
|
def update
|
258
|
-
api_response(self.
|
277
|
+
api_response(self.update!)
|
259
278
|
end
|
260
279
|
|
261
|
-
def
|
262
|
-
@record
|
280
|
+
def update!
|
281
|
+
@record ||= self.get_record
|
263
282
|
@record.update!(self.get_update_params)
|
264
283
|
return self.get_serializer_class.new(@record, controller: self).serialize
|
265
284
|
end
|
@@ -268,12 +287,12 @@ end
|
|
268
287
|
# Mixin for destroying records.
|
269
288
|
module RESTFramework::DestroyModelMixin
|
270
289
|
def destroy
|
271
|
-
self.
|
290
|
+
self.destroy!
|
272
291
|
api_response("")
|
273
292
|
end
|
274
293
|
|
275
|
-
def
|
276
|
-
@record
|
294
|
+
def destroy!
|
295
|
+
@record ||= self.get_record
|
277
296
|
@record.destroy!
|
278
297
|
end
|
279
298
|
end
|
@@ -13,15 +13,17 @@ end
|
|
13
13
|
class RESTFramework::ModelFilter < RESTFramework::BaseFilter
|
14
14
|
# Filter params for keys allowed by the current action's filterset_fields/fields config.
|
15
15
|
def _get_filter_params
|
16
|
-
fields
|
17
|
-
|
18
|
-
fields.include?(p)
|
19
|
-
|
16
|
+
# Map filterset fields to strings because query parameter keys are strings.
|
17
|
+
if fields = @controller.get_filterset_fields&.map(&:to_s)
|
18
|
+
return @controller.request.query_parameters.select { |p, _| fields.include?(p) }
|
19
|
+
end
|
20
|
+
|
21
|
+
return @controller.request.query_parameters.to_h
|
20
22
|
end
|
21
23
|
|
22
24
|
# Filter data according to the request query parameters.
|
23
25
|
def get_filtered_data(data)
|
24
|
-
filter_params = self._get_filter_params
|
26
|
+
filter_params = self._get_filter_params.symbolize_keys
|
25
27
|
unless filter_params.blank?
|
26
28
|
return data.where(**filter_params)
|
27
29
|
end
|
@@ -36,11 +38,12 @@ class RESTFramework::ModelOrderingFilter < RESTFramework::BaseFilter
|
|
36
38
|
def _get_ordering
|
37
39
|
return nil if @controller.class.ordering_query_param.blank?
|
38
40
|
|
39
|
-
ordering_fields
|
41
|
+
# Ensure ordering_fields are strings since the split param will be strings.
|
42
|
+
ordering_fields = @controller.get_ordering_fields&.map(&:to_s)
|
40
43
|
order_string = @controller.params[@controller.class.ordering_query_param]
|
41
44
|
|
42
45
|
unless order_string.blank?
|
43
|
-
ordering = {}
|
46
|
+
ordering = {}.with_indifferent_access
|
44
47
|
order_string.split(",").each do |field|
|
45
48
|
if field[0] == "-"
|
46
49
|
column = field[1..-1]
|
@@ -49,8 +52,8 @@ class RESTFramework::ModelOrderingFilter < RESTFramework::BaseFilter
|
|
49
52
|
column = field
|
50
53
|
direction = :asc
|
51
54
|
end
|
52
|
-
if column.in?(ordering_fields)
|
53
|
-
ordering[column
|
55
|
+
if !ordering_fields || column.in?(ordering_fields)
|
56
|
+
ordering[column] = direction
|
54
57
|
end
|
55
58
|
end
|
56
59
|
return ordering
|
@@ -6,7 +6,7 @@ module ActionDispatch::Routing
|
|
6
6
|
# Internal interface to get the controller class from the name and current scope.
|
7
7
|
def _get_controller_class(name, pluralize: true, fallback_reverse_pluralization: true)
|
8
8
|
# Get class name.
|
9
|
-
name = name.to_s.camelize #
|
9
|
+
name = name.to_s.camelize # Camelize to leave plural names plural.
|
10
10
|
name = name.pluralize if pluralize
|
11
11
|
if name == name.pluralize
|
12
12
|
name_reverse = name.singularize
|
@@ -212,9 +212,8 @@ class RESTFramework::NativeSerializer < RESTFramework::BaseSerializer
|
|
212
212
|
return serializer_config.deep_dup
|
213
213
|
end
|
214
214
|
|
215
|
-
# If the config wasn't determined, build a serializer config from
|
216
|
-
fields = @controller
|
217
|
-
if fields
|
215
|
+
# If the config wasn't determined, build a serializer config from controller fields.
|
216
|
+
if fields = @controller&.get_fields
|
218
217
|
fields = fields.deep_dup
|
219
218
|
|
220
219
|
if @model
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest_framework
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gregory N. Schmit
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|