jpie 2.1.2 → 2.1.4
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/Gemfile.lock +1 -1
- data/lib/json_api/controllers/concerns/relationships/sorting.rb +3 -5
- data/lib/json_api/controllers/concerns/resource_actions/filter_validation.rb +5 -16
- data/lib/json_api/controllers/concerns/resource_actions/include_preloading.rb +1 -0
- data/lib/json_api/support/concerns/condition_building.rb +13 -2
- data/lib/json_api/support/concerns/nested_filters.rb +2 -30
- data/lib/json_api/support/concerns/regular_filters.rb +1 -29
- data/lib/json_api/support/concerns/sorting.rb +3 -5
- data/lib/json_api/support/sort_value_comparison.rb +26 -0
- data/lib/json_api/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 23a1e7f0dd69ee73d5a8f684ac39005fca7081222517086e5f708ffd8ca7815b
|
|
4
|
+
data.tar.gz: c2ae85e3db1522db8891a6ec0cba3956af94993e1658bdbe0e2a517af9954740
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2fa70259c383d4f694f0071384f3b9a8f6f46e3b26765644bbaa45045c4be86454ba9a934b1ec79f9571f1846ae54cdd3b61ec439ba9c000155ee74feaeef1f8
|
|
7
|
+
data.tar.gz: 3b00c7a05a52bc30b81109a09e95c65cdd6602facba9e8c92b0011ca3a6b3cc0eecb4da2b15704a5d2df03325b70f3aed474988034cefdd7111089815eab8e39
|
data/Gemfile.lock
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "json_api/support/sort_value_comparison"
|
|
4
|
+
|
|
3
5
|
module JSONAPI
|
|
4
6
|
module Relationships
|
|
5
7
|
module Sorting
|
|
@@ -75,11 +77,7 @@ module JSONAPI
|
|
|
75
77
|
end
|
|
76
78
|
|
|
77
79
|
def compare_values(value_a, value_b)
|
|
78
|
-
|
|
79
|
-
return -1 if value_a.nil?
|
|
80
|
-
return 1 if value_b.nil?
|
|
81
|
-
|
|
82
|
-
value_a <=> value_b
|
|
80
|
+
JSONAPI::Support::SortValueComparison.compare(value_a, value_b)
|
|
83
81
|
end
|
|
84
82
|
|
|
85
83
|
def validate_sort_param
|
|
@@ -21,26 +21,15 @@ module JSONAPI
|
|
|
21
21
|
check_filter_parts(parts, @resource_class, model_class)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def check_filter_parts(parts, res_cls, mod_cls
|
|
24
|
+
def check_filter_parts(parts, res_cls, mod_cls)
|
|
25
25
|
return false if parts.empty?
|
|
26
|
-
return single_filter_valid?(parts.first, res_cls
|
|
26
|
+
return single_filter_valid?(parts.first, res_cls) if parts.length == 1
|
|
27
27
|
|
|
28
28
|
check_nested_filter(parts, res_cls, mod_cls)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
def single_filter_valid?(name, res_cls
|
|
32
|
-
|
|
33
|
-
return false unless allow_related
|
|
34
|
-
|
|
35
|
-
related_column_valid?(name, mod_cls)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def related_column_valid?(name, mod_cls)
|
|
39
|
-
col = parse_column_filter(name)
|
|
40
|
-
return true if col && mod_cls.column_for_attribute(col[:column])
|
|
41
|
-
return true if mod_cls.column_names.include?(name)
|
|
42
|
-
|
|
43
|
-
mod_cls.respond_to?(name.to_sym)
|
|
31
|
+
def single_filter_valid?(name, res_cls)
|
|
32
|
+
res_cls.permitted_filters.map(&:to_s).include?(name)
|
|
44
33
|
end
|
|
45
34
|
|
|
46
35
|
def check_nested_filter(parts, res_cls, mod_cls)
|
|
@@ -59,7 +48,7 @@ module JSONAPI
|
|
|
59
48
|
rel_res = JSONAPI::Resource.resource_for_model(rel_mod)
|
|
60
49
|
return false unless rel_res
|
|
61
50
|
|
|
62
|
-
check_filter_parts(parts, rel_res, rel_mod
|
|
51
|
+
check_filter_parts(parts, rel_res, rel_mod)
|
|
63
52
|
end
|
|
64
53
|
|
|
65
54
|
def filter_rel_allowed?(res_cls, rel)
|
|
@@ -19,6 +19,7 @@ module JSONAPI
|
|
|
19
19
|
def scope_with_includes(scope)
|
|
20
20
|
includes = parse_include_param
|
|
21
21
|
return scope unless includes.any?
|
|
22
|
+
return scope if scope.is_a?(Array)
|
|
22
23
|
|
|
23
24
|
inc_hash = includes_to_hash(includes)
|
|
24
25
|
hash_contains_polymorphic?(inc_hash, model_class) ? scope.preload(inc_hash) : scope.includes(inc_hash)
|
|
@@ -13,8 +13,6 @@ module JSONAPI
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def normalize_filter_value_for_model(model, column, raw_value)
|
|
16
|
-
return nil unless column
|
|
17
|
-
|
|
18
16
|
value = raw_value.is_a?(Array) ? raw_value.first : raw_value
|
|
19
17
|
return nil if value.nil?
|
|
20
18
|
|
|
@@ -39,6 +37,19 @@ module JSONAPI
|
|
|
39
37
|
lower_attr.matches(pattern.downcase)
|
|
40
38
|
end
|
|
41
39
|
|
|
40
|
+
def apply_column_filter(scope, model, filter_name, raw_value)
|
|
41
|
+
column_filter = parse_column_filter(filter_name)
|
|
42
|
+
return nil unless column_filter
|
|
43
|
+
return nil unless model.column_names.include?(column_filter[:column])
|
|
44
|
+
|
|
45
|
+
column = model.column_for_attribute(column_filter[:column])
|
|
46
|
+
value = normalize_filter_value_for_model(model, column, raw_value)
|
|
47
|
+
return nil unless value
|
|
48
|
+
|
|
49
|
+
condition = build_condition(model, column, value, column_filter[:operator])
|
|
50
|
+
condition ? apply_condition(scope, condition) : nil
|
|
51
|
+
end
|
|
52
|
+
|
|
42
53
|
def apply_condition(scope, condition)
|
|
43
54
|
scope.where(condition)
|
|
44
55
|
end
|
|
@@ -81,40 +81,12 @@ module JSONAPI
|
|
|
81
81
|
def apply_filter_on_model(scope, target_model, target_resource, filter_name, filter_value)
|
|
82
82
|
return scope if empty_filter_value?(filter_value)
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
apply_direct_column_filter(scope, target_model, filter_name, filter_value) ||
|
|
84
|
+
apply_column_filter(scope, target_model, filter_name, filter_value) ||
|
|
86
85
|
apply_scope_method_filter(scope, target_model, target_resource, filter_name, filter_value) ||
|
|
87
86
|
scope
|
|
88
87
|
end
|
|
89
88
|
|
|
90
|
-
def
|
|
91
|
-
column_filter = parse_column_filter(filter_name)
|
|
92
|
-
return nil unless column_filter
|
|
93
|
-
|
|
94
|
-
column = target_model.column_for_attribute(column_filter[:column])
|
|
95
|
-
return nil unless column
|
|
96
|
-
|
|
97
|
-
value = normalize_filter_value_for_model(target_model, column, filter_value)
|
|
98
|
-
return nil unless value
|
|
99
|
-
|
|
100
|
-
condition = build_condition(target_model, column, value, column_filter[:operator])
|
|
101
|
-
condition ? apply_condition(scope, condition) : nil
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def apply_direct_column_filter(scope, target_model, filter_name, filter_value)
|
|
105
|
-
return nil unless target_model.column_names.include?(filter_name)
|
|
106
|
-
|
|
107
|
-
scope.where(target_model.table_name => { filter_name => filter_value })
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def apply_scope_method_filter(scope, target_model, target_resource, filter_name, filter_value)
|
|
111
|
-
if target_model.respond_to?(filter_name.to_sym)
|
|
112
|
-
return try_scope_method(scope, target_model, filter_name,
|
|
113
|
-
filter_value,)
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
return nil unless target_resource
|
|
117
|
-
return nil unless target_resource.permitted_filters.map(&:to_s).include?(filter_name)
|
|
89
|
+
def apply_scope_method_filter(scope, target_model, _target_resource, filter_name, filter_value)
|
|
118
90
|
return nil unless target_model.respond_to?(filter_name.to_sym)
|
|
119
91
|
|
|
120
92
|
try_scope_method(scope, target_model, filter_name, filter_value)
|
|
@@ -19,36 +19,8 @@ module JSONAPI
|
|
|
19
19
|
def apply_regular_filter(scope, filter_name, filter_value)
|
|
20
20
|
return scope if empty_filter_value?(filter_value)
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
if column_filter
|
|
24
|
-
apply_column_filter(scope, column_filter, filter_value)
|
|
25
|
-
else
|
|
22
|
+
apply_column_filter(scope, model_class, filter_name, filter_value) ||
|
|
26
23
|
apply_scope_fallback(scope, filter_name, filter_value)
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def apply_column_filter(scope, column_filter, raw_value)
|
|
31
|
-
condition = build_column_condition(column_filter, raw_value)
|
|
32
|
-
condition ? apply_condition(scope, condition) : scope
|
|
33
|
-
rescue StandardError => e
|
|
34
|
-
log_filter_error(column_filter, column_filter[:operator], e)
|
|
35
|
-
scope
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def build_column_condition(column_filter, raw_value)
|
|
39
|
-
column = model_class.column_for_attribute(column_filter[:column])
|
|
40
|
-
return nil unless column
|
|
41
|
-
|
|
42
|
-
value = normalize_filter_value_for_model(model_class, column, raw_value)
|
|
43
|
-
return nil if value.nil?
|
|
44
|
-
|
|
45
|
-
build_condition(model_class, column, value, column_filter[:operator])
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def log_filter_error(column_filter, operator, error)
|
|
49
|
-
return unless defined?(Rails.logger)
|
|
50
|
-
|
|
51
|
-
Rails.logger.warn("Filter error for #{column_filter[:column]}_#{operator}: #{error.class} - #{error.message}")
|
|
52
24
|
end
|
|
53
25
|
|
|
54
26
|
def apply_scope_fallback(scope, filter_name, filter_value)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "json_api/support/sort_value_comparison"
|
|
4
|
+
|
|
3
5
|
module JSONAPI
|
|
4
6
|
module Support
|
|
5
7
|
module Sorting
|
|
@@ -77,11 +79,7 @@ module JSONAPI
|
|
|
77
79
|
end
|
|
78
80
|
|
|
79
81
|
def compare_values(value_a, value_b)
|
|
80
|
-
|
|
81
|
-
return -1 if value_a.nil?
|
|
82
|
-
return 1 if value_b.nil?
|
|
83
|
-
|
|
84
|
-
value_a <=> value_b
|
|
82
|
+
SortValueComparison.compare(value_a, value_b)
|
|
85
83
|
end
|
|
86
84
|
end
|
|
87
85
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JSONAPI
|
|
4
|
+
module Support
|
|
5
|
+
# Compares two values for stable sort ordering. Ruby 3.4+ TrueClass#<=> returns nil
|
|
6
|
+
# when operands differ (true <=> false), so booleans are normalized before <=>.
|
|
7
|
+
module SortValueComparison
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
def compare(value_a, value_b)
|
|
11
|
+
return 0 if value_a.nil? && value_b.nil?
|
|
12
|
+
return -1 if value_a.nil?
|
|
13
|
+
return 1 if value_b.nil?
|
|
14
|
+
|
|
15
|
+
value_a = value_a ? 1 : 0 if value_a in TrueClass | FalseClass
|
|
16
|
+
value_b = value_b ? 1 : 0 if value_b in TrueClass | FalseClass
|
|
17
|
+
|
|
18
|
+
result = value_a <=> value_b
|
|
19
|
+
return result unless result.nil?
|
|
20
|
+
|
|
21
|
+
detail = "#{value_a.class.name} (#{value_a.inspect}), #{value_b.class.name} (#{value_b.inspect})"
|
|
22
|
+
raise ArgumentError, "incomparable sort values: #{detail}"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/json_api/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jpie
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.1.
|
|
4
|
+
version: 2.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Emil Kampp
|
|
@@ -192,6 +192,7 @@ files:
|
|
|
192
192
|
- lib/json_api/support/resource_identifier.rb
|
|
193
193
|
- lib/json_api/support/responders.rb
|
|
194
194
|
- lib/json_api/support/sort_parsing.rb
|
|
195
|
+
- lib/json_api/support/sort_value_comparison.rb
|
|
195
196
|
- lib/json_api/support/type_conversion.rb
|
|
196
197
|
- lib/json_api/testing.rb
|
|
197
198
|
- lib/json_api/testing/rspec.rb
|