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.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/VERSION +1 -1
- data/app/views/rest_framework/routes_and_forms/_html_form.html.erb +6 -6
- data/app/views/rest_framework/routes_and_forms/_raw_form.html.erb +1 -1
- data/app/views/rest_framework/routes_and_forms/routes/_route.html.erb +1 -1
- data/lib/rest_framework/errors/{nil_passed_to_api_response_error.rb → nil_passed_to_render_api_error.rb} +3 -3
- data/lib/rest_framework/errors.rb +1 -1
- data/lib/rest_framework/filters/ordering_filter.rb +4 -7
- data/lib/rest_framework/filters/query_filter.rb +1 -4
- data/lib/rest_framework/filters/ransack_filter.rb +4 -4
- data/lib/rest_framework/filters/search_filter.rb +3 -6
- data/lib/rest_framework/mixins/base_controller_mixin.rb +92 -100
- data/lib/rest_framework/mixins/bulk_model_controller_mixin.rb +7 -7
- data/lib/rest_framework/mixins/model_controller_mixin.rb +215 -190
- data/lib/rest_framework/paginators/page_number_paginator.rb +12 -11
- data/lib/rest_framework/routers.rb +11 -1
- data/lib/rest_framework/serializers/native_serializer.rb +10 -10
- data/lib/rest_framework/utils.rb +24 -24
- metadata +3 -3
@@ -13,34 +13,35 @@ class RESTFramework::Paginators::PageNumberPaginator < RESTFramework::Paginators
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def _page_size
|
16
|
-
page_size =
|
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[
|
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
|
-
|
32
|
-
|
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
|
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.
|
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
|
-
|
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.
|
58
|
+
controller_serializer = @controller.class.native_serializer_plural_config
|
59
59
|
elsif @many == false
|
60
|
-
controller_serializer = @controller.
|
60
|
+
controller_serializer = @controller.class.native_serializer_singular_config
|
61
61
|
end
|
62
62
|
|
63
|
-
return controller_serializer || @controller.
|
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.
|
118
|
-
only_param = @controller.
|
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.
|
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|
|
data/lib/rest_framework/utils.rb
CHANGED
@@ -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:}
|
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
|
-
#
|
23
|
-
metadata = v
|
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
|
-
#
|
95
|
-
|
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
|
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
|
-
|
109
|
-
|
110
|
-
|
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
|
-
|
122
|
-
|
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.
|
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.
|
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-
|
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/
|
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
|