jsonapi-resources 0.5.4 → 0.5.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/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:
|