rest_framework 0.9.15 → 0.10.0

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
  SHA256:
3
- metadata.gz: 734af1c9a436fd842c36503794ef16b94e4b0d3f7ad91d011bcd12d06e4b1e21
4
- data.tar.gz: d4c0140985a5405750cdd092c4a70b092be69b3523a3c088d2268711c38e5ad1
3
+ metadata.gz: 8a916afbf32cf43553b8aa952024011639f311ab80db53685163e607e48e1ad0
4
+ data.tar.gz: 1cc8aa7aed712a63b1ef9586c37b64a87de62fe5dfdcf659e982a1b77c20fd89
5
5
  SHA512:
6
- metadata.gz: 4fc442c77a0c8543913ceacd7a7116f9e044ee1d9b0e3e08a5c58ddb6d00ee12b7f719c83e7aed233070075bb031aa8a90cabc7337bd57e28883aca4221d5ea6
7
- data.tar.gz: 2f60ffddea13e956a3a0a0ec909d2de533cc0c5b350af75467f7e006b5133c982192cbcc28da7cb566803458c76917ae702f4838c3f0096722a94f5309babb7a
6
+ metadata.gz: bef1f7c3c52c7a42e8c307ccaf37e4e25f4e663359e26be433f20fd644fca0e59cd3b56613f965b084662046577576728981a320d1d5a5a6517d98556008fc99
7
+ data.tar.gz: '080f96e20b330a391b896db89a192e415328aa320f8d669260d8d282c0eee709022afa7fa5dd484449eb5bba85544f8974d24764a5e5b45821803d1ccd3c23f0'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.15
1
+ 0.10.0
@@ -3,11 +3,10 @@
3
3
  <head>
4
4
  <title><%= @title %></title>
5
5
 
6
- <%# These dynamic tags cannot be cached, so include directly instead of in `head` partial. %>
7
6
  <%= csrf_meta_tags %>
8
7
  <%= csp_meta_tag rescue nil %>
9
8
 
10
- <%= render partial: "rest_framework/head", cached: true %>
9
+ <%= render partial: "rest_framework/head" %>
11
10
 
12
11
  <%= yield :head %>
13
12
  </head>
@@ -296,8 +296,9 @@
296
296
  document.write(content)
297
297
  document.close()
298
298
 
299
- // Trigger `DOMContentLoaded` manually so our custom JavaScript works.
300
- document.dispatchEvent(new Event("DOMContentLoaded", {bubbles: true, cancelable: true}))
299
+ // It seems that `DOMContentLoaded` is already triggered on `document.close()`.
300
+ // // Trigger `DOMContentLoaded` manually so our custom JavaScript works.
301
+ // // document.dispatchEvent(new Event("DOMContentLoaded", {bubbles: true, cancelable: true}))
301
302
  }
302
303
 
303
304
  // Refresh the window as a `GET` request.
@@ -3,7 +3,7 @@
3
3
  <%= render partial: "rest_framework/heading/actions" if @route_groups.present? %>
4
4
  <h1 style="margin: 0"><%= @heading_title || @title %></h1>
5
5
  <% if @description.present? %>
6
- <br><br><p style="display: inline-block; margin-bottom: 0"><%= @description %></p>
6
+ <p style="display: inline-block; margin-bottom: 0; margin-top: 1em"><%= @description %></p>
7
7
  <% end %>
8
8
  </div>
9
9
  </div>
@@ -26,14 +26,14 @@
26
26
  %>
27
27
  <div class="mb-2">
28
28
  <% if metadata[:kind] == "rich_text" %>
29
- <label class="form-label w-100"><%= controller.class.get_label(f) %></label>
29
+ <label class="form-label w-100"><%= controller.class.label_for(f) %></label>
30
30
  <%= form.rich_text_area f %>
31
31
  <% elsif metadata[:kind] == "attachment" %>
32
- <label class="form-label w-100"><%= controller.class.get_label(f) %>
32
+ <label class="form-label w-100"><%= controller.class.label_for(f) %>
33
33
  <%= form.file_field f, multiple: metadata.dig(:attachment, :macro) == :has_many_attached %>
34
34
  </label>
35
35
  <% else %>
36
- <label class="form-label w-100"><%= controller.class.get_label(f) %>
36
+ <label class="form-label w-100"><%= controller.class.label_for(f) %>
37
37
  <%= form.text_field f, class: "form-control form-control-sm" %>
38
38
  </label>
39
39
  <% end %>
@@ -40,7 +40,7 @@
40
40
  local: true,
41
41
  }.compact) do |form| %>
42
42
  <% attachment_reflections.each do |field, ref| %>
43
- <label class="form-label w-100"><%= controller.class.get_label(field) %>
43
+ <label class="form-label w-100"><%= controller.class.label_for(field) %>
44
44
  <%= form.file_field field, multiple: ref.macro == :has_many_attached %>
45
45
  </label>
46
46
  <% end %>
@@ -3,7 +3,7 @@ class RESTFramework::Filters::BaseFilter
3
3
  @controller = controller
4
4
  end
5
5
 
6
- def get_filtered_data(data)
6
+ def filter_data(data)
7
7
  raise NotImplementedError
8
8
  end
9
9
  end
@@ -1,5 +1,5 @@
1
1
  # A filter backend which handles ordering of the recordset.
2
- class RESTFramework::Filters::ModelOrderingFilter < RESTFramework::Filters::BaseFilter
2
+ class RESTFramework::Filters::OrderingFilter < RESTFramework::Filters::BaseFilter
3
3
  # Get a list of ordering fields for the current action.
4
4
  def _get_fields
5
5
  return @controller.ordering_fields&.map(&:to_s) || @controller.get_fields
@@ -38,7 +38,7 @@ class RESTFramework::Filters::ModelOrderingFilter < RESTFramework::Filters::Base
38
38
  end
39
39
 
40
40
  # Order data according to the request query parameters.
41
- def get_filtered_data(data)
41
+ def filter_data(data)
42
42
  ordering = self._get_ordering
43
43
  reorder = !@controller.ordering_no_reorder
44
44
 
@@ -51,4 +51,7 @@ class RESTFramework::Filters::ModelOrderingFilter < RESTFramework::Filters::Base
51
51
  end
52
52
 
53
53
  # Alias for convenience.
54
- RESTFramework::ModelOrderingFilter = RESTFramework::Filters::ModelOrderingFilter
54
+ RESTFramework::OrderingFilter = RESTFramework::Filters::OrderingFilter
55
+
56
+ # TODO: Compatibility; remove in 1.0.
57
+ RESTFramework::ModelOrderingFilter = RESTFramework::Filters::OrderingFilter
@@ -1,14 +1,14 @@
1
1
  # A simple filtering backend that supports filtering a recordset based on query parameters.
2
- class RESTFramework::Filters::ModelQueryFilter < RESTFramework::Filters::BaseFilter
2
+ class RESTFramework::Filters::QueryFilter < RESTFramework::Filters::BaseFilter
3
3
  NIL_VALUES = ["nil", "null"].freeze
4
4
 
5
- # Get a list of filterset fields for the current action.
5
+ # Get a list of filter fields for the current action.
6
6
  def _get_fields
7
7
  # Always return a list of strings; `@controller.get_fields` already does this.
8
- return @controller.class.filterset_fields&.map(&:to_s) || @controller.get_fields
8
+ return @controller.class.filter_fields&.map(&:to_s) || @controller.get_fields
9
9
  end
10
10
 
11
- # Filter params for keys allowed by the current action's filterset_fields/fields config.
11
+ # Filter params for keys allowed by the current action's filter_fields/fields config.
12
12
  def _get_filter_params
13
13
  fields = self._get_fields
14
14
  includes = []
@@ -22,7 +22,7 @@ class RESTFramework::Filters::ModelQueryFilter < RESTFramework::Filters::BaseFil
22
22
  field, sub_field = match[1..2]
23
23
  next false unless field.in?(fields)
24
24
 
25
- sub_fields = @controller.class.get_field_config(field)[:sub_fields] || []
25
+ sub_fields = @controller.class.field_config_for(field)[:sub_fields] || []
26
26
  if sub_field.in?(sub_fields)
27
27
  includes << field.to_sym
28
28
  next true
@@ -49,7 +49,7 @@ class RESTFramework::Filters::ModelQueryFilter < RESTFramework::Filters::BaseFil
49
49
  end
50
50
 
51
51
  # Filter data according to the request query parameters.
52
- def get_filtered_data(data)
52
+ def filter_data(data)
53
53
  filter_params, includes = self._get_filter_params
54
54
 
55
55
  if filter_params.any?
@@ -65,4 +65,7 @@ class RESTFramework::Filters::ModelQueryFilter < RESTFramework::Filters::BaseFil
65
65
  end
66
66
 
67
67
  # Alias for convenience.
68
- RESTFramework::ModelQueryFilter = RESTFramework::Filters::ModelQueryFilter
68
+ RESTFramework::QueryFilter = RESTFramework::Filters::QueryFilter
69
+
70
+ # TODO: Compatibility; remove in 1.0.
71
+ RESTFramework::ModelQueryFilter = RESTFramework::Filters::QueryFilter
@@ -1,7 +1,7 @@
1
1
  # Adapter for the `ransack` gem.
2
2
  class RESTFramework::Filters::RansackFilter < RESTFramework::Filters::BaseFilter
3
3
  # Filter data according to the request query parameters.
4
- def get_filtered_data(data)
4
+ def filter_data(data)
5
5
  q = @controller.request.query_parameters[@controller.ransack_query_param]
6
6
 
7
7
  if q.present?
@@ -1,5 +1,4 @@
1
- # Multi-field text searching on models.
2
- class RESTFramework::Filters::ModelSearchFilter < RESTFramework::Filters::BaseFilter
1
+ class RESTFramework::Filters::SearchFilter < RESTFramework::Filters::BaseFilter
3
2
  # Get a list of search fields for the current action.
4
3
  def _get_fields
5
4
  if search_fields = @controller.search_fields
@@ -13,7 +12,7 @@ class RESTFramework::Filters::ModelSearchFilter < RESTFramework::Filters::BaseFi
13
12
  end
14
13
 
15
14
  # Filter data according to the request query parameters.
16
- def get_filtered_data(data)
15
+ def filter_data(data)
17
16
  search = @controller.request.query_parameters[@controller.search_query_param]
18
17
 
19
18
  if search.present?
@@ -41,4 +40,7 @@ class RESTFramework::Filters::ModelSearchFilter < RESTFramework::Filters::BaseFi
41
40
  end
42
41
 
43
42
  # Alias for convenience.
44
- RESTFramework::ModelSearchFilter = RESTFramework::Filters::ModelSearchFilter
43
+ RESTFramework::SearchFilter = RESTFramework::Filters::SearchFilter
44
+
45
+ # TODO: Compatibility; remove in 1.0.
46
+ RESTFramework::ModelSearchFilter = RESTFramework::Filters::SearchFilter
@@ -3,7 +3,7 @@ end
3
3
 
4
4
  require_relative "filters/base_filter"
5
5
 
6
- require_relative "filters/model_ordering_filter"
7
- require_relative "filters/model_query_filter"
8
- require_relative "filters/model_search_filter"
6
+ require_relative "filters/ordering_filter"
7
+ require_relative "filters/query_filter"
9
8
  require_relative "filters/ransack_filter"
9
+ require_relative "filters/search_filter"
@@ -1,6 +1,6 @@
1
1
  # This module provides the common functionality for any controller mixins, a `root` action, and
2
- # the ability to route arbitrary actions with `extra_actions`. This is also where `api_response`
3
- # is defined.
2
+ # the ability to route arbitrary actions with `extra_actions`. This is also where `render_api` is
3
+ # implemented.
4
4
  module RESTFramework::Mixins::BaseControllerMixin
5
5
  RRF_BASE_CONFIG = {
6
6
  extra_actions: nil,
@@ -11,9 +11,6 @@ module RESTFramework::Mixins::BaseControllerMixin
11
11
  title: nil,
12
12
  description: nil,
13
13
  inflect_acronyms: ["ID", "IDs", "REST", "API", "APIs"].freeze,
14
- }
15
- RRF_BASE_INSTANCE_CONFIG = {
16
- filter_backends: nil,
17
14
 
18
15
  # Options related to serialization.
19
16
  rescue_unknown_format_with: :json,
@@ -21,6 +18,11 @@ module RESTFramework::Mixins::BaseControllerMixin
21
18
  serialize_to_json: true,
22
19
  serialize_to_xml: true,
23
20
 
21
+ # Custom integrations (reduces serializer performance due to method calls).
22
+ enable_action_text: false,
23
+ enable_active_storage: false,
24
+ }
25
+ RRF_BASE_INSTANCE_CONFIG = {
24
26
  # Options related to pagination.
25
27
  paginator_class: nil,
26
28
  page_size: 20,
@@ -35,12 +37,12 @@ module RESTFramework::Mixins::BaseControllerMixin
35
37
 
36
38
  # Default action for API root.
37
39
  def root
38
- api_response({message: "This is the API root."})
40
+ render_api({message: "This is the API root."})
39
41
  end
40
42
 
41
43
  module ClassMethods
42
- # Get the title of this controller. By default, this is the name of the controller class,
43
- # titleized and with any custom inflection acronyms applied.
44
+ # By default, this is the name of the controller class, titleized and with any custom inflection
45
+ # acronyms applied.
44
46
  def get_title
45
47
  return self.title || RESTFramework::Utils.inflect(
46
48
  self.name.demodulize.chomp("Controller").titleize(keep_id_suffix: true),
@@ -49,7 +51,7 @@ module RESTFramework::Mixins::BaseControllerMixin
49
51
  end
50
52
 
51
53
  # Get a label from a field/column name, titleized and inflected.
52
- def get_label(s)
54
+ def label_for(s)
53
55
  return RESTFramework::Utils.inflect(
54
56
  s.to_s.titleize(keep_id_suffix: true),
55
57
  self.inflect_acronyms,
@@ -57,7 +59,7 @@ module RESTFramework::Mixins::BaseControllerMixin
57
59
  end
58
60
 
59
61
  # Collect actions (including extra actions) metadata for this controller.
60
- def get_actions_metadata
62
+ def actions_metadata
61
63
  actions = {}
62
64
 
63
65
  # Start with builtin actions.
@@ -67,7 +69,7 @@ module RESTFramework::Mixins::BaseControllerMixin
67
69
  next unless self.method_defined?(action)
68
70
 
69
71
  actions[action] = {
70
- path: "", methods: methods, type: :builtin, metadata: {label: self.get_label(action)}
72
+ path: "", methods: methods, type: :builtin, metadata: {label: self.label_for(action)}
71
73
  }
72
74
  end
73
75
 
@@ -76,7 +78,7 @@ module RESTFramework::Mixins::BaseControllerMixin
76
78
  next unless self.method_defined?(action)
77
79
 
78
80
  actions[action] = {
79
- path: "", methods: methods, type: :builtin, metadata: {label: self.get_label(action)}
81
+ path: "", methods: methods, type: :builtin, metadata: {label: self.label_for(action)}
80
82
  }
81
83
  end
82
84
 
@@ -89,7 +91,7 @@ module RESTFramework::Mixins::BaseControllerMixin
89
91
  end
90
92
 
91
93
  # Collect member actions (including extra member actions) metadata for this controller.
92
- def get_member_actions_metadata
94
+ def member_actions_metadata
93
95
  actions = {}
94
96
 
95
97
  # Start with builtin actions.
@@ -97,7 +99,7 @@ module RESTFramework::Mixins::BaseControllerMixin
97
99
  next unless self.method_defined?(action)
98
100
 
99
101
  actions[action] = {
100
- path: "", methods: methods, type: :builtin, metadata: {label: self.get_label(action)}
102
+ path: "", methods: methods, type: :builtin, metadata: {label: self.label_for(action)}
101
103
  }
102
104
  end
103
105
 
@@ -109,8 +111,7 @@ module RESTFramework::Mixins::BaseControllerMixin
109
111
  return actions
110
112
  end
111
113
 
112
- # Get a hash of metadata to be rendered in the `OPTIONS` response. Cache the result.
113
- def get_options_metadata
114
+ def options_metadata
114
115
  return {
115
116
  title: self.get_title,
116
117
  description: self.description,
@@ -119,8 +120,8 @@ module RESTFramework::Mixins::BaseControllerMixin
119
120
  self.serialize_to_json ? "application/json" : nil,
120
121
  self.serialize_to_xml ? "application/xml" : nil,
121
122
  ].compact,
122
- actions: self.get_actions_metadata,
123
- member_actions: self.get_member_actions_metadata,
123
+ actions: self.actions_metadata,
124
+ member_actions: self.member_actions_metadata,
124
125
  }.compact
125
126
  end
126
127
 
@@ -203,47 +204,24 @@ module RESTFramework::Mixins::BaseControllerMixin
203
204
  end
204
205
  end
205
206
 
206
- # Get the configured serializer class.
207
- def get_serializer_class
208
- return nil unless serializer_class = self.serializer_class
209
-
210
- # Support dynamically resolving serializer given a symbol or string.
211
- serializer_class = serializer_class.to_s if serializer_class.is_a?(Symbol)
212
- if serializer_class.is_a?(String)
213
- serializer_class = self.class.const_get(serializer_class)
214
- end
215
-
216
- # Wrap it with an adapter if it's an active_model_serializer.
217
- if defined?(ActiveModel::Serializer) && (serializer_class < ActiveModel::Serializer)
218
- serializer_class = RESTFramework::ActiveModelSerializerAdapterFactory.for(serializer_class)
207
+ def serializer_class
208
+ # TODO: Compatibility; remove in 1.0.
209
+ if klass = self.try(:get_serializer_class)
210
+ return klass
219
211
  end
220
212
 
221
- return serializer_class
213
+ return self.class.serializer_class
222
214
  end
223
215
 
224
216
  # Serialize the given data using the `serializer_class`.
225
217
  def serialize(data, **kwargs)
226
- return self.get_serializer_class.new(data, controller: self, **kwargs).serialize
218
+ return RESTFramework::Utils.wrap_ams(self.serializer_class).new(
219
+ data, controller: self, **kwargs
220
+ ).serialize
227
221
  end
228
222
 
229
- # Get filtering backends, defaulting to no backends.
230
- def get_filter_backends
231
- return self.filter_backends || []
232
- end
233
-
234
- # Filter an arbitrary data set over all configured filter backends.
235
- def get_filtered_data(data)
236
- # Apply each filter sequentially.
237
- self.get_filter_backends.each do |filter_class|
238
- filter = filter_class.new(controller: self)
239
- data = filter.get_filtered_data(data)
240
- end
241
-
242
- return data
243
- end
244
-
245
- def get_options_metadata
246
- return self.class.get_options_metadata
223
+ def options_metadata
224
+ return self.class.options_metadata
247
225
  end
248
226
 
249
227
  def rrf_error_handler(e)
@@ -295,25 +273,25 @@ module RESTFramework::Mixins::BaseControllerMixin
295
273
  begin
296
274
  respond_to do |format|
297
275
  if payload == ""
298
- format.json { head(kwargs[:status] || :no_content) } if self.serialize_to_json
299
- format.xml { head(kwargs[:status] || :no_content) } if self.serialize_to_xml
276
+ format.json { head(kwargs[:status] || :no_content) } if self.class.serialize_to_json
277
+ format.xml { head(kwargs[:status] || :no_content) } if self.class.serialize_to_xml
300
278
  else
301
279
  format.json {
302
280
  render(json: payload, **kwargs.merge(json_kwargs))
303
- } if self.serialize_to_json
281
+ } if self.class.serialize_to_json
304
282
  format.xml {
305
283
  render(xml: payload, **kwargs.merge(xml_kwargs))
306
- } if self.serialize_to_xml
284
+ } if self.class.serialize_to_xml
307
285
  # TODO: possibly support more formats here if supported?
308
286
  end
309
287
  format.html {
310
288
  @payload = payload
311
289
  if payload == ""
312
- @json_payload = "" if self.serialize_to_json
313
- @xml_payload = "" if self.serialize_to_xml
290
+ @json_payload = "" if self.class.serialize_to_json
291
+ @xml_payload = "" if self.class.serialize_to_xml
314
292
  else
315
- @json_payload = payload.to_json if self.serialize_to_json
316
- @xml_payload = payload.to_xml if self.serialize_to_xml
293
+ @json_payload = payload.to_json if self.class.serialize_to_json
294
+ @xml_payload = payload.to_xml if self.class.serialize_to_xml
317
295
  end
318
296
  @title ||= self.class.get_title
319
297
  @description ||= self.class.description
@@ -329,7 +307,7 @@ module RESTFramework::Mixins::BaseControllerMixin
329
307
  }
330
308
  end
331
309
  rescue ActionController::UnknownFormat
332
- if !already_rescued_unknown_format && rescue_format = self.rescue_unknown_format_with
310
+ if !already_rescued_unknown_format && rescue_format = self.class.rescue_unknown_format_with
333
311
  request.format = rescue_format
334
312
  already_rescued_unknown_format = true
335
313
  retry
@@ -339,9 +317,11 @@ module RESTFramework::Mixins::BaseControllerMixin
339
317
  end
340
318
  end
341
319
 
342
- # Provide a generic `OPTIONS` response with metadata such as available actions.
320
+ # TODO: Might make this the default render method in the future.
321
+ alias_method :render_api, :api_response
322
+
343
323
  def options
344
- return api_response(self.get_options_metadata)
324
+ return api_response(self.options_metadata)
345
325
  end
346
326
  end
347
327
 
@@ -6,7 +6,7 @@ module RESTFramework::Mixins::BulkCreateModelMixin
6
6
  # While bulk update/destroy are obvious because they create new router endpoints, bulk create
7
7
  # overloads the existing collection `POST` endpoint, so we add a special key to the options
8
8
  # metadata to indicate bulk create is supported.
9
- def get_options_metadata
9
+ def options_metadata
10
10
  return super.merge({bulk_create: true})
11
11
  end
12
12