Skip to content

Commit e9a35a5

Browse files
author
Lee Richmond
committed
Typecast certain string filters automatically
* `"true" becomes `true` * `"false" becomes `false` * `"nil" becomes `nil` * `"null" becomes `nil`
1 parent 07846a6 commit e9a35a5

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

lib/jsonapi_compliable/scoping/filter.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,31 @@ def each_filter
5252
filter = find_filter!(param_name.to_sym)
5353
value = param_value
5454
value = value.split(',') if value.is_a?(String) && value.include?(',')
55+
value = normalize_string_values(value)
5556
yield filter, value
5657
end
5758
end
59+
60+
# Convert a string of "true" to true, etc
61+
#
62+
# NB - avoid Array(value) here since we might want to
63+
# return a single element instead of array
64+
def normalize_string_values(value)
65+
if value.is_a?(Array)
66+
value.map { |v| normalize_string_value(v) }
67+
else
68+
normalize_string_value(value)
69+
end
70+
end
71+
72+
def normalize_string_value(value)
73+
case value
74+
when 'true' then true
75+
when 'false' then false
76+
when 'nil', 'null' then nil
77+
else
78+
value
79+
end
80+
end
5881
end
5982
end

spec/filtering_spec.rb

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
allow_filter :first_name_prefix do |scope, value|
1414
scope.where(['first_name like ?', "#{value}%"])
1515
end
16+
allow_filter :active
1617
end
1718
end
1819

@@ -26,6 +27,54 @@
2627
expect(scope.resolve.map(&:id)).to eq([author1.id])
2728
end
2829

30+
context 'when filter is a "string nil"' do
31+
before do
32+
params[:filter] = { first_name: 'nil' }
33+
author2.update_attribute(:first_name, nil)
34+
end
35+
36+
it 'converts to a real nil' do
37+
ids = scope.resolve.map(&:id)
38+
expect(ids).to eq([author2.id])
39+
end
40+
end
41+
42+
context 'when filter is a "string null"' do
43+
before do
44+
params[:filter] = { first_name: 'null' }
45+
author2.update_attribute(:first_name, nil)
46+
end
47+
48+
it 'converts to a real nil' do
49+
ids = scope.resolve.map(&:id)
50+
expect(ids).to eq([author2.id])
51+
end
52+
end
53+
54+
context 'when filter is a "string boolean"' do
55+
before do
56+
params[:filter] = { active: 'true' }
57+
author2.update_attribute(:active, false)
58+
end
59+
60+
it 'automatically casts to a real boolean' do
61+
ids = scope.resolve.map(&:id)
62+
expect(ids.length).to eq(3)
63+
expect(ids).to_not include(author2.id)
64+
end
65+
66+
context 'and multiple are passed' do
67+
before do
68+
params[:filter] = { active: 'true,false' }
69+
end
70+
71+
it 'still works' do
72+
ids = scope.resolve.map(&:id)
73+
expect(ids.length).to eq(4)
74+
end
75+
end
76+
end
77+
2978
context 'when filter is an integer' do
3079
before do
3180
params[:filter] = { id: author1.id }

spec/fixtures/legacy.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
ActiveRecord::Schema.define(:version => 1) do
22
create_table :authors do |t|
3+
t.boolean :active, default: true
34
t.string :first_name
45
t.string :last_name
56
t.string :dwelling_type

0 commit comments

Comments
 (0)