rest_framework 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,34 +13,35 @@ class RESTFramework::Paginators::PageNumberPaginator < RESTFramework::Paginators
13
13
  end
14
14
 
15
15
  def _page_size
16
- page_size = nil
16
+ page_size = 1
17
17
 
18
18
  # Get from context, if allowed.
19
- if @controller.page_size_query_param
20
- if page_size = @controller.params[@controller.page_size_query_param].presence
19
+ if param = @controller.class.page_size_query_param
20
+ if page_size = @controller.params[param].presence
21
21
  page_size = page_size.to_i
22
22
  end
23
23
  end
24
24
 
25
25
  # Otherwise, get from config.
26
- if !page_size && @controller.page_size
27
- page_size = @controller.page_size
26
+ if !page_size && @controller.class.page_size
27
+ page_size = @controller.class.page_size.to_i
28
28
  end
29
29
 
30
30
  # Ensure we don't exceed the max page size.
31
- if @controller.max_page_size && page_size > @controller.max_page_size
32
- page_size = @controller.max_page_size
31
+ max_page_size = @controller.class.max_page_size&.to_i
32
+ if max_page_size && page_size > max_page_size
33
+ page_size = max_page_size
33
34
  end
34
35
 
35
36
  # Ensure we return at least 1.
36
- return page_size.zero? ? 1 : page_size
37
+ return [page_size, 1].max
37
38
  end
38
39
 
39
40
  # Get the page and return it so the caller can serialize it.
40
41
  def get_page(page_number=nil)
41
42
  # If page number isn't provided, infer from the params or use 1 as a fallback value.
42
43
  unless page_number
43
- page_number = @controller&.params&.[](@controller.page_query_param&.to_sym)
44
+ page_number = @controller&.params&.[](@controller.class.page_query_param&.to_sym)
44
45
  if page_number.blank?
45
46
  page_number = 1
46
47
  else
@@ -57,9 +58,9 @@ class RESTFramework::Paginators::PageNumberPaginator < RESTFramework::Paginators
57
58
  return @data.limit(@page_size).offset(page_index * @page_size)
58
59
  end
59
60
 
60
- # Wrap the serialized page with appropriate metadata. TODO: include links.
61
+ # Wrap the serialized page with appropriate metadata.
61
62
  def get_paginated_response(serialized_page)
62
- page_query_param = @controller.page_query_param
63
+ page_query_param = @controller.class.page_query_param
63
64
  base_params = @controller.params.to_unsafe_h
64
65
  next_url = if @page_number < @total_pages
65
66
  @controller.url_for({**base_params, page_query_param => @page_number + 1})
@@ -27,7 +27,17 @@ module ActionDispatch::Routing
27
27
  controller = mod.const_get(name)
28
28
  rescue NameError
29
29
  if fallback_reverse_pluralization
30
- controller = mod.const_get(name_reverse)
30
+ reraise = false
31
+
32
+ begin
33
+ controller = mod.const_get(name_reverse)
34
+ rescue
35
+ reraise = true
36
+ end
37
+
38
+ if reraise
39
+ raise
40
+ end
31
41
  else
32
42
  raise
33
43
  end
@@ -55,12 +55,12 @@ class RESTFramework::Serializers::NativeSerializer < RESTFramework::Serializers:
55
55
  return nil unless @controller
56
56
 
57
57
  if @many == true
58
- controller_serializer = @controller.try(:native_serializer_plural_config)
58
+ controller_serializer = @controller.class.native_serializer_plural_config
59
59
  elsif @many == false
60
- controller_serializer = @controller.try(:native_serializer_singular_config)
60
+ controller_serializer = @controller.class.native_serializer_singular_config
61
61
  end
62
62
 
63
- return controller_serializer || @controller.try(:native_serializer_config)
63
+ return controller_serializer || @controller.class.native_serializer_config
64
64
  end
65
65
 
66
66
  # Filter a single subconfig for specific keys. By default, keys from `fields` are removed from the
@@ -114,8 +114,8 @@ class RESTFramework::Serializers::NativeSerializer < RESTFramework::Serializers:
114
114
  def filter_from_request(cfg)
115
115
  return cfg unless @controller
116
116
 
117
- except_param = @controller.try(:native_serializer_except_query_param)
118
- only_param = @controller.try(:native_serializer_only_query_param)
117
+ except_param = @controller.class.native_serializer_except_query_param
118
+ only_param = @controller.class.native_serializer_only_query_param
119
119
  if except_param && except = @controller.request&.query_parameters&.[](except_param).presence
120
120
  if except = except.split(",").map(&:strip).map(&:to_sym).presence
121
121
  # Filter `only`, `except` (additive), `include`, `methods`, and `serializer_methods`.
@@ -160,10 +160,10 @@ class RESTFramework::Serializers::NativeSerializer < RESTFramework::Serializers:
160
160
  def _get_associations_limit
161
161
  return @_get_associations_limit if defined?(@_get_associations_limit)
162
162
 
163
- limit = @controller&.native_serializer_associations_limit
163
+ limit = @controller&.class&.native_serializer_associations_limit
164
164
 
165
165
  # Extract the limit from the query parameters if it's set.
166
- if query_param = @controller&.native_serializer_associations_limit_query_param
166
+ if query_param = @controller&.class&.native_serializer_associations_limit_query_param
167
167
  if @controller.request.query_parameters.key?(query_param)
168
168
  query_limit = @controller.request.query_parameters[query_param].to_i
169
169
  if query_limit > 0
@@ -195,7 +195,7 @@ class RESTFramework::Serializers::NativeSerializer < RESTFramework::Serializers:
195
195
  attachment_reflections = @model.attachment_reflections
196
196
 
197
197
  fields.each do |f|
198
- field_config = @controller.class.field_config_for(f)
198
+ field_config = @controller.class.field_configuration[f]
199
199
  next if field_config[:write_only]
200
200
 
201
201
  if f.in?(column_names)
@@ -226,7 +226,7 @@ class RESTFramework::Serializers::NativeSerializer < RESTFramework::Serializers:
226
226
  #
227
227
  # # Even though we use a serializer method, if the count will later be added, then put
228
228
  # # this field into the includes_map.
229
- # if @controller.native_serializer_include_associations_count
229
+ # if @controller.class.native_serializer_include_associations_count
230
230
  # includes_map[f] = f.to_sym
231
231
  # end
232
232
  else
@@ -235,7 +235,7 @@ class RESTFramework::Serializers::NativeSerializer < RESTFramework::Serializers:
235
235
  end
236
236
 
237
237
  # If we need to include the association count, then add it here.
238
- if @controller.native_serializer_include_associations_count
238
+ if @controller.class.native_serializer_include_associations_count
239
239
  method_name = "#{f}.count"
240
240
  serializer_methods[method_name] = method_name
241
241
  self.define_singleton_method(method_name) do |record|
@@ -1,14 +1,12 @@
1
1
  module RESTFramework::Utils
2
2
  HTTP_VERB_ORDERING = %w(GET POST PUT PATCH DELETE OPTIONS HEAD)
3
3
 
4
- # Convert `extra_actions` hash to a consistent format: `{path:, methods:, kwargs:}`, and
5
- # additional metadata fields.
4
+ # Convert `extra_actions` hash to a consistent format: `{path:, methods:, kwargs:}`.
6
5
  #
7
6
  # If a controller is provided, labels will be added to any metadata fields.
8
7
  def self.parse_extra_actions(extra_actions, controller: nil)
9
8
  return (extra_actions || {}).map { |k, v|
10
9
  path = k
11
- metadata = {}
12
10
 
13
11
  # Convert structure to path/methods/kwargs.
14
12
  if v.is_a?(Hash) # Allow kwargs to be used to define path differently from the key.
@@ -19,11 +17,9 @@ module RESTFramework::Utils
19
17
  methods = v.delete(:method)
20
18
  end
21
19
 
22
- # First, remove the route metadata.
23
- metadata = v.delete(:metadata) || {}
24
-
25
- # Add label to fields.
26
- if controller && metadata[:fields]
20
+ # Add label to metadata fields, if any exist.
21
+ metadata = v[:metadata]
22
+ if controller && metadata&.key?(:fields)
27
23
  metadata[:fields] = metadata[:fields].map { |f|
28
24
  [f, {}]
29
25
  }.to_h if metadata[:fields].is_a?(Array)
@@ -56,8 +52,6 @@ module RESTFramework::Utils
56
52
  path: path,
57
53
  methods: methods,
58
54
  kwargs: kwargs,
59
- type: :extra,
60
- metadata: metadata.presence,
61
55
  }.compact,
62
56
  ]
63
57
  }.to_h
@@ -91,25 +85,28 @@ module RESTFramework::Utils
91
85
  current_levels = current_path.count("/")
92
86
  current_comparable_path = %r{^#{Regexp.quote(self.comparable_path(current_path))}(/|$)}
93
87
 
94
- # Add helpful properties of the current route.
95
- path_args = current_route.required_parts.map { |n| request.path_parameters[n] }
96
- route_props = {
97
- with_path_args: ->(r) {
98
- r.format(r.required_parts.each_with_index.map { |p, i| [p, path_args[i]] }.to_h)
99
- },
100
- }
88
+ # Get current route path parameters.
89
+ path_params = current_route.required_parts.map { |n| request.path_parameters[n] }
101
90
 
102
91
  # Return routes that match our current route subdomain/pattern, grouped by controller. We
103
92
  # precompute certain properties of the route for performance.
104
- return route_props, application_routes.routes.select { |r|
93
+ return application_routes.routes.select { |r|
105
94
  # We `select` first to avoid unnecessarily calculating metadata for routes we don't even want
106
95
  # to show.
107
96
  (r.defaults[:subdomain].blank? || r.defaults[:subdomain] == request.subdomain) &&
108
- current_comparable_path.match?(self.comparable_path(r.path.spec.to_s)) &&
109
- r.defaults[:controller].present? &&
110
- r.defaults[:action].present?
97
+ current_comparable_path.match?(self.comparable_path(r.path.spec.to_s)) &&
98
+ r.defaults[:controller].present? &&
99
+ r.defaults[:action].present?
111
100
  }.map { |r|
112
101
  path = r.path.spec.to_s.gsub("(.:format)", "")
102
+
103
+ # Starts at the number of levels in current path, and removes the `(.:format)` at the end.
104
+ relative_path = path.split("/")[current_levels..]&.join("/").presence || "/"
105
+
106
+ # This path is what would need to be concatenated onto the current path to get to the
107
+ # destination path.
108
+ concat_path = relative_path.gsub(/^[^\/]*/, "").presence || "/"
109
+
113
110
  levels = path.count("/")
114
111
  matches_path = current_path == path
115
112
  matches_params = r.required_parts.length == current_route.required_parts.length
@@ -118,8 +115,11 @@ module RESTFramework::Utils
118
115
  route: r,
119
116
  verb: r.verb,
120
117
  path: path,
121
- # Starts at the number of levels in current path, and removes the `(.:format)` at the end.
122
- relative_path: path.split("/")[current_levels..]&.join("/").presence || "/",
118
+ path_with_params: r.format(
119
+ r.required_parts.each_with_index.map { |p, i| [p, path_params[i]] }.to_h,
120
+ ),
121
+ relative_path: relative_path,
122
+ concat_path: concat_path,
123
123
  controller: r.defaults[:controller].presence,
124
124
  action: r.defaults[:action].presence,
125
125
  matches_path: matches_path,
@@ -234,7 +234,7 @@ module RESTFramework::Utils
234
234
  end
235
235
 
236
236
  # Get a field's id/ids variation.
237
- def self.get_id_field(field, reflection)
237
+ def self.id_field_for(field, reflection)
238
238
  if reflection.collection?
239
239
  return "#{field.singularize}_ids"
240
240
  elsif reflection.belongs_to?
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.10.0
4
+ version: 0.11.0
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: 2024-12-23 00:00:00.000000000 Z
11
+ date: 2024-12-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -54,7 +54,7 @@ files:
54
54
  - lib/rest_framework/engine.rb
55
55
  - lib/rest_framework/errors.rb
56
56
  - lib/rest_framework/errors/base_error.rb
57
- - lib/rest_framework/errors/nil_passed_to_api_response_error.rb
57
+ - lib/rest_framework/errors/nil_passed_to_render_api_error.rb
58
58
  - lib/rest_framework/errors/unknown_model_error.rb
59
59
  - lib/rest_framework/filters.rb
60
60
  - lib/rest_framework/filters/base_filter.rb