rest_framework 0.8.3 → 0.8.5
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 +4 -4
- data/VERSION +1 -1
- data/lib/rest_framework/controller_mixins/base.rb +1 -1
- data/lib/rest_framework/controller_mixins/models.rb +7 -4
- data/lib/rest_framework/filters.rb +32 -16
- data/lib/rest_framework/utils.rb +3 -3
- data/lib/rest_framework.rb +12 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8bbc760b6f4694137002e90cf81453f1e07cd86ffd69a8318646db54b31144b6
|
4
|
+
data.tar.gz: 41ce57cbee20b11453d332e03fbdf54118ba7b7f1ceeaa5b3b02d118675c6a3d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59fdf66ab6dd1c457a9551ed1a9ab0724fc2079be1c28ec2ebc08eada94390fe66e3722ab278a6d5fba7c55aed9a4a75dca0e3ea498cd183832d70553f6db9d7
|
7
|
+
data.tar.gz: e3e2f6b3c3ff29e03d8c9c3a058996bea5de44acfae449a065278a000b98b22b536892dd2d4e3e46b65d9c94cee85aedd1f9928e697e39afd4c491b33ae33504
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.8.
|
1
|
+
0.8.5
|
@@ -112,7 +112,7 @@ module RESTFramework::BaseControllerMixin
|
|
112
112
|
|
113
113
|
# Get a hash of metadata to be rendered in the `OPTIONS` response. Cache the result.
|
114
114
|
def get_options_metadata
|
115
|
-
return
|
115
|
+
return {
|
116
116
|
title: self.get_title,
|
117
117
|
description: self.description,
|
118
118
|
renders: [
|
@@ -285,9 +285,9 @@ module RESTFramework::BaseModelControllerMixin
|
|
285
285
|
}.to_h
|
286
286
|
end
|
287
287
|
|
288
|
-
# Get a hash of metadata to be rendered in the `OPTIONS` response.
|
288
|
+
# Get a hash of metadata to be rendered in the `OPTIONS` response.
|
289
289
|
def get_options_metadata
|
290
|
-
return super
|
290
|
+
return super.merge(
|
291
291
|
{
|
292
292
|
fields: self.get_fields_metadata,
|
293
293
|
callbacks: self._process_action_callbacks.as_json,
|
@@ -439,10 +439,13 @@ module RESTFramework::BaseModelControllerMixin
|
|
439
439
|
return super || RESTFramework::NativeSerializer
|
440
440
|
end
|
441
441
|
|
442
|
-
# Get filtering backends, defaulting to using `ModelFilter` and
|
442
|
+
# Get filtering backends, defaulting to using `ModelFilter`, `ModelOrderingFilter`, and
|
443
|
+
# `ModelSearchFilter`.
|
443
444
|
def get_filter_backends
|
444
445
|
return self.class.filter_backends || [
|
445
|
-
RESTFramework::ModelFilter,
|
446
|
+
RESTFramework::ModelFilter,
|
447
|
+
RESTFramework::ModelOrderingFilter,
|
448
|
+
RESTFramework::ModelSearchFilter,
|
446
449
|
]
|
447
450
|
end
|
448
451
|
|
@@ -14,7 +14,7 @@ class RESTFramework::ModelFilter < RESTFramework::BaseFilter
|
|
14
14
|
# Get a list of filterset fields for the current action. Fallback to columns because we don't want
|
15
15
|
# to try filtering by any query parameter because that could clash with other query parameters.
|
16
16
|
def _get_fields
|
17
|
-
return
|
17
|
+
return (
|
18
18
|
@controller.class.filterset_fields || @controller.get_fields(fallback: true)
|
19
19
|
).map(&:to_s)
|
20
20
|
end
|
@@ -69,9 +69,7 @@ class RESTFramework::ModelOrderingFilter < RESTFramework::BaseFilter
|
|
69
69
|
# Get a list of ordering fields for the current action. Do not fallback to columns in case the
|
70
70
|
# user wants to order by a virtual column.
|
71
71
|
def _get_fields
|
72
|
-
return @
|
73
|
-
@controller.class.ordering_fields || @controller.get_fields
|
74
|
-
)&.map(&:to_s)
|
72
|
+
return (@controller.class.ordering_fields || @controller.get_fields)&.map(&:to_s)
|
75
73
|
end
|
76
74
|
|
77
75
|
# Convert ordering string to an ordering configuration.
|
@@ -117,25 +115,43 @@ end
|
|
117
115
|
|
118
116
|
# Multi-field text searching on models.
|
119
117
|
class RESTFramework::ModelSearchFilter < RESTFramework::BaseFilter
|
120
|
-
|
121
|
-
|
118
|
+
DEFAULT_SEARCH_COLUMNS = %w[name email title description note]
|
119
|
+
|
120
|
+
# Get a list of search fields for the current action. Fallback to columns but only grab a few
|
121
|
+
# common string-like columns by default.
|
122
122
|
def _get_fields
|
123
|
-
|
123
|
+
if search_fields = @controller.class.search_fields
|
124
|
+
return search_fields
|
125
|
+
end
|
126
|
+
|
127
|
+
columns = @controller.class.get_model.columns_hash.keys
|
128
|
+
return @controller.get_fields(fallback: true).select { |f|
|
129
|
+
f.in?(DEFAULT_SEARCH_COLUMNS) && f.in?(columns)
|
130
|
+
}
|
124
131
|
end
|
125
132
|
|
126
133
|
# Filter data according to the request query parameters.
|
127
134
|
def get_filtered_data(data)
|
128
|
-
fields = self._get_fields
|
129
135
|
search = @controller.request.query_parameters[@controller.class.search_query_param]
|
130
136
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
"
|
136
|
-
|
137
|
-
|
138
|
-
|
137
|
+
if search.present?
|
138
|
+
if fields = self._get_fields.presence
|
139
|
+
# MySQL doesn't support casting to VARCHAR, so we need to use CHAR instead.
|
140
|
+
data_type = if data.connection.adapter_name =~ /mysql/i
|
141
|
+
"CHAR"
|
142
|
+
else
|
143
|
+
# Sufficient for both PostgreSQL and SQLite.
|
144
|
+
"VARCHAR"
|
145
|
+
end
|
146
|
+
|
147
|
+
# Ensure we pass user input as arguments to prevent SQL injection.
|
148
|
+
return data.where(
|
149
|
+
fields.map { |f|
|
150
|
+
"CAST(#{f} AS #{data_type}) #{@controller.class.search_ilike ? "ILIKE" : "LIKE"} ?"
|
151
|
+
}.join(" OR "),
|
152
|
+
*(["%#{search}%"] * fields.length),
|
153
|
+
)
|
154
|
+
end
|
139
155
|
end
|
140
156
|
|
141
157
|
return data
|
data/lib/rest_framework/utils.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
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 url)
|
4
3
|
|
5
4
|
# Convert `extra_actions` hash to a consistent format: `{path:, methods:, kwargs:}`, and
|
6
5
|
# additional metadata fields.
|
@@ -186,14 +185,15 @@ module RESTFramework::Utils
|
|
186
185
|
def self.sub_fields_for(ref)
|
187
186
|
if !ref.polymorphic? && model = ref.klass
|
188
187
|
sub_fields = [model.primary_key].flatten.compact
|
188
|
+
label_fields = RESTFramework.config.label_fields
|
189
189
|
|
190
190
|
# Preferrably find a database column to use as label.
|
191
|
-
if match =
|
191
|
+
if match = label_fields.find { |f| f.in?(model.column_names) }
|
192
192
|
return sub_fields + [match]
|
193
193
|
end
|
194
194
|
|
195
195
|
# Otherwise, find a method.
|
196
|
-
if match =
|
196
|
+
if match = label_fields.find { |f| model.method_defined?(f) }
|
197
197
|
return sub_fields + [match]
|
198
198
|
end
|
199
199
|
|
data/lib/rest_framework.rb
CHANGED
@@ -26,6 +26,8 @@ module RESTFramework
|
|
26
26
|
ActiveStorage::Attachment
|
27
27
|
ActiveStorage::Blob
|
28
28
|
).freeze
|
29
|
+
DEFAULT_LABEL_FIELDS = %w(name label login title email username url).freeze
|
30
|
+
DEFAULT_SEARCH_COLUMNS = DEFAULT_LABEL_FIELDS + %w(description note).freeze
|
29
31
|
|
30
32
|
# Do not run `rrf_finalize` on controllers automatically using a `TracePoint` hook. This is a
|
31
33
|
# performance option and must be global because we have to determine this before any
|
@@ -47,15 +49,23 @@ module RESTFramework
|
|
47
49
|
# Whether the backtrace should be shown in rescued errors.
|
48
50
|
attr_accessor :show_backtrace
|
49
51
|
|
50
|
-
#
|
52
|
+
# Disable `rescue_from` on the controller mixins.
|
51
53
|
attr_accessor :disable_rescue_from
|
52
54
|
|
53
|
-
#
|
55
|
+
# Exclude certain classes from being added by default as association fields.
|
54
56
|
attr_accessor :exclude_association_classes
|
55
57
|
|
58
|
+
# The default label fields to use when generating labels for `has_many` associations.
|
59
|
+
attr_accessor :label_fields
|
60
|
+
|
61
|
+
# The default search columns to use when generating search filters.
|
62
|
+
attr_accessor :search_columns
|
63
|
+
|
56
64
|
def initialize
|
57
65
|
self.show_backtrace = Rails.env.development?
|
58
66
|
self.exclude_association_classes = DEFAULT_EXCLUDE_ASSOCIATION_CLASSES
|
67
|
+
self.label_fields = DEFAULT_LABEL_FIELDS
|
68
|
+
self.search_columns = DEFAULT_SEARCH_COLUMNS
|
59
69
|
end
|
60
70
|
end
|
61
71
|
|
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.8.
|
4
|
+
version: 0.8.5
|
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-
|
11
|
+
date: 2023-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|