rest_framework 0.7.7 → 0.7.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 829e2b04366870f6c4a7cad1c0bfdaf62c56c7085bdb52d028e1ec87c46b12ee
4
- data.tar.gz: 739f019c64bdd79e9af321b3ccb8cd4db8c0ab13c8e7e01b116b78e9fe1a529a
3
+ metadata.gz: e5c7efedb6af2b7a589a2b3f7cedd600f9851bb4ba6be334465285f052e961ed
4
+ data.tar.gz: e14be403f25acf8e17ba54e324ec7b13e838a28b171e4866fcbb287b4f15a4dd
5
5
  SHA512:
6
- metadata.gz: 64c8bf0286fbef571f76aeeb0679041f0844fccc3ae06aea1f1e09256ebbc973e073ffc47bca6cafa1b7ff4d72e955cfe44145dfe48aa0ba7ed56cbb089eed9c
7
- data.tar.gz: 85d773111e1c1923b79181593ed963c8b5566dcb2ff35a71fa542809bf90616de7c8ff005d11d9acfd5ce78fcaa99096e4b5490beda9126712c5b6cbc588aa11
6
+ metadata.gz: 730bb926137c31d86215cb433c97ea2d5252c24d8b38f8ce78596296a30cfc3786a5b69664b927323dbf9598385ed9b5a79cb931821ee9dad9aa9e7c7d08e111
7
+ data.tar.gz: 12af341b9c75a9c63b9a48a5ca71aab3dcb521f03862a74acd595d732df1e55ee9d8f16eb34485ad8b640439c4ab28dde08db20f8e598c583c66df3a3a58d121
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.7
1
+ 0.7.8
@@ -126,15 +126,22 @@
126
126
  Routes
127
127
  </a>
128
128
  </li>
129
- <% raw_form_routes = @route_groups.values[0].select { |r|
129
+ <% @_rrf_form_routes = @route_groups.values[0].select { |r|
130
130
  r[:matches_params] && r[:verb].in?(["POST", "PUT", "PATCH"])
131
131
  } %>
132
- <% unless raw_form_routes.empty? %>
132
+ <% unless @_rrf_form_routes.empty? %>
133
133
  <li class="nav-item">
134
134
  <a class="nav-link" href="#tab-raw-form" data-bs-toggle="tab" role="tab">
135
135
  Raw Form
136
136
  </a>
137
137
  </li>
138
+ <% if RESTFramework.features[:html_forms] %>
139
+ <li class="nav-item">
140
+ <a class="nav-link" href="#tab-raw-form" data-bs-toggle="tab" role="tab">
141
+ HTML Form
142
+ </a>
143
+ </li>
144
+ <% end %>
138
145
  <% end %>
139
146
  </ul>
140
147
  </div>
@@ -142,10 +149,15 @@
142
149
  <div class="tab-pane fade show active" id="tab-routes" role="tab">
143
150
  <%= render partial: 'rest_framework/routes' %>
144
151
  </div>
145
- <% unless raw_form_routes.empty? %>
152
+ <% unless @_rrf_form_routes.empty? %>
146
153
  <div class="tab-pane fade" id="tab-raw-form" role="tab">
147
- <%= render partial: 'rest_framework/raw_form', locals: {raw_form_routes: raw_form_routes} %>
154
+ <%= render partial: 'rest_framework/raw_form' %>
148
155
  </div>
156
+ <% if RESTFramework.features[:html_forms] %>
157
+ <div class="tab-pane fade" id="tab-raw-form" role="tab">
158
+ <%= render partial: 'rest_framework/html_form' %>
159
+ </div>
160
+ <% end %>
149
161
  <% end %>
150
162
  </div>
151
163
  </div>
@@ -0,0 +1,10 @@
1
+ <div class="mb-2">
2
+ <label class="form-label w-100">Route
3
+ <select class="form-control" id="rawFormRoute">
4
+ <% @_rrf_form_routes.each do |route| %>
5
+ <% path = @route_props[:with_path_args].call(route[:route]) %>
6
+ <option value="<%= route[:verb] %>:<%= path %>"><%= route[:verb] %> <%= route[:relative_path] %></option>
7
+ <% end %>
8
+ </select>
9
+ </label>
10
+ </div>
@@ -73,8 +73,8 @@ code {
73
73
  // What to do when document loads.
74
74
  document.addEventListener("DOMContentLoaded", (event) => {
75
75
  // Pretty-print JSON.
76
- [...document.getElementsByClassName("language-json")].forEach((element, index) => {
77
- element.innerHTML = neatJSON(JSON.parse(element.innerText), {
76
+ [...document.getElementsByClassName("language-json")].forEach((el, index) => {
77
+ el.innerHTML = neatJSON(JSON.parse(el.innerText), {
78
78
  wrap: 80,
79
79
  afterComma: 1,
80
80
  afterColon: 1,
@@ -84,15 +84,25 @@ document.addEventListener("DOMContentLoaded", (event) => {
84
84
  // Then highlight it.
85
85
  hljs.highlightAll();
86
86
 
87
+ // Replace all text nodes with anchor tag links.
88
+ [...document.querySelectorAll(".rrf-copy code")].forEach((el, index) => {
89
+ el.innerHTML = rrfLinkify(el.innerHTML)
90
+ });
91
+
87
92
  // Insert copy link and callback to copy contents of `<code>` element.
88
- [...document.getElementsByClassName("rrf-copy")].forEach((element, index) => {
89
- element.insertAdjacentHTML(
93
+ [...document.querySelectorAll("rrf-copy")].forEach((el, index) => {
94
+ el.insertAdjacentHTML(
90
95
  "afterbegin",
91
96
  "<a class=\"rrf-copy-link\" onclick=\"return rrfCopyToClipboard(this)\" href=\"#\">Copy to Clipboard</a>",
92
97
  )
93
- })
98
+ });
94
99
  })
95
100
 
101
+ // Convert plain-text links to anchor tag links.
102
+ function rrfLinkify(text) {
103
+ return text.replace(/(https?:\/\/[^\s<>"]+)/g, "<a href=\"$1\" target=\"_blank\">$1</a>")
104
+ }
105
+
96
106
  // Replace the document when doing form submission (mainly to support PUT/PATCH/DELETE).
97
107
  function rrfReplaceDocument(content) {
98
108
  // Replace the document with provided content.
@@ -0,0 +1,7 @@
1
+ <div style="max-width: 60em; margin: auto">
2
+ <%= render partial: "rest_framework/form_routes" %>
3
+
4
+ <%= form_for @ do |f| %>
5
+ <%= f.file_field :picture %>
6
+ <% end %>
7
+ </div>
@@ -1,14 +1,5 @@
1
1
  <div style="max-width: 60em; margin: auto">
2
- <div class="mb-2">
3
- <label class="form-label w-100">Route
4
- <select class="form-control" id="rawFormRoute">
5
- <% raw_form_routes.each do |route| %>
6
- <% path = @route_props[:with_path_args].call(route[:route]) %>
7
- <option value="<%= route[:verb] %>:<%= path %>"><%= route[:verb] %> <%= route[:relative_path] %></option>
8
- <% end %>
9
- </select>
10
- </label>
11
- </div>
2
+ <%= render partial: "rest_framework/form_routes" %>
12
3
 
13
4
  <div class="mb-2">
14
5
  <label class="form-label w-100">Media Type
@@ -11,7 +11,6 @@ module RESTFramework::BaseControllerMixin
11
11
  exclude_body_fields: [
12
12
  :created_at, :created_by, :created_by_id, :updated_at, :updated_by, :updated_by_id
13
13
  ].freeze,
14
- accept_generic_params_as_body_params: false,
15
14
  extra_actions: nil,
16
15
  extra_member_actions: nil,
17
16
  filter_backends: nil,
@@ -15,6 +15,11 @@ module RESTFramework::BaseModelControllerMixin
15
15
  field_config: nil,
16
16
  action_fields: nil,
17
17
 
18
+ # Options for what should be included/excluded from default fields.
19
+ exclude_associations: false,
20
+ include_active_storage: false,
21
+ include_action_text: false,
22
+
18
23
  # Attributes for finding records.
19
24
  find_by_fields: nil,
20
25
  find_by_query_param: "find_by",
@@ -29,6 +34,9 @@ module RESTFramework::BaseModelControllerMixin
29
34
  native_serializer_plural_config: nil,
30
35
  native_serializer_only_query_param: "only",
31
36
  native_serializer_except_query_param: "except",
37
+ native_serializer_associations_limit: nil,
38
+ native_serializer_associations_limit_query_param: "associations_limit",
39
+ native_serializer_include_associations_count: false,
32
40
 
33
41
  # Attributes for default model filtering, ordering, and searching.
34
42
  filterset_fields: nil,
@@ -39,15 +47,16 @@ module RESTFramework::BaseModelControllerMixin
39
47
  search_query_param: "search",
40
48
  search_ilike: false,
41
49
 
50
+ # Options for association assignment.
51
+ permit_id_assignment: true,
52
+ permit_nested_attributes_assignment: true,
53
+
42
54
  # Option for `recordset.create` vs `Model.create` behavior.
43
55
  create_from_recordset: true,
44
56
 
45
57
  # Control if filtering is done before find.
46
58
  filter_recordset_before_find: true,
47
59
 
48
- # Option to exclude associations from default fields.
49
- exclude_associations: false,
50
-
51
60
  # Control if bulk operations are done in a transaction and rolled back on error, or if all bulk
52
61
  # operations are attempted and errors simply returned in the response.
53
62
  bulk_transactional: false,
@@ -91,19 +100,26 @@ module RESTFramework::BaseModelControllerMixin
91
100
  return self.get_model.human_attribute_name(s, default: super)
92
101
  end
93
102
 
94
- # Get fields without any action context. Always fallback to columns at the class level.
95
- def get_fields
96
- if self.fields.is_a?(Hash)
103
+ # Get the available fields. Returning `nil` indicates that anything should be accepted. If
104
+ # `fallback` is true, then we should fallback to this controller's model columns, or an empty
105
+ # array.
106
+ def get_fields(input_fields: nil, fallback: true)
107
+ input_fields ||= self.fields if fallback
108
+
109
+ # If fields is a hash, then parse it.
110
+ if input_fields.is_a?(Hash)
97
111
  return RESTFramework::Utils.parse_fields_hash(
98
- self.fields, self.get_model, exclude_associations: self.exclude_associations
112
+ input_fields, self.get_model, exclude_associations: self.exclude_associations
99
113
  )
114
+ elsif !input_fields && fallback
115
+ # Otherwise, if fields is nil and fallback is true, then fallback to columns.
116
+ model = self.get_model
117
+ return model ? RESTFramework::Utils.fields_for(
118
+ model, exclude_associations: self.exclude_associations
119
+ ) : []
100
120
  end
101
121
 
102
- return self.fields || (
103
- self.get_model ? RESTFramework::Utils.fields_for(
104
- self.get_model, exclude_associations: self.exclude_associations
105
- ) : []
106
- )
122
+ return input_fields
107
123
  end
108
124
 
109
125
  # Get a field's config, including defaults.
@@ -112,8 +128,12 @@ module RESTFramework::BaseModelControllerMixin
112
128
 
113
129
  # Default sub-fields if field is an association.
114
130
  if ref = self.get_model.reflections[f]
115
- model = ref.klass
116
- columns = model.columns_hash
131
+ if ref.polymorphic?
132
+ columns = {}
133
+ else
134
+ model = ref.klass
135
+ columns = model.columns_hash
136
+ end
117
137
  config[:sub_fields] ||= RESTFramework::Utils.sub_fields_for(ref)
118
138
 
119
139
  # Serialize very basic metadata about sub-fields.
@@ -193,18 +213,37 @@ module RESTFramework::BaseModelControllerMixin
193
213
  # Get association metadata.
194
214
  if ref = reflections[f]
195
215
  metadata[:kind] = "association"
216
+
217
+ # Determine if we render id/ids fields.
218
+ if self.permit_id_assignment
219
+ if ref.collection?
220
+ metadata[:id_field] = "#{f.singularize}_ids"
221
+ else
222
+ metadata[:id_field] = "#{f}_id"
223
+ end
224
+ end
225
+
226
+ # Determine if we render nested attributes options.
227
+ if self.permit_nested_attributes_assignment
228
+ if nested_opts = model.nested_attributes_options[f.to_sym].presence
229
+ nested_opts[:field] = "#{f}_attributes"
230
+ metadata[:nested_attributes_options] = nested_opts
231
+ end
232
+ end
233
+
196
234
  begin
197
235
  pk = ref.active_record_primary_key
198
236
  rescue ActiveRecord::UnknownPrimaryKey
199
237
  end
200
238
  metadata[:association] = {
201
239
  macro: ref.macro,
240
+ collection: ref.collection?,
202
241
  class_name: ref.class_name,
203
242
  foreign_key: ref.foreign_key,
204
243
  primary_key: pk,
205
244
  polymorphic: ref.polymorphic?,
206
245
  table_name: ref.table_name,
207
- options: ref.options.presence,
246
+ options: ref.options.as_json.presence,
208
247
  }.compact
209
248
  end
210
249
 
@@ -327,26 +366,10 @@ module RESTFramework::BaseModelControllerMixin
327
366
  return (action_config[action] if action) || self.class.send(generic_config_key)
328
367
  end
329
368
 
330
- # Get a list of fields for the current action. Returning `nil` indicates that anything should be
331
- # accepted unless `fallback` is true, in which case we should fallback to this controller's model
332
- # columns, or en empty array.
369
+ # Get a list of fields, taking into account the current action.
333
370
  def get_fields(fallback: false)
334
- fields = _get_specific_action_config(:action_fields, :fields)
335
-
336
- # If fields is a hash, then parse it.
337
- if fields.is_a?(Hash)
338
- return RESTFramework::Utils.parse_fields_hash(
339
- fields, self.class.get_model, exclude_associations: self.class.exclude_associations
340
- )
341
- elsif !fields && fallback
342
- # Otherwise, if fields is nil and fallback is true, then fallback to columns.
343
- model = self.class.get_model
344
- return model ? RESTFramework::Utils.fields_for(
345
- model, exclude_associations: self.class.exclude_associations
346
- ) : []
347
- end
348
-
349
- return fields
371
+ fields = self._get_specific_action_config(:action_fields, :fields)
372
+ return self.class.get_fields(input_fields: fields, fallback: fallback)
350
373
  end
351
374
 
352
375
  # Pass fields to get dynamic metadata based on which fields are available.
@@ -389,26 +412,27 @@ module RESTFramework::BaseModelControllerMixin
389
412
  # allowed parameters or fields.
390
413
  allowed_params = self.get_allowed_parameters&.map(&:to_s)
391
414
  body_params = if allowed_params
392
- data.select { |p| allowed_params.include?(p) }
415
+ data.select { |p|
416
+ p.in?(allowed_params) || (
417
+ self.class.permit_id_assignment && (
418
+ p.chomp("_id").in?(allowed_params) || p.chomp("_ids").pluralize.in?(allowed_params)
419
+ )
420
+ ) || (
421
+ self.class.permit_nested_attributes_assignment &&
422
+ p.chomp("_attributes").in?(allowed_params)
423
+
424
+ )
425
+ }
393
426
  else
394
427
  data
395
428
  end
396
429
 
397
- # Add query params in place of missing body params, if configured.
398
- if self.class.accept_generic_params_as_body_params && allowed_params
399
- (allowed_params - body_params.keys).each do |k|
400
- if value = params[k].presence
401
- body_params[k] = value
402
- end
403
- end
404
- end
405
-
406
430
  # Filter primary key if configured.
407
431
  if self.class.filter_pk_from_request_body
408
432
  body_params.delete(self.class.get_model&.primary_key)
409
433
  end
410
434
 
411
- # Filter fields in exclude_body_fields.
435
+ # Filter fields in `exclude_body_fields`.
412
436
  (self.class.exclude_body_fields || []).each { |f| body_params.delete(f) }
413
437
 
414
438
  return body_params
@@ -157,7 +157,7 @@ module ActionDispatch::Routing
157
157
  public_send(:resource, name, only: [], **kwargs) do
158
158
  # Route a root for this resource.
159
159
  if route_root_to
160
- get("", action: route_root_to)
160
+ get("", action: route_root_to, as: "")
161
161
  end
162
162
 
163
163
  collection do
@@ -192,6 +192,83 @@ class RESTFramework::NativeSerializer < RESTFramework::BaseSerializer
192
192
  return cfg
193
193
  end
194
194
 
195
+ # Get the associations limit from the controller.
196
+ def _get_associations_limit
197
+ return @_get_associations_limit if defined?(@_get_associations_limit)
198
+
199
+ limit = @controller.class.native_serializer_associations_limit
200
+
201
+ # Extract the limit from the query parameters if it's set.
202
+ if query_param = @controller.class.native_serializer_associations_limit_query_param
203
+ if @controller.request.query_parameters.key?(query_param)
204
+ query_limit = @controller.request.query_parameters[query_param].to_i
205
+ if query_limit > 0
206
+ limit = query_limit
207
+ else
208
+ limit = nil
209
+ end
210
+ end
211
+ end
212
+
213
+ return @_get_associations_limit = limit
214
+ end
215
+
216
+ # Get a serializer configuration from the controller. `@controller` and `@model` must be set.
217
+ def _get_controller_serializer_config(fields)
218
+ columns = []
219
+ includes = {}
220
+ methods = []
221
+ serializer_methods = {}
222
+ fields.each do |f|
223
+ if f.in?(@model.column_names)
224
+ columns << f
225
+ elsif ref = @model.reflections[f]
226
+ sub_columns = []
227
+ sub_methods = []
228
+ @controller.class.get_field_config(f)[:sub_fields].each do |sf|
229
+ if !ref.polymorphic? && sf.in?(ref.klass.column_names)
230
+ sub_columns << sf
231
+ else
232
+ sub_methods << sf
233
+ end
234
+ end
235
+ sub_config = {only: sub_columns, methods: sub_methods}
236
+
237
+ # Apply certain rules regarding collection associations.
238
+ if ref.collection?
239
+ # If we need to limit the number of serialized association records, then dynamically add a
240
+ # serializer method to do so.
241
+ if limit = self._get_associations_limit
242
+ method_name = "__rrf_limit_method_#{f}"
243
+ serializer_methods[method_name] = f
244
+ self.define_singleton_method(method_name) do |record|
245
+ next record.send(f).limit(limit).as_json(**sub_config)
246
+ end
247
+ else
248
+ includes[f] = sub_config
249
+ end
250
+
251
+ # If we need to include the association count, then add it here.
252
+ if @controller.class.native_serializer_include_associations_count
253
+ method_name = "__rrf_count_method_#{f}"
254
+ serializer_methods[method_name] = "#{f}.count"
255
+ self.define_singleton_method(method_name) do |record|
256
+ next record.send(f).count
257
+ end
258
+ end
259
+ else
260
+ includes[f] = sub_config
261
+ end
262
+ elsif @model.method_defined?(f)
263
+ methods << f
264
+ end
265
+ end
266
+
267
+ return {
268
+ only: columns, include: includes, methods: methods, serializer_methods: serializer_methods
269
+ }
270
+ end
271
+
195
272
  # Get the raw serializer config. Use `deep_dup` on any class mutables (array, hash, etc) to avoid
196
273
  # mutating class state.
197
274
  def _get_raw_serializer_config
@@ -206,40 +283,11 @@ class RESTFramework::NativeSerializer < RESTFramework::BaseSerializer
206
283
  end
207
284
 
208
285
  # If the config wasn't determined, build a serializer config from controller fields.
209
- if fields = @controller&.get_fields(fallback: true)
210
- fields = fields.deep_dup
211
-
212
- columns = []
213
- includes = {}
214
- methods = []
215
- if @model
216
- fields.each do |f|
217
- if f.in?(@model.column_names)
218
- columns << f
219
- elsif @model.reflections.key?(f)
220
- sub_columns = []
221
- sub_methods = []
222
- @controller.class.get_field_config(f)[:sub_fields].each do |sf|
223
- sub_model = @model.reflections[f].klass
224
- if sf.in?(sub_model.column_names)
225
- sub_columns << sf
226
- elsif sub_model.method_defined?(sf)
227
- sub_methods << sf
228
- end
229
- end
230
- includes[f] = {only: sub_columns, methods: sub_methods}
231
- elsif @model.method_defined?(f)
232
- methods << f
233
- end
234
- end
235
- else
236
- columns = fields
237
- end
238
-
239
- return {only: columns, include: includes, methods: methods}
286
+ if @model && fields = @controller&.get_fields(fallback: true)
287
+ return self._get_controller_serializer_config(fields.deep_dup)
240
288
  end
241
289
 
242
- # By default, pass an empty configuration, allowing the serialization of all columns.
290
+ # By default, pass an empty configuration, using the default Rails serializer.
243
291
  return {}
244
292
  end
245
293
 
@@ -250,14 +298,14 @@ class RESTFramework::NativeSerializer < RESTFramework::BaseSerializer
250
298
 
251
299
  # Serialize a single record and merge results of `serializer_methods`.
252
300
  def _serialize(record, config, serializer_methods)
253
- # Ensure serializer_methods is either falsy, or an array.
254
- if serializer_methods && !serializer_methods.respond_to?(:to_ary)
255
- serializer_methods = [serializer_methods]
301
+ # Ensure serializer_methods is either falsy, or a hash.
302
+ if serializer_methods && !serializer_methods.is_a?(Hash)
303
+ serializer_methods = [serializer_methods].flatten.map { |m| [m, m] }.to_h
256
304
  end
257
305
 
258
306
  # Merge serialized record with any serializer method results.
259
307
  return record.serializable_hash(config).merge(
260
- serializer_methods&.map { |m| [m.to_sym, self.send(m, record)] }.to_h,
308
+ serializer_methods&.map { |m, k| [k.to_sym, self.send(m, record)] }.to_h,
261
309
  )
262
310
  end
263
311
 
@@ -1,6 +1,6 @@
1
1
  module RESTFramework::Utils
2
2
  HTTP_METHOD_ORDERING = %w(GET POST PUT PATCH DELETE OPTIONS HEAD)
3
- LABEL_FIELDS = %w(name label login title email username)
3
+ LABEL_FIELDS = %w(name label login title email username url)
4
4
 
5
5
  # Convert `extra_actions` hash to a consistent format: `{path:, methods:, kwargs:}`, and
6
6
  # additional metadata fields.
@@ -168,8 +168,14 @@ module RESTFramework::Utils
168
168
  return model.column_names.reject { |c|
169
169
  c.in?(foreign_keys)
170
170
  } + model.reflections.map { |association, ref|
171
- if ref.macro.in?([:has_many, :has_and_belongs_to_many]) &&
172
- RESTFramework.config.large_reverse_association_tables&.include?(ref.table_name)
171
+ # Exclude certain associations (by default, active storage and action text associations).
172
+ if ref.class_name.in?(RESTFramework.config.exclude_association_classes)
173
+ next nil
174
+ end
175
+
176
+ if ref.collection? && RESTFramework.config.large_reverse_association_tables&.include?(
177
+ ref.table_name,
178
+ )
173
179
  next nil
174
180
  end
175
181
 
@@ -179,9 +185,7 @@ module RESTFramework::Utils
179
185
 
180
186
  # Get the sub-fields that may be serialized and filtered/ordered for a reflection.
181
187
  def self.sub_fields_for(ref)
182
- model = ref.klass
183
-
184
- if model
188
+ if !ref.polymorphic? && model = ref.klass
185
189
  sub_fields = [model.primary_key].flatten.compact
186
190
 
187
191
  # Preferrably find a database column to use as label.
@@ -21,6 +21,12 @@ module RESTFramework
21
21
  # Global configuration should be kept minimal, as controller-level configurations allows multiple
22
22
  # APIs to be defined to behave differently.
23
23
  class Config
24
+ DEFAULT_EXCLUDE_ASSOCIATION_CLASSES = %w(
25
+ ActionText::RichText
26
+ ActiveStorage::Attachment
27
+ ActiveStorage::Blob
28
+ ).freeze
29
+
24
30
  # Do not run `rrf_finalize` on controllers automatically using a `TracePoint` hook. This is a
25
31
  # performance option and must be global because we have to determine this before any
26
32
  # controller-specific configuration is set. If this is set to `true`, then you must manually
@@ -44,8 +50,12 @@ module RESTFramework
44
50
  # Option to disable `rescue_from` on the controller mixins.
45
51
  attr_accessor :disable_rescue_from
46
52
 
53
+ # Options to exclude certain classes from being added by default as association fields.
54
+ attr_accessor :exclude_association_classes
55
+
47
56
  def initialize
48
57
  self.show_backtrace = Rails.env.development?
58
+ self.exclude_association_classes = DEFAULT_EXCLUDE_ASSOCIATION_CLASSES
49
59
  end
50
60
  end
51
61
 
@@ -56,6 +66,12 @@ module RESTFramework
56
66
  def self.configure
57
67
  yield(self.config)
58
68
  end
69
+
70
+ def self.features
71
+ return @features ||= {
72
+ html_forms: false,
73
+ }
74
+ end
59
75
  end
60
76
 
61
77
  require_relative "rest_framework/controller_mixins"
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.7.7
4
+ version: 0.7.8
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: 2023-01-15 00:00:00.000000000 Z
11
+ date: 2023-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -35,7 +35,9 @@ files:
35
35
  - README.md
36
36
  - VERSION
37
37
  - app/views/layouts/rest_framework.html.erb
38
+ - app/views/rest_framework/_form_routes.html.erb
38
39
  - app/views/rest_framework/_head.html.erb
40
+ - app/views/rest_framework/_html_form.html.erb
39
41
  - app/views/rest_framework/_raw_form.html.erb
40
42
  - app/views/rest_framework/_route.html.erb
41
43
  - app/views/rest_framework/_routes.html.erb