rest_framework 1.0.0 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90b0053684520db23e669f2badfea90f4bc138106f79cfece16e17fc4ef449f0
4
- data.tar.gz: 03a2d6ec4d1178fca154641ca6522df27592fa2b32b7024de76ceec827d23a8f
3
+ metadata.gz: '087da1898a00546ec0964c7f16a31ccdfdfefe6574e614764a9a3fe50dbbd89b'
4
+ data.tar.gz: a9720b7867fb57f681d786080d570161ff4ebb653015d429b331397a9962d95d
5
5
  SHA512:
6
- metadata.gz: bb23fb3f071a17bbc1aaf2f8c5b8571e47a46a8faeeeb43f851dc64d60d422b7a12ba924200e5ec4124b5b75fe06f868a8ee623c97345753f7d1dc3d5244c16d
7
- data.tar.gz: 2828fe0ca8cf5415c781f09da370dc1e92e5408b21e0d77650151aa1d9234e0a31e1e4fb8db2737166acdeba4166b79f42659086fdbd0dcf6bd80150cfb73f11
6
+ metadata.gz: cd6d3507ce2a40c4dffa147b5bd381ff5ae4b9dedc0f42d879ef96c66c9f67b07abb7de1005fe46fdaa8412aedd1d0c2c5332c17a11c407a577997b70dc3455f
7
+ data.tar.gz: d2d76d723db9f61c731aeb58d9cfd0c5c02c73bc7c75406ae835c4a24fc75f0fdfc9df24083313b2dc792b1dc7fe86eb4d8bdc32f6c15dfd60a5603ee7114cea
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0
1
+ 1.0.1
@@ -184,7 +184,7 @@
184
184
  el.setAttribute("data-bs-theme", "dark")
185
185
  })
186
186
  } else {
187
- console.log(`RRF: Unknown mode: ${mode}`)
187
+ console.log(`RRF: Unknown mode: ${realMode}`)
188
188
  }
189
189
  }
190
190
 
@@ -372,3 +372,5 @@
372
372
  .then((body) => { rrfReplaceDocument(body) })
373
373
  }
374
374
  </script>
375
+
376
+ <%= render partial: "rest_framework/head/extra" %>
@@ -5,6 +5,7 @@
5
5
  <% if @description.present? %>
6
6
  <p style="display: inline-block; margin-bottom: 0; margin-top: 1em"><%= @description %></p>
7
7
  <% end %>
8
+ <%= render partial: "rest_framework/heading/extra" %>
8
9
  </div>
9
10
  </div>
10
11
  <hr/>
File without changes
@@ -1,4 +1,5 @@
1
1
  <div style="float: right">
2
+ <%= render partial: "rest_framework/heading/actions/extra" %>
2
3
  <% if @route_groups.values[0].any? { |r| r[:matches_path] && r[:verb] == "DELETE" && r[:action] == "destroy" } %>
3
4
  <button type="button" class="btn btn-danger" onclick="rrfDelete(this)">DELETE</button>
4
5
  <% end %>
@@ -6,4 +7,4 @@
6
7
  <button type="button" class="btn btn-primary" onclick="rrfOptions(this)">OPTIONS</button>
7
8
  <% end %>
8
9
  <button type="button" class="btn btn-primary" onclick="rrfGet(this)">GET</button>
9
- </div>
10
+ </div>
File without changes
@@ -20,9 +20,9 @@
20
20
  }.compact) do |form| %>
21
21
  <% controller.get_fields.map(&:to_s).each do |f| %>
22
22
  <%
23
- # Don't provide form fields for associations or primary keys.
23
+ # Don't provide form fields for associations or read-only fields.
24
24
  cfg = controller.class.field_configuration[f]
25
- next if !cfg || cfg[:kind] == "association" || cfg[:readonly]
25
+ next if !cfg || cfg[:kind] == "association" || cfg[:read_only]
26
26
  %>
27
27
  <div class="mb-2">
28
28
  <% if cfg[:kind] == "rich_text" %>
@@ -15,6 +15,7 @@ class RESTFramework::Filters::QueryFilter < RESTFramework::Filters::BaseFilter
15
15
  null: nil,
16
16
  lt: ->(f, v) { { f => ...v } },
17
17
  # `gt` must negate `lte` because Rails doesn't support `>` with endless ranges.
18
+ # Ref: https://github.com/rails/rails/pull/47345
18
19
  gt: ->(f, v) { Not.new({ f => ..v }) },
19
20
  lte: ->(f, v) { { f => ..v } },
20
21
  gte: ->(f, v) { { f => v.. } },
@@ -22,9 +23,9 @@ class RESTFramework::Filters::QueryFilter < RESTFramework::Filters::BaseFilter
22
23
  cont: ->(f, v) { [ "#{f} LIKE ?", "%#{ActiveRecord::Base.sanitize_sql_like(v)}%" ] },
23
24
  in: ->(f, v) {
24
25
  if v.is_a?(Array)
25
- { f => v.map { |v| v == "null" ? nil : v } }
26
+ { f => v.map { |el| el == "null" ? nil : el } }
26
27
  elsif v.is_a?(String)
27
- { f => v.split(",").map { |v| v == "null" ? nil : v } }
28
+ { f => v.split(",").map { |el| el == "null" ? nil : el } }
28
29
  end
29
30
  },
30
31
  }.freeze
@@ -25,7 +25,7 @@ module RESTFramework::Mixins::BulkCreateModelMixin
25
25
  create_data = self.get_create_params(bulk_mode: true)[:_json]
26
26
 
27
27
  # Perform bulk create in a transaction.
28
- ActiveRecord::Base.transaction { self.get_create_from.create(create_data) }
28
+ ActiveRecord::Base.transaction { self.create_from.create(create_data) }
29
29
  end
30
30
  end
31
31
 
@@ -23,27 +23,30 @@ module RESTFramework::Mixins::BaseModelControllerMixin
23
23
  # Attributes for configuring record fields.
24
24
  fields: nil,
25
25
  field_config: nil,
26
+ read_only_fields: RESTFramework.config.read_only_fields,
27
+ write_only_fields: RESTFramework.config.write_only_fields,
28
+ hidden_fields: nil,
26
29
 
27
30
  # Attributes for finding records.
28
31
  find_by_fields: nil,
29
- find_by_query_param: "find_by",
32
+ find_by_query_param: "find_by".freeze,
30
33
 
31
34
  # Options for what should be included/excluded from default fields.
32
35
  exclude_associations: false,
33
36
 
34
37
  # Options for handling request body parameters.
35
38
  allowed_parameters: nil,
36
- filter_pk_from_request_body: true,
37
- exclude_body_fields: RESTFramework.config.exclude_body_fields,
38
39
 
39
40
  # Attributes for the default native serializer.
40
41
  native_serializer_config: nil,
41
42
  native_serializer_singular_config: nil,
42
43
  native_serializer_plural_config: nil,
43
- native_serializer_only_query_param: "only",
44
- native_serializer_except_query_param: "except",
44
+ native_serializer_only_query_param: "only".freeze,
45
+ native_serializer_except_query_param: "except".freeze,
46
+ native_serializer_include_query_param: "include".freeze,
47
+ native_serializer_exclude_query_param: "exclude".freeze,
45
48
  native_serializer_associations_limit: nil,
46
- native_serializer_associations_limit_query_param: "associations_limit",
49
+ native_serializer_associations_limit_query_param: "associations_limit".freeze,
47
50
  native_serializer_include_associations_count: false,
48
51
 
49
52
  # Attributes for filtering, ordering, and searching.
@@ -51,19 +54,19 @@ module RESTFramework::Mixins::BaseModelControllerMixin
51
54
  RESTFramework::QueryFilter,
52
55
  RESTFramework::OrderingFilter,
53
56
  RESTFramework::SearchFilter,
54
- ],
57
+ ].freeze,
55
58
  filter_recordset_before_find: true,
56
59
  filter_fields: nil,
57
60
  ordering_fields: nil,
58
- ordering_query_param: "ordering",
61
+ ordering_query_param: "ordering".freeze,
59
62
  ordering_no_reorder: false,
60
63
  search_fields: nil,
61
- search_query_param: "search",
64
+ search_query_param: "search".freeze,
62
65
  search_ilike: false,
63
66
  ransack_options: nil,
64
- ransack_query_param: "q",
67
+ ransack_query_param: "q".freeze,
65
68
  ransack_distinct: true,
66
- ransack_distinct_query_param: "distinct",
69
+ ransack_distinct_query_param: "distinct".freeze,
67
70
 
68
71
  # Options for association assignment.
69
72
  permit_id_assignment: true,
@@ -135,7 +138,9 @@ module RESTFramework::Mixins::BaseModelControllerMixin
135
138
  reflections = model.reflections
136
139
  attributes = model._default_attributes
137
140
  readonly_attributes = model.readonly_attributes
138
- exclude_body_fields = self.exclude_body_fields&.map(&:to_s)
141
+ read_only_fields = self.read_only_fields&.map(&:to_s)&.to_set || Set[]
142
+ write_only_fields = self.write_only_fields&.map(&:to_s)&.to_set || Set[]
143
+ hidden_fields = self.hidden_fields&.map(&:to_s)&.to_set || Set[]
139
144
  rich_text_association_names = model.reflect_on_all_associations(:has_one)
140
145
  .collect(&:name)
141
146
  .select { |n| n.to_s.start_with?("rich_text_") }
@@ -149,14 +154,29 @@ module RESTFramework::Mixins::BaseModelControllerMixin
149
154
  if model.primary_key == f
150
155
  cfg[:primary_key] = true
151
156
 
152
- unless cfg.key?(:readonly)
153
- cfg[:readonly] = true
157
+ unless cfg.key?(:read_only)
158
+ cfg[:read_only] = true
154
159
  end
155
160
  end
156
161
 
157
- # Annotate readonly attributes.
158
- if f.in?(readonly_attributes) || f.in?(exclude_body_fields)
159
- cfg[:readonly] = true
162
+ # Annotate field mutability and display properties.
163
+ cfg[:read_only] = true if f.in?(readonly_attributes) || f.in?(read_only_fields)
164
+ cfg[:write_only] = true if f.in?(write_only_fields)
165
+ cfg[:hidden] = true if f.in?(hidden_fields)
166
+
167
+ # Raise warnings on some bad combinations of properties.
168
+ if cfg[:write_only]
169
+ if cfg[:read_only]
170
+ Rails.logger.warn("RRF: `#{f}` write_only conflicts with read_only.")
171
+ end
172
+
173
+ if cfg[:hidden]
174
+ Rails.logger.warn("RRF: `#{f}` write_only implies hidden.")
175
+ end
176
+
177
+ if cfg[:hidden_from_index]
178
+ Rails.logger.warn("RRF: `#{f}` write_only implies hidden_from_index.")
179
+ end
160
180
  end
161
181
 
162
182
  # Annotate column data.
@@ -167,12 +187,12 @@ module RESTFramework::Mixins::BaseModelControllerMixin
167
187
  end
168
188
 
169
189
  # Add default values from the model's schema.
170
- if column_default = column_defaults[f] && !cfg[:default].nil?
171
- cfg[:default] ||= column_default
190
+ if cfg[:default].nil? && (column_default = column_defaults[f])
191
+ cfg[:default] = column_default
172
192
  end
173
193
 
174
194
  # Add metadata from the model's attributes hash.
175
- if attribute = attributes[f]
195
+ if attributes.key?(f) && attribute = attributes[f]
176
196
  if cfg[:default].nil? && default = attribute.value_before_type_cast
177
197
  cfg[:default] = default
178
198
  end
@@ -256,6 +276,7 @@ module RESTFramework::Mixins::BaseModelControllerMixin
256
276
  # Determine if this is just a method.
257
277
  if !cfg[:kind] && model.method_defined?(f)
258
278
  cfg[:kind] = "method"
279
+ cfg[:read_only] = true if cfg[:read_only].nil?
259
280
  end
260
281
 
261
282
  # Collect validator options into a hash on their type, while also updating `required` based
@@ -284,7 +305,7 @@ module RESTFramework::Mixins::BaseModelControllerMixin
284
305
  end
285
306
 
286
307
  next [ f, cfg ]
287
- }.to_h.with_indifferent_access
308
+ }.to_h.compact.with_indifferent_access
288
309
  end
289
310
 
290
311
  def openapi_schema
@@ -309,7 +330,7 @@ module RESTFramework::Mixins::BaseModelControllerMixin
309
330
  v[:type] = cfg[:type]
310
331
  end
311
332
 
312
- v[:readOnly] = true if cfg[:readonly]
333
+ v[:readOnly] = true if cfg[:read_only]
313
334
  v[:default] = cfg[:default] if cfg.key?(:default)
314
335
 
315
336
  if enum_variants = cfg[:enum_variants]
@@ -497,7 +518,7 @@ module RESTFramework::Mixins::BaseModelControllerMixin
497
518
  config = self.class.field_configuration[f]
498
519
 
499
520
  # ActionText Integration:
500
- if self.class.enable_action_text && reflections.key?("rich_test_#{f}")
521
+ if self.class.enable_action_text && reflections.key?("rich_text_#{f}")
501
522
  next f
502
523
  end
503
524
 
@@ -632,14 +653,12 @@ module RESTFramework::Mixins::BaseModelControllerMixin
632
653
  body_params[k].unshift(*v)
633
654
  end
634
655
 
635
- # Filter primary key, if configured.
636
- if self.class.filter_pk_from_request_body && bulk_mode != :update
637
- body_params.delete(pk)
656
+ # Filter read-only fields.
657
+ body_params.delete_if do |f, _|
658
+ cfg = self.class.field_configuration[f]
659
+ cfg && cfg[:read_only]
638
660
  end
639
661
 
640
- # Filter fields in `exclude_body_fields`.
641
- (self.class.exclude_body_fields || []).each { |f| body_params.delete(f) }
642
-
643
662
  body_params
644
663
  end
645
664
  alias_method :get_create_params, :get_body_params
@@ -701,7 +720,7 @@ module RESTFramework::Mixins::BaseModelControllerMixin
701
720
  end
702
721
 
703
722
  # Determine what collection to call `create` on.
704
- def get_create_from
723
+ def create_from
705
724
  if self.class.create_from_recordset
706
725
  # Create with any properties inherited from the recordset. We exclude any `select` clauses
707
726
  # in case model callbacks need to call `count` on this collection, which typically raises a
@@ -769,7 +788,7 @@ module RESTFramework::Mixins::CreateModelMixin
769
788
 
770
789
  # Perform the `create!` call and return the created record.
771
790
  def create!
772
- self.get_create_from.create!(self.get_create_params)
791
+ self.create_from.create!(self.get_create_params)
773
792
  end
774
793
  end
775
794
 
@@ -46,7 +46,7 @@ module ActionDispatch::Routing
46
46
  controller
47
47
  end
48
48
 
49
- # Interal interface for routing extra actions.
49
+ # Internal interface for routing extra actions.
50
50
  def _route_extra_actions(actions, &block)
51
51
  parsed_actions = RESTFramework::Utils.parse_extra_actions(actions)
52
52
 
@@ -84,13 +84,7 @@ module ActionDispatch::Routing
84
84
  unscoped = kwargs.delete(:unscoped)
85
85
 
86
86
  # Determine plural/singular resource.
87
- force_singular = kwargs.delete(:force_singular)
88
- force_plural = kwargs.delete(:force_plural)
89
- if force_singular
90
- singular = true
91
- elsif force_plural
92
- singular = false
93
- elsif !controller_class.singleton_controller.nil?
87
+ if !controller_class.singleton_controller.nil?
94
88
  singular = controller_class.singleton_controller
95
89
  else
96
90
  singular = default_singular
@@ -98,7 +92,7 @@ module ActionDispatch::Routing
98
92
  resource_method = singular ? :resource : :resources
99
93
 
100
94
  # Call either `resource` or `resources`, passing appropriate modifiers.
101
- skip = RESTFramework::Utils.get_skipped_builtin_actions(controller_class)
95
+ skip = RESTFramework::Utils.get_skipped_builtin_actions(controller_class, singular)
102
96
  public_send(resource_method, name, except: skip, **kwargs) do
103
97
  if controller_class.respond_to?(:extra_member_actions)
104
98
  member do
@@ -1,6 +1,14 @@
1
1
  # This serializer uses `.serializable_hash` to convert objects to Ruby primitives (with the
2
2
  # top-level being either an array or a hash).
3
3
  class RESTFramework::Serializers::NativeSerializer < RESTFramework::Serializers::BaseSerializer
4
+ EXTRACT_FROM_QUERY = ->(p, controller) {
5
+ return Set[] if p.blank?
6
+ (
7
+ controller.request&.query_parameters&.[](p).presence&.split(",")&.map { |x|
8
+ x.strip.presence
9
+ }&.compact || []
10
+ ).to_set
11
+ }
4
12
  class_attribute :config
5
13
  class_attribute :singular_config
6
14
  class_attribute :plural_config
@@ -26,28 +34,66 @@ class RESTFramework::Serializers::NativeSerializer < RESTFramework::Serializers:
26
34
  @model ||= @controller.class.get_model if @controller
27
35
  end
28
36
 
29
- # Get controller action, if possible.
30
- def get_action
31
- @controller&.action_name&.to_sym
37
+ def action
38
+ @action ||= @controller&.action_name&.to_sym
32
39
  end
33
40
 
34
- # Get a locally defined native serializer configuration, if one is defined.
35
- def get_local_native_serializer_config
36
- action = self.get_action
41
+ def fields
42
+ return @fields if defined?(@fields)
43
+ return nil unless base_fields = @controller&.get_fields
44
+
45
+ only_param = @controller.class.native_serializer_only_query_param
46
+ except_param = @controller.class.native_serializer_except_query_param
47
+ include_param = @controller.class.native_serializer_include_query_param
48
+ exclude_param = @controller.class.native_serializer_exclude_query_param
49
+
50
+ only = EXTRACT_FROM_QUERY.call(only_param, @controller)
51
+ except = EXTRACT_FROM_QUERY.call(except_param, @controller)
52
+ include = EXTRACT_FROM_QUERY.call(include_param, @controller)
53
+ exclude = EXTRACT_FROM_QUERY.call(exclude_param, @controller)
54
+
55
+ field_configuration = @controller.class.field_configuration
56
+ @fields = base_fields.select do |f|
57
+ cfg = field_configuration[f]
58
+
59
+ # We never serialize write-only fields.
60
+ next false if cfg[:write_only]
61
+
62
+ # We never serialize `hidden_from_index` fields for collections as this is a performance
63
+ # option.
64
+ next false if cfg[:hidden_from_index] && @many
65
+
66
+ # Explicitly excluded fields should never be serialized.
67
+ next false if f.in?(except) || f.in?(exclude)
68
+
69
+ # Hidden fields must be in `only` or `include` to be serialized; for non-hidden fields, either
70
+ # `only` must be empty, or the field must be in `only` or `include`.
71
+ if cfg[:hidden]
72
+ next true if f.in?(only) || f.in?(include)
73
+ elsif only.empty? || f.in?(only) || f.in?(include)
74
+ next true
75
+ end
37
76
 
38
- if action && self.action_config
77
+ next false
78
+ end
79
+
80
+ @fields
81
+ end
82
+
83
+ def get_local_native_serializer_config
84
+ if (action = self.action) && (cfg = action_config)
39
85
  # Index action should use :list serializer config if :index is not provided.
40
- action = :list if action == :index && !self.action_config.key?(:index)
86
+ action = :list if action == :index && !cfg.key?(:index)
41
87
 
42
- return self.action_config[action] if self.action_config[action]
88
+ return cfg[action] if cfg[action]
43
89
  end
44
90
 
45
91
  # No action_config, so try singular/plural config if explicitly instructed to via @many.
46
92
  return self.plural_config if @many == true && self.plural_config
47
93
  return self.singular_config if @many == false && self.singular_config
48
94
 
49
- # Lastly, try returning the default config, or singular/plural config in that order.
50
- self.config || self.singular_config || self.plural_config
95
+ # Lastly, try returning the default config.
96
+ self.config
51
97
  end
52
98
 
53
99
  # Get a native serializer configuration from the controller.
@@ -63,102 +109,9 @@ class RESTFramework::Serializers::NativeSerializer < RESTFramework::Serializers:
63
109
  controller_serializer || @controller.class.native_serializer_config
64
110
  end
65
111
 
66
- # Filter a single subconfig for specific keys. By default, keys from `fields` are removed from the
67
- # provided `subcfg`. There are two (mutually exclusive) options to adjust the behavior:
68
- #
69
- # `add`: Add any `fields` to the `subcfg` which aren't already in the `subcfg`.
70
- # `only`: Remove any values found in the `subcfg` not in `fields`.
71
- def self.filter_subcfg(subcfg, fields:, add: false, only: false)
72
- raise "`add` and `only` conflict with one another" if add && only
73
-
74
- # Don't process nil `subcfg`s.
75
- return subcfg unless subcfg
76
-
77
- if subcfg.is_a?(Array)
78
- subcfg = subcfg.map(&:to_sym)
79
-
80
- if add
81
- # Only add fields which are not already included.
82
- subcfg += fields - subcfg
83
- elsif only
84
- subcfg.select! { |c| c.in?(fields) }
85
- else
86
- subcfg -= fields
87
- end
88
- elsif subcfg.is_a?(Hash)
89
- subcfg = subcfg.symbolize_keys
90
-
91
- if add
92
- # Add doesn't make sense in a hash context since we wouldn't know the values.
93
- elsif only
94
- subcfg.select! { |k, _v| k.in?(fields) }
95
- else
96
- subcfg.reject! { |k, _v| k.in?(fields) }
97
- end
98
- else # Subcfg is a single element (assume string/symbol).
99
- subcfg = subcfg.to_sym
100
-
101
- if add
102
- subcfg = subcfg.in?(fields) ? fields : [ subcfg, *fields ]
103
- elsif only
104
- subcfg = subcfg.in?(fields) ? subcfg : []
105
- else
106
- subcfg = subcfg.in?(fields) ? [] : subcfg
107
- end
108
- end
109
-
110
- subcfg
111
- end
112
-
113
- # Filter out configuration properties based on the :except/:only query parameters.
114
- def filter_from_request(cfg)
115
- return cfg unless @controller
116
-
117
- except_param = @controller.class.native_serializer_except_query_param
118
- only_param = @controller.class.native_serializer_only_query_param
119
- if except_param && except = @controller.request&.query_parameters&.[](except_param).presence
120
- if except = except.split(",").map(&:strip).map(&:to_sym).presence
121
- # Filter `only`, `except` (additive), `include`, `methods`, and `serializer_methods`.
122
- if cfg[:only]
123
- cfg[:only] = self.class.filter_subcfg(cfg[:only], fields: except)
124
- elsif cfg[:except]
125
- cfg[:except] = self.class.filter_subcfg(cfg[:except], fields: except, add: true)
126
- else
127
- cfg[:except] = except
128
- end
129
-
130
- cfg[:include] = self.class.filter_subcfg(cfg[:include], fields: except)
131
- cfg[:methods] = self.class.filter_subcfg(cfg[:methods], fields: except)
132
- cfg[:serializer_methods] = self.class.filter_subcfg(
133
- cfg[:serializer_methods], fields: except
134
- )
135
- cfg[:includes_map] = self.class.filter_subcfg(cfg[:includes_map], fields: except)
136
- end
137
- elsif only_param && only = @controller.request&.query_parameters&.[](only_param).presence
138
- if only = only.split(",").map(&:strip).map(&:to_sym).presence
139
- # Filter `only`, `include`, and `methods`. Adding anything to `except` is not needed,
140
- # because any configuration there takes precedence over `only`.
141
- if cfg[:only]
142
- cfg[:only] = self.class.filter_subcfg(cfg[:only], fields: only, only: true)
143
- else
144
- cfg[:only] = only
145
- end
146
-
147
- cfg[:include] = self.class.filter_subcfg(cfg[:include], fields: only, only: true)
148
- cfg[:methods] = self.class.filter_subcfg(cfg[:methods], fields: only, only: true)
149
- cfg[:serializer_methods] = self.class.filter_subcfg(
150
- cfg[:serializer_methods], fields: only, only: true
151
- )
152
- cfg[:includes_map] = self.class.filter_subcfg(cfg[:includes_map], fields: only, only: true)
153
- end
154
- end
155
-
156
- cfg
157
- end
158
-
159
112
  # Get the associations limit from the controller.
160
- def _get_associations_limit
161
- return @_get_associations_limit if defined?(@_get_associations_limit)
113
+ def _associations_limit
114
+ return @_associations_limit if defined?(@_associations_limit)
162
115
 
163
116
  limit = @controller&.class&.native_serializer_associations_limit
164
117
 
@@ -174,11 +127,11 @@ class RESTFramework::Serializers::NativeSerializer < RESTFramework::Serializers:
174
127
  end
175
128
  end
176
129
 
177
- @_get_associations_limit = limit
130
+ @_associations_limit = limit
178
131
  end
179
132
 
180
133
  # Get a serializer configuration from the controller. `@controller` and `@model` must be set.
181
- def _get_controller_serializer_config(fields)
134
+ def _get_controller_serializer_config
182
135
  columns = []
183
136
  includes = {}
184
137
  methods = []
@@ -194,7 +147,7 @@ class RESTFramework::Serializers::NativeSerializer < RESTFramework::Serializers:
194
147
  reflections = @model.reflections
195
148
  attachment_reflections = @model.attachment_reflections
196
149
 
197
- fields.each do |f|
150
+ self.fields.each do |f|
198
151
  field_config = @controller.class.field_configuration[f]
199
152
  next if field_config[:write_only]
200
153
 
@@ -216,7 +169,7 @@ class RESTFramework::Serializers::NativeSerializer < RESTFramework::Serializers:
216
169
  if ref.collection?
217
170
  # If we need to limit the number of serialized association records, then dynamically add a
218
171
  # serializer method to do so.
219
- if limit = self._get_associations_limit
172
+ if limit = self._associations_limit
220
173
  serializer_methods[f] = f
221
174
  self.define_singleton_method(f) do |record|
222
175
  next record.send(f).limit(limit).as_json(**sub_config)
@@ -312,17 +265,17 @@ class RESTFramework::Serializers::NativeSerializer < RESTFramework::Serializers:
312
265
  end
313
266
 
314
267
  # If the config wasn't determined, build a serializer config from controller fields.
315
- if @model && fields = @controller&.get_fields
316
- return self._get_controller_serializer_config(fields.deep_dup)
268
+ if @model && self.fields
269
+ return self._get_controller_serializer_config
317
270
  end
318
271
 
319
272
  # By default, pass an empty configuration, using the default Rails serializer.
320
273
  {}
321
274
  end
322
275
 
323
- # Get a configuration passable to `serializable_hash` for the object, filtered if required.
276
+ # Get a configuration passable to `serializable_hash` for the object.
324
277
  def get_serializer_config
325
- self.filter_from_request(self.get_raw_serializer_config)
278
+ self.get_raw_serializer_config
326
279
  end
327
280
 
328
281
  # Serialize a single record and merge results of `serializer_methods`.
@@ -41,10 +41,11 @@ module RESTFramework::Utils
41
41
  }.to_h
42
42
  end
43
43
 
44
- # Get actions which should be skipped for a given controller.
45
- def self.get_skipped_builtin_actions(controller_class)
44
+ def self.get_skipped_builtin_actions(controller_class, singular)
46
45
  (
47
- RESTFramework::BUILTIN_ACTIONS.keys + RESTFramework::BUILTIN_MEMBER_ACTIONS.keys
46
+ (
47
+ RESTFramework::BUILTIN_ACTIONS.keys - (singular ? [ :index ] : [])
48
+ ) + RESTFramework::BUILTIN_MEMBER_ACTIONS.keys
48
49
  ).reject do |action|
49
50
  controller_class.method_defined?(action)
50
51
  end
@@ -154,7 +155,7 @@ module RESTFramework::Utils
154
155
 
155
156
  # Warn for any unknown keys.
156
157
  (h.keys - [ :only, :except, :include, :exclude ]).each do |k|
157
- Rails.logger.warn("RRF: Unknown key in fields hash: #{k}")
158
+ Rails.logger.warn("RRF: Unknown key in fields hash: #{k}.")
158
159
  end
159
160
 
160
161
  # We should always return strings, not symbols.
@@ -203,7 +204,7 @@ module RESTFramework::Utils
203
204
  sub_fields = [ model.primary_key ].flatten.compact
204
205
  label_fields = RESTFramework.config.label_fields
205
206
 
206
- # Preferrably find a database column to use as label.
207
+ # Preferably find a database column to use as label.
207
208
  if match = label_fields.find { |f| f.in?(model.column_names) }
208
209
  return sub_fields + [ match ]
209
210
  end