Skip to content

Commit 465d29b

Browse files
committed
Merge pull request #230 from brettchalupa/request-filters-each-check
Only loop through filters if #each is implemented
2 parents 98cca61 + d1eb9d0 commit 465d29b

5 files changed

Lines changed: 71 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,7 @@ module JSONAPI
736736
INVALID_PAGE_OBJECT = 117
737737
INVALID_PAGE_VALUE = 118
738738
INVALID_FIELD_FORMAT = 119
739+
INVALID_FILTERS_SYNTAX = 120
739740
FORBIDDEN = 403
740741
RECORD_NOT_FOUND = 404
741742
UNSUPPORTED_MEDIA_TYPE = 415

lib/jsonapi/error_codes.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module JSONAPI
1818
INVALID_PAGE_OBJECT = 117
1919
INVALID_PAGE_VALUE = 118
2020
INVALID_FIELD_FORMAT = 119
21+
INVALID_FILTERS_SYNTAX = 120
2122
FORBIDDEN = 403
2223
RECORD_NOT_FOUND = 404
2324
UNSUPPORTED_MEDIA_TYPE = 415
@@ -46,5 +47,6 @@ module JSONAPI
4647
FORBIDDEN => 'FORBIDDEN',
4748
RECORD_NOT_FOUND => 'RECORD_NOT_FOUND',
4849
UNSUPPORTED_MEDIA_TYPE => 'UNSUPPORTED_MEDIA_TYPE',
49-
LOCKED => 'LOCKED' }
50+
LOCKED => 'LOCKED',
51+
INVALID_FILTERS_SYNTAX => 'INVALID_FILTERS_SYNTAX' }
5052
end

lib/jsonapi/exceptions.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,20 @@ def errors
6767
end
6868
end
6969

70+
class InvalidFiltersSyntax < Error
71+
attr_accessor :filters
72+
def initialize(filters)
73+
@filters = filters
74+
end
75+
76+
def errors
77+
[JSONAPI::Error.new(code: JSONAPI::INVALID_FILTERS_SYNTAX,
78+
status: :bad_request,
79+
title: 'Invalid filters syntax',
80+
detail: "#{filters} is not a valid syntax for filtering.")]
81+
end
82+
end
83+
7084
class FilterNotAllowed < Error
7185
attr_accessor :filter
7286
def initialize(filter)

lib/jsonapi/request.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,11 @@ def parse_include_directives(include)
211211
def parse_filters(filters)
212212
return unless filters
213213

214+
unless filters.class.method_defined?(:each)
215+
@errors.concat(JSONAPI::Exceptions::InvalidFiltersSyntax.new(filters).errors)
216+
return
217+
end
218+
214219
filters.each do |key, value|
215220
filter = unformat_key(key)
216221
if @resource_klass._allowed_filter?(filter)

test/unit/jsonapi_request/jsonapi_request_test.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
require File.expand_path('../../../test_helper', __FILE__)
22

3+
class CatResource < JSONAPI::Resource
4+
attribute :id
5+
attribute :name
6+
attribute :breed
7+
8+
has_one :mother, class_name: 'Cat'
9+
has_one :father, class_name: 'Cat'
10+
11+
filters :name
12+
end
13+
314
class JSONAPIRequestTest < ActiveSupport::TestCase
415
def test_parse_includes_underscored
516
params = ActionController::Parameters.new(
@@ -149,4 +160,41 @@ def test_parse_dasherized_with_underscored_resource
149160
refute request.errors.empty?
150161
assert_equal 'expense_entries is not a valid resource.', request.errors[0].detail
151162
end
163+
164+
def test_parse_filters_with_valid_filters
165+
setup_request
166+
@request.parse_filters({name: 'Whiskers'})
167+
assert_equal(@request.filters[:name], 'Whiskers')
168+
assert_equal(@request.errors, [])
169+
end
170+
171+
def test_parse_filters_with_non_valid_filter
172+
setup_request
173+
@request.parse_filters({breed: 'Whiskers'}) # breed is not a set filter
174+
assert_equal(@request.filters, {})
175+
assert_equal(@request.errors.count, 1)
176+
assert_equal(@request.errors.first.title, "Filter not allowed")
177+
end
178+
179+
def test_parse_filters_with_no_filters
180+
setup_request
181+
@request.parse_filters(nil)
182+
assert_equal(@request.filters, {})
183+
assert_equal(@request.errors, [])
184+
end
185+
186+
def test_parse_filters_with_invalid_filters_param
187+
setup_request
188+
@request.parse_filters('noeach') # String does not implement #each
189+
assert_equal(@request.filters, {})
190+
assert_equal(@request.errors.count, 1)
191+
assert_equal(@request.errors.first.title, "Invalid filters syntax")
192+
end
193+
194+
private
195+
196+
def setup_request
197+
@request = JSONAPI::Request.new
198+
@request.resource_klass = CatResource
199+
end
152200
end

0 commit comments

Comments
 (0)