jsonapi-resources 0.5.4 → 0.5.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +9 -1
- data/lib/generators/jsonapi/USAGE +8 -0
- data/lib/generators/jsonapi/resource_generator.rb +14 -0
- data/lib/generators/jsonapi/templates/jsonapi_resource.rb +4 -0
- data/lib/jsonapi/configuration.rb +8 -3
- data/lib/jsonapi/exceptions.rb +2 -2
- data/lib/jsonapi/link_builder.rb +4 -2
- data/lib/jsonapi/operation.rb +31 -3
- data/lib/jsonapi/operation_result.rb +10 -0
- data/lib/jsonapi/paginator.rb +6 -2
- data/lib/jsonapi/request.rb +12 -0
- data/lib/jsonapi/resource.rb +3 -4
- data/lib/jsonapi/resources/version.rb +1 -1
- data/lib/jsonapi/response_document.rb +21 -13
- data/test/controllers/controller_test.rb +32 -8
- data/test/integration/requests/request_test.rb +58 -0
- data/test/lib/generators/jsonapi/resource_generator_test.rb +25 -0
- data/test/unit/pagination/offset_paginator_test.rb +39 -0
- data/test/unit/pagination/paged_paginator_test.rb +39 -0
- data/test/unit/serializer/link_builder_test.rb +17 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dcb37444c599cb514483e80217f64409d7745411
|
4
|
+
data.tar.gz: eaeff3c3ee4183273ccb9cc59a1933781426c21f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 829b54dedc77b56e63757c0ea593a98b562d573fc2f1ba221baa036f429e365b21c28f99c846c681d681677f7bca9c240ca617d133f39a1ea1c9292ecaf5b1d4
|
7
|
+
data.tar.gz: dc68f574e96aa495ee6f6da7402869262864d169bdaa476b06948888935701f7601b2cdc9b0092c6a67bd9a89c1df96ae4c55c07a70a3f4223628d36a494588b
|
data/README.md
CHANGED
@@ -54,6 +54,11 @@ class ContactResource < JSONAPI::Resource
|
|
54
54
|
end
|
55
55
|
```
|
56
56
|
|
57
|
+
A jsonapi-resource generator is avaliable
|
58
|
+
```
|
59
|
+
rails generate jsonapi:resource contact
|
60
|
+
```
|
61
|
+
|
57
62
|
##### Abstract Resources
|
58
63
|
|
59
64
|
Resources that are not backed by a model (purely used as base classes for other resources) should be declared as
|
@@ -1272,7 +1277,10 @@ JSONAPI.configure do |config|
|
|
1272
1277
|
#:basic, :active_record, or custom
|
1273
1278
|
config.operations_processor = :active_record
|
1274
1279
|
|
1275
|
-
|
1280
|
+
# optional request features
|
1281
|
+
config.allow_include = true
|
1282
|
+
config.allow_sort = true
|
1283
|
+
config.allow_filter = true
|
1276
1284
|
|
1277
1285
|
# :none, :offset, :paged, or a custom paginator name
|
1278
1286
|
config.default_paginator = :none
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Jsonapi
|
2
|
+
class ResourceGenerator < Rails::Generators::NamedBase
|
3
|
+
source_root File.expand_path('../templates', __FILE__)
|
4
|
+
|
5
|
+
def create_resource
|
6
|
+
template_file = File.join(
|
7
|
+
'app/resources',
|
8
|
+
class_path,
|
9
|
+
"#{file_name}_resource.rb"
|
10
|
+
)
|
11
|
+
template 'jsonapi_resource.rb', template_file
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -9,7 +9,9 @@ module JSONAPI
|
|
9
9
|
:route_format,
|
10
10
|
:route_formatter,
|
11
11
|
:operations_processor,
|
12
|
-
:
|
12
|
+
:allow_include,
|
13
|
+
:allow_sort,
|
14
|
+
:allow_filter,
|
13
15
|
:default_paginator,
|
14
16
|
:default_page_size,
|
15
17
|
:maximum_page_size,
|
@@ -31,7 +33,10 @@ module JSONAPI
|
|
31
33
|
#:basic, :active_record, or custom
|
32
34
|
self.operations_processor = :active_record
|
33
35
|
|
34
|
-
|
36
|
+
# optional request features
|
37
|
+
self.allow_include = true
|
38
|
+
self.allow_sort = true
|
39
|
+
self.allow_filter = true
|
35
40
|
|
36
41
|
# :none, :offset, :paged, or a custom paginator name
|
37
42
|
self.default_paginator = :none
|
@@ -79,7 +84,7 @@ module JSONAPI
|
|
79
84
|
@operations_processor = JSONAPI::OperationsProcessor.operations_processor_for(@operations_processor_name)
|
80
85
|
end
|
81
86
|
|
82
|
-
attr_writer :
|
87
|
+
attr_writer :allow_include, :allow_sort, :allow_filter
|
83
88
|
|
84
89
|
attr_writer :default_paginator
|
85
90
|
|
data/lib/jsonapi/exceptions.rb
CHANGED
@@ -317,8 +317,8 @@ module JSONAPI
|
|
317
317
|
def json_api_error(attr_key, message)
|
318
318
|
JSONAPI::Error.new(code: JSONAPI::VALIDATION_ERROR,
|
319
319
|
status: :unprocessable_entity,
|
320
|
-
title:
|
321
|
-
detail: message,
|
320
|
+
title: message,
|
321
|
+
detail: "#{format_key(attr_key)} - #{message}",
|
322
322
|
source: { pointer: pointer(attr_key) })
|
323
323
|
end
|
324
324
|
|
data/lib/jsonapi/link_builder.rb
CHANGED
@@ -31,8 +31,10 @@ module JSONAPI
|
|
31
31
|
"#{ primary_resources_url }?#{ query_params.to_query }"
|
32
32
|
end
|
33
33
|
|
34
|
-
def relationships_related_link(source, relationship)
|
35
|
-
"#{ self_link(source) }/#{ route_for_relationship(relationship) }"
|
34
|
+
def relationships_related_link(source, relationship, query_params = {})
|
35
|
+
url = "#{ self_link(source) }/#{ route_for_relationship(relationship) }"
|
36
|
+
url = "#{ url }?#{ query_params.to_query }" if query_params.present?
|
37
|
+
url
|
36
38
|
end
|
37
39
|
|
38
40
|
def relationships_self_link(source, relationship)
|
data/lib/jsonapi/operation.rb
CHANGED
@@ -149,15 +149,43 @@ module JSONAPI
|
|
149
149
|
@transactional = false
|
150
150
|
end
|
151
151
|
|
152
|
-
def
|
153
|
-
|
152
|
+
def record_count
|
153
|
+
@_record_count ||= records.count
|
154
|
+
end
|
155
|
+
|
156
|
+
def source_resource
|
157
|
+
@_source_resource ||= @source_klass.find_by_key(@source_id, context: @context)
|
158
|
+
end
|
159
|
+
|
160
|
+
def records
|
161
|
+
related_resource_records = source_resource.records_for(@relationship_type)
|
162
|
+
@resource_klass.filter_records(@filters, @options, related_resource_records)
|
163
|
+
end
|
164
|
+
|
165
|
+
def pagination_params
|
166
|
+
if @paginator && JSONAPI.configuration.top_level_links_include_pagination
|
167
|
+
options = {}
|
168
|
+
options[:record_count] = record_count if @paginator.class.requires_record_count
|
169
|
+
@paginator.links_page_params(options)
|
170
|
+
else
|
171
|
+
{}
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def options
|
176
|
+
opts = {}
|
177
|
+
opts.merge!(pagination_params: pagination_params) if JSONAPI.configuration.top_level_links_include_pagination
|
178
|
+
opts.merge!(record_count: pagination_params) if JSONAPI.configuration.top_level_meta_include_record_count
|
179
|
+
opts
|
180
|
+
end
|
154
181
|
|
182
|
+
def apply
|
155
183
|
related_resource = source_resource.public_send(@relationship_type,
|
156
184
|
filters: @filters,
|
157
185
|
sort_criteria: @sort_criteria,
|
158
186
|
paginator: @paginator)
|
159
187
|
|
160
|
-
return JSONAPI::
|
188
|
+
return JSONAPI::RelatedResourcesOperationResult.new(:ok, source_resource, @relationship_type, related_resource, options)
|
161
189
|
|
162
190
|
rescue JSONAPI::Exceptions::Error => e
|
163
191
|
return JSONAPI::ErrorsOperationResult.new(e.errors[0].code, e.errors)
|
@@ -42,6 +42,16 @@ module JSONAPI
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
class RelatedResourcesOperationResult < ResourcesOperationResult
|
46
|
+
attr_accessor :source_resource, :_type
|
47
|
+
|
48
|
+
def initialize(code, source_resource, type, resources, options = {})
|
49
|
+
@source_resource = source_resource
|
50
|
+
@_type = type
|
51
|
+
super(code, resources, options)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
45
55
|
class LinksObjectOperationResult < OperationResult
|
46
56
|
attr_accessor :parent_resource, :relationship
|
47
57
|
|
data/lib/jsonapi/paginator.rb
CHANGED
@@ -74,8 +74,12 @@ class OffsetPaginator < JSONAPI::Paginator
|
|
74
74
|
end
|
75
75
|
|
76
76
|
if record_count
|
77
|
+
last_offset = record_count - @limit
|
78
|
+
|
79
|
+
last_offset = 0 if last_offset < 0
|
80
|
+
|
77
81
|
links_page_params['last'] = {
|
78
|
-
'offset' =>
|
82
|
+
'offset' => last_offset,
|
79
83
|
'limit' => @limit
|
80
84
|
}
|
81
85
|
end
|
@@ -159,7 +163,7 @@ class PagedPaginator < JSONAPI::Paginator
|
|
159
163
|
|
160
164
|
if record_count
|
161
165
|
links_page_params['last'] = {
|
162
|
-
'number' => page_count,
|
166
|
+
'number' => page_count == 0 ? 1 : page_count,
|
163
167
|
'size' => @size
|
164
168
|
}
|
165
169
|
end
|
data/lib/jsonapi/request.rb
CHANGED
@@ -196,6 +196,10 @@ module JSONAPI
|
|
196
196
|
def parse_include_directives(include)
|
197
197
|
return if include.nil?
|
198
198
|
|
199
|
+
unless JSONAPI.configuration.allow_include
|
200
|
+
fail JSONAPI::Exceptions::ParametersNotAllowed.new([:include])
|
201
|
+
end
|
202
|
+
|
199
203
|
included_resources = CSV.parse_line(include)
|
200
204
|
return if included_resources.nil?
|
201
205
|
|
@@ -211,6 +215,10 @@ module JSONAPI
|
|
211
215
|
def parse_filters(filters)
|
212
216
|
return unless filters
|
213
217
|
|
218
|
+
unless JSONAPI.configuration.allow_filter
|
219
|
+
fail JSONAPI::Exceptions::ParametersNotAllowed.new([:filter])
|
220
|
+
end
|
221
|
+
|
214
222
|
unless filters.class.method_defined?(:each)
|
215
223
|
@errors.concat(JSONAPI::Exceptions::InvalidFiltersSyntax.new(filters).errors)
|
216
224
|
return
|
@@ -236,6 +244,10 @@ module JSONAPI
|
|
236
244
|
def parse_sort_criteria(sort_criteria)
|
237
245
|
return unless sort_criteria.present?
|
238
246
|
|
247
|
+
unless JSONAPI.configuration.allow_sort
|
248
|
+
fail JSONAPI::Exceptions::ParametersNotAllowed.new([:sort])
|
249
|
+
end
|
250
|
+
|
239
251
|
@sort_criteria = CSV.parse_line(URI.unescape(sort_criteria)).collect do |sort|
|
240
252
|
if sort.start_with?('-')
|
241
253
|
sort_criteria = { field: unformat_key(sort[1..-1]).to_s }
|
data/lib/jsonapi/resource.rb
CHANGED
@@ -472,8 +472,7 @@ module JSONAPI
|
|
472
472
|
records
|
473
473
|
end
|
474
474
|
|
475
|
-
def filter_records(filters, options)
|
476
|
-
records = records(options)
|
475
|
+
def filter_records(filters, options, records = records(options))
|
477
476
|
records = apply_filters(records, filters, options)
|
478
477
|
apply_includes(records, options)
|
479
478
|
end
|
@@ -483,7 +482,7 @@ module JSONAPI
|
|
483
482
|
end
|
484
483
|
|
485
484
|
def find_count(filters, options = {})
|
486
|
-
filter_records(filters, options).count
|
485
|
+
filter_records(filters, options).count(:all)
|
487
486
|
end
|
488
487
|
|
489
488
|
# Override this method if you have more complex requirements than this basic find method provides
|
@@ -686,7 +685,7 @@ module JSONAPI
|
|
686
685
|
check_reserved_relationship_name(attr)
|
687
686
|
|
688
687
|
# Initialize from an ActiveRecord model's properties
|
689
|
-
if _model_class && _model_class
|
688
|
+
if _model_class && _model_class.ancestors.collect{|ancestor| ancestor.name}.include?('ActiveRecord::Base')
|
690
689
|
model_association = _model_class.reflect_on_association(attr)
|
691
690
|
if model_association
|
692
691
|
options[:class_name] ||= model_association.class_name
|
@@ -69,25 +69,33 @@ module JSONAPI
|
|
69
69
|
links.merge!(result.links)
|
70
70
|
|
71
71
|
# Build pagination links
|
72
|
-
if result.is_a?(JSONAPI::ResourcesOperationResult)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
query_params[:filter] = request.params[:filter] if request.params[:filter]
|
82
|
-
|
83
|
-
links[link_name] = serializer.find_link(query_params)
|
84
|
-
end
|
72
|
+
if result.is_a?(JSONAPI::ResourcesOperationResult) || result.is_a?(JSONAPI::RelatedResourcesOperationResult)
|
73
|
+
result.pagination_params.each_pair do |link_name, params|
|
74
|
+
if result.is_a?(JSONAPI::RelatedResourcesOperationResult)
|
75
|
+
relationship = result.source_resource.class._relationships[result._type.to_sym]
|
76
|
+
links[link_name] = serializer.url_generator.relationships_related_link(result.source_resource, relationship, query_params(params))
|
77
|
+
else
|
78
|
+
links[link_name] = serializer.find_link(query_params(params))
|
79
|
+
end
|
80
|
+
end
|
85
81
|
end
|
86
82
|
end
|
87
83
|
|
88
84
|
links.deep_transform_keys { |key| @key_formatter.format(key) }
|
89
85
|
end
|
90
86
|
|
87
|
+
def query_params(params)
|
88
|
+
query_params = {}
|
89
|
+
query_params[:page] = params
|
90
|
+
|
91
|
+
request = @options[:request]
|
92
|
+
query_params[:fields] = request.params[:fields] if request.params[:fields]
|
93
|
+
query_params[:include] = request.params[:include] if request.params[:include]
|
94
|
+
query_params[:sort] = request.params[:sort] if request.params[:sort]
|
95
|
+
query_params[:filter] = request.params[:filter] if request.params[:filter]
|
96
|
+
query_params
|
97
|
+
end
|
98
|
+
|
91
99
|
def results_to_hash
|
92
100
|
if @operation_results.has_errors?
|
93
101
|
{ errors: @operation_results.all_errors }
|
@@ -69,6 +69,14 @@ class PostsControllerTest < ActionController::TestCase
|
|
69
69
|
assert_equal 1, json_response['included'].size
|
70
70
|
end
|
71
71
|
|
72
|
+
def test_index_filter_not_allowed
|
73
|
+
JSONAPI.configuration.allow_filter = false
|
74
|
+
get :index, {filter: {id: '1'}}
|
75
|
+
assert_response :bad_request
|
76
|
+
ensure
|
77
|
+
JSONAPI.configuration.allow_filter = true
|
78
|
+
end
|
79
|
+
|
72
80
|
def test_index_include_one_level_query_count
|
73
81
|
count_queries do
|
74
82
|
get :index, {include: 'author'}
|
@@ -239,6 +247,14 @@ class PostsControllerTest < ActionController::TestCase
|
|
239
247
|
assert_match /asdfg is not a valid sort criteria for post/, response.body
|
240
248
|
end
|
241
249
|
|
250
|
+
def test_show_single_with_sort_disallowed
|
251
|
+
JSONAPI.configuration.allow_sort = false
|
252
|
+
get :index, {sort: 'title,body'}
|
253
|
+
assert_response :bad_request
|
254
|
+
ensure
|
255
|
+
JSONAPI.configuration.allow_sort = true
|
256
|
+
end
|
257
|
+
|
242
258
|
def test_excluded_sort_param
|
243
259
|
get :index, {sort: 'id'}
|
244
260
|
|
@@ -276,6 +292,14 @@ class PostsControllerTest < ActionController::TestCase
|
|
276
292
|
assert_equal 2, json_response['included'].size
|
277
293
|
end
|
278
294
|
|
295
|
+
def test_show_single_with_include_disallowed
|
296
|
+
JSONAPI.configuration.allow_include = false
|
297
|
+
get :show, {id: '1', include: 'comments'}
|
298
|
+
assert_response :bad_request
|
299
|
+
ensure
|
300
|
+
JSONAPI.configuration.allow_include = true
|
301
|
+
end
|
302
|
+
|
279
303
|
def test_show_single_with_fields
|
280
304
|
get :show, {id: '1', fields: {posts: 'author'}}
|
281
305
|
assert_response :success
|
@@ -396,12 +420,12 @@ class PostsControllerTest < ActionController::TestCase
|
|
396
420
|
assert_response :unprocessable_entity
|
397
421
|
|
398
422
|
assert_equal "/data/relationships/author", json_response['errors'][0]['source']['pointer']
|
399
|
-
assert_equal "can't be blank", json_response['errors'][0]['
|
400
|
-
assert_equal "author - can't be blank", json_response['errors'][0]['
|
423
|
+
assert_equal "can't be blank", json_response['errors'][0]['title']
|
424
|
+
assert_equal "author - can't be blank", json_response['errors'][0]['detail']
|
401
425
|
|
402
426
|
assert_equal "/data/attributes/title", json_response['errors'][1]['source']['pointer']
|
403
|
-
assert_equal "is too long (maximum is 35 characters)", json_response['errors'][1]['
|
404
|
-
assert_equal "title - is too long (maximum is 35 characters)", json_response['errors'][1]['
|
427
|
+
assert_equal "is too long (maximum is 35 characters)", json_response['errors'][1]['title']
|
428
|
+
assert_equal "title - is too long (maximum is 35 characters)", json_response['errors'][1]['detail']
|
405
429
|
end
|
406
430
|
|
407
431
|
def test_create_multiple
|
@@ -2212,12 +2236,12 @@ class FactsControllerTest < ActionController::TestCase
|
|
2212
2236
|
assert_response :unprocessable_entity
|
2213
2237
|
|
2214
2238
|
assert_equal "/data/attributes/spouse-name", json_response['errors'][0]['source']['pointer']
|
2215
|
-
assert_equal "can't be blank", json_response['errors'][0]['
|
2216
|
-
assert_equal "spouse-name - can't be blank", json_response['errors'][0]['
|
2239
|
+
assert_equal "can't be blank", json_response['errors'][0]['title']
|
2240
|
+
assert_equal "spouse-name - can't be blank", json_response['errors'][0]['detail']
|
2217
2241
|
|
2218
2242
|
assert_equal "/data/attributes/bio", json_response['errors'][1]['source']['pointer']
|
2219
|
-
assert_equal "can't be blank", json_response['errors'][1]['
|
2220
|
-
assert_equal "bio - can't be blank", json_response['errors'][1]['
|
2243
|
+
assert_equal "can't be blank", json_response['errors'][1]['title']
|
2244
|
+
assert_equal "bio - can't be blank", json_response['errors'][1]['detail']
|
2221
2245
|
end
|
2222
2246
|
end
|
2223
2247
|
|
@@ -389,6 +389,25 @@ class RequestTest < ActionDispatch::IntegrationTest
|
|
389
389
|
assert_equal 'This is comment 18 on book 1.', json_response['data'][9]['attributes']['body']
|
390
390
|
end
|
391
391
|
|
392
|
+
def test_pagination_related_resources_links
|
393
|
+
Api::V2::BookResource.paginator :offset
|
394
|
+
Api::V2::BookCommentResource.paginator :offset
|
395
|
+
get '/api/v2/books/1/book_comments?page[limit]=10'
|
396
|
+
assert_equal 'http://www.example.com/api/v2/books/1/book_comments?page%5Blimit%5D=10&page%5Boffset%5D=0', json_response['links']['first']
|
397
|
+
assert_equal 'http://www.example.com/api/v2/books/1/book_comments?page%5Blimit%5D=10&page%5Boffset%5D=10', json_response['links']['next']
|
398
|
+
assert_equal 'http://www.example.com/api/v2/books/1/book_comments?page%5Blimit%5D=10&page%5Boffset%5D=41', json_response['links']['last']
|
399
|
+
end
|
400
|
+
|
401
|
+
def test_pagination_related_resources_without_related
|
402
|
+
Api::V2::BookResource.paginator :offset
|
403
|
+
Api::V2::BookCommentResource.paginator :offset
|
404
|
+
get '/api/v2/books/10/book_comments'
|
405
|
+
assert_equal 200, status
|
406
|
+
assert_nil json_response['links']['next']
|
407
|
+
assert_equal 'http://www.example.com/api/v2/books/10/book_comments?page%5Blimit%5D=10&page%5Boffset%5D=0', json_response['links']['first']
|
408
|
+
assert_equal 'http://www.example.com/api/v2/books/10/book_comments?page%5Blimit%5D=10&page%5Boffset%5D=0', json_response['links']['last']
|
409
|
+
end
|
410
|
+
|
392
411
|
def test_pagination_related_resources_data_includes
|
393
412
|
Api::V2::BookResource.paginator :offset
|
394
413
|
Api::V2::BookCommentResource.paginator :offset
|
@@ -398,6 +417,17 @@ class RequestTest < ActionDispatch::IntegrationTest
|
|
398
417
|
assert_equal 'This is comment 18 on book 1.', json_response['data'][9]['attributes']['body']
|
399
418
|
end
|
400
419
|
|
420
|
+
def test_pagination_empty_results
|
421
|
+
Api::V2::BookResource.paginator :offset
|
422
|
+
Api::V2::BookCommentResource.paginator :offset
|
423
|
+
get '/api/v2/books?filter[id]=2000&page[limit]=10'
|
424
|
+
assert_equal 200, status
|
425
|
+
assert_equal 0, json_response['data'].size
|
426
|
+
assert_nil json_response['links']['next']
|
427
|
+
assert_equal 'http://www.example.com/api/v2/books?filter%5Bid%5D=2000&page%5Blimit%5D=10&page%5Boffset%5D=0', json_response['links']['first']
|
428
|
+
assert_equal 'http://www.example.com/api/v2/books?filter%5Bid%5D=2000&page%5Blimit%5D=10&page%5Boffset%5D=0', json_response['links']['last']
|
429
|
+
end
|
430
|
+
|
401
431
|
# def test_pagination_related_resources_data_includes
|
402
432
|
# Api::V2::BookResource.paginator :none
|
403
433
|
# Api::V2::BookCommentResource.paginator :none
|
@@ -691,4 +721,32 @@ class RequestTest < ActionDispatch::IntegrationTest
|
|
691
721
|
assert_equal 204, status
|
692
722
|
end
|
693
723
|
|
724
|
+
def test_include_parameter_allowed
|
725
|
+
get '/api/v2/books/1/book_comments?include=author'
|
726
|
+
assert_equal 200, status
|
727
|
+
end
|
728
|
+
|
729
|
+
def test_include_parameter_not_allowed
|
730
|
+
JSONAPI.configuration.allow_include = false
|
731
|
+
get '/api/v2/books/1/book_comments?include=author'
|
732
|
+
assert_equal 400, status
|
733
|
+
ensure
|
734
|
+
JSONAPI.configuration.allow_include = true
|
735
|
+
end
|
736
|
+
|
737
|
+
def test_filter_parameter_not_allowed
|
738
|
+
JSONAPI.configuration.allow_filter = false
|
739
|
+
get '/api/v2/books?filter[author]=1'
|
740
|
+
assert_equal 400, status
|
741
|
+
ensure
|
742
|
+
JSONAPI.configuration.allow_filter = true
|
743
|
+
end
|
744
|
+
|
745
|
+
def test_sort_parameter_not_allowed
|
746
|
+
JSONAPI.configuration.allow_sort = false
|
747
|
+
get '/api/v2/books?sort=title'
|
748
|
+
assert_equal 400, status
|
749
|
+
ensure
|
750
|
+
JSONAPI.configuration.allow_sort = true
|
751
|
+
end
|
694
752
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'generators/jsonapi/resource_generator'
|
3
|
+
|
4
|
+
module Jsonapi
|
5
|
+
class ResourceGeneratorTest < Rails::Generators::TestCase
|
6
|
+
tests ResourceGenerator
|
7
|
+
destination Rails.root.join('../resources')
|
8
|
+
setup :prepare_destination
|
9
|
+
teardown :cleanup_destination_root
|
10
|
+
|
11
|
+
def cleanup_destination_root
|
12
|
+
FileUtils.rm_rf destination_root
|
13
|
+
end
|
14
|
+
|
15
|
+
test "resource is created" do
|
16
|
+
run_generator ["post"]
|
17
|
+
assert_file 'app/resources/post_resource.rb', /class PostResource < JSONAPI::Resource/
|
18
|
+
end
|
19
|
+
|
20
|
+
test "resource is created with namespace" do
|
21
|
+
run_generator ["api/v1/post"]
|
22
|
+
assert_file 'app/resources/api/v1/post_resource.rb', /class Api::V1::PostResource < JSONAPI::Resource/
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -82,6 +82,45 @@ class OffsetPaginatorTest < ActiveSupport::TestCase
|
|
82
82
|
assert_equal 0, paginator.offset
|
83
83
|
end
|
84
84
|
|
85
|
+
def test_offset_links_page_params_empty_results
|
86
|
+
params = ActionController::Parameters.new(
|
87
|
+
{
|
88
|
+
limit: 5,
|
89
|
+
offset: 0
|
90
|
+
}
|
91
|
+
)
|
92
|
+
|
93
|
+
paginator = OffsetPaginator.new(params)
|
94
|
+
links_params = paginator.links_page_params(record_count: 0)
|
95
|
+
|
96
|
+
assert_equal 2, links_params.size
|
97
|
+
|
98
|
+
assert_equal 5, links_params['first']['limit']
|
99
|
+
assert_equal 0, links_params['first']['offset']
|
100
|
+
|
101
|
+
assert_equal 5, links_params['last']['limit']
|
102
|
+
assert_equal 0, links_params['last']['offset']
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_offset_links_page_params_small_resultsets
|
106
|
+
params = ActionController::Parameters.new(
|
107
|
+
{
|
108
|
+
limit: 5,
|
109
|
+
offset: 0
|
110
|
+
}
|
111
|
+
)
|
112
|
+
|
113
|
+
paginator = OffsetPaginator.new(params)
|
114
|
+
links_params = paginator.links_page_params(record_count: 3)
|
115
|
+
|
116
|
+
assert_equal 2, links_params.size
|
117
|
+
|
118
|
+
assert_equal 5, links_params['first']['limit']
|
119
|
+
assert_equal 0, links_params['first']['offset']
|
120
|
+
|
121
|
+
assert_equal 5, links_params['last']['limit']
|
122
|
+
assert_equal 0, links_params['last']['offset']
|
123
|
+
end
|
85
124
|
|
86
125
|
def test_offset_links_page_params_large_data_set_start
|
87
126
|
params = ActionController::Parameters.new(
|
@@ -82,6 +82,45 @@ class PagedPaginatorTest < ActiveSupport::TestCase
|
|
82
82
|
assert_equal 1, paginator.number
|
83
83
|
end
|
84
84
|
|
85
|
+
def test_paged_links_page_params_empty_results
|
86
|
+
params = ActionController::Parameters.new(
|
87
|
+
{
|
88
|
+
size: 5,
|
89
|
+
number: 1
|
90
|
+
}
|
91
|
+
)
|
92
|
+
|
93
|
+
paginator = PagedPaginator.new(params)
|
94
|
+
links_params = paginator.links_page_params(record_count: 0)
|
95
|
+
|
96
|
+
assert_equal 2, links_params.size
|
97
|
+
|
98
|
+
assert_equal 5, links_params['first']['size']
|
99
|
+
assert_equal 1, links_params['first']['number']
|
100
|
+
|
101
|
+
assert_equal 5, links_params['last']['size']
|
102
|
+
assert_equal 1, links_params['last']['number']
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_paged_links_page_params_small_resultsets
|
106
|
+
params = ActionController::Parameters.new(
|
107
|
+
{
|
108
|
+
size: 5,
|
109
|
+
number: 1
|
110
|
+
}
|
111
|
+
)
|
112
|
+
|
113
|
+
paginator = PagedPaginator.new(params)
|
114
|
+
links_params = paginator.links_page_params(record_count: 3)
|
115
|
+
|
116
|
+
assert_equal 2, links_params.size
|
117
|
+
|
118
|
+
assert_equal 5, links_params['first']['size']
|
119
|
+
assert_equal 1, links_params['first']['number']
|
120
|
+
|
121
|
+
assert_equal 5, links_params['last']['size']
|
122
|
+
assert_equal 1, links_params['last']['number']
|
123
|
+
end
|
85
124
|
|
86
125
|
def test_paged_links_page_params_large_data_set_start_full_pages
|
87
126
|
params = ActionController::Parameters.new(
|
@@ -169,6 +169,23 @@ class LinkBuilderTest < ActionDispatch::IntegrationTest
|
|
169
169
|
builder.relationships_related_link(source, relationship)
|
170
170
|
end
|
171
171
|
|
172
|
+
def test_relationships_related_link_with_query_params
|
173
|
+
config = {
|
174
|
+
base_url: @base_url,
|
175
|
+
route_formatter: @route_formatter,
|
176
|
+
primary_resource_klass: Api::V1::PersonResource
|
177
|
+
}
|
178
|
+
|
179
|
+
builder = JSONAPI::LinkBuilder.new(config)
|
180
|
+
source = Api::V1::PersonResource.new(@steve)
|
181
|
+
relationship = JSONAPI::Relationship::ToMany.new("posts", {})
|
182
|
+
expected_link = "#{ @base_url }/api/v1/people/#{ @steve.id }/posts?page%5Blimit%5D=12&page%5Boffset%5D=0"
|
183
|
+
query = { page: { offset: 0, limit: 12 } }
|
184
|
+
|
185
|
+
assert_equal expected_link,
|
186
|
+
builder.relationships_related_link(source, relationship, query)
|
187
|
+
end
|
188
|
+
|
172
189
|
def test_query_link_for_regular_app
|
173
190
|
config = {
|
174
191
|
base_url: @base_url,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonapi-resources
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Gebhardt
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-08-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -139,6 +139,9 @@ files:
|
|
139
139
|
- README.md
|
140
140
|
- Rakefile
|
141
141
|
- jsonapi-resources.gemspec
|
142
|
+
- lib/generators/jsonapi/USAGE
|
143
|
+
- lib/generators/jsonapi/resource_generator.rb
|
144
|
+
- lib/generators/jsonapi/templates/jsonapi_resource.rb
|
142
145
|
- lib/jsonapi-resources.rb
|
143
146
|
- lib/jsonapi/active_record_operations_processor.rb
|
144
147
|
- lib/jsonapi/acts_as_resource_controller.rb
|
@@ -202,6 +205,7 @@ files:
|
|
202
205
|
- test/helpers/value_matchers_test.rb
|
203
206
|
- test/integration/requests/request_test.rb
|
204
207
|
- test/integration/routes/routes_test.rb
|
208
|
+
- test/lib/generators/jsonapi/resource_generator_test.rb
|
205
209
|
- test/test_helper.rb
|
206
210
|
- test/unit/jsonapi_request/jsonapi_request_test.rb
|
207
211
|
- test/unit/operation/operations_processor_test.rb
|
@@ -276,6 +280,7 @@ test_files:
|
|
276
280
|
- test/helpers/value_matchers_test.rb
|
277
281
|
- test/integration/requests/request_test.rb
|
278
282
|
- test/integration/routes/routes_test.rb
|
283
|
+
- test/lib/generators/jsonapi/resource_generator_test.rb
|
279
284
|
- test/test_helper.rb
|
280
285
|
- test/unit/jsonapi_request/jsonapi_request_test.rb
|
281
286
|
- test/unit/operation/operations_processor_test.rb
|
@@ -287,3 +292,4 @@ test_files:
|
|
287
292
|
- test/unit/serializer/polymorphic_serializer_test.rb
|
288
293
|
- test/unit/serializer/response_document_test.rb
|
289
294
|
- test/unit/serializer/serializer_test.rb
|
295
|
+
has_rdoc:
|