jsonapi-utils 0.4.9 → 0.5.0.beta1
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 +89 -56
- data/bin/console +3 -3
- data/lib/jsonapi/utils.rb +0 -4
- data/lib/jsonapi/utils/request.rb +37 -77
- data/lib/jsonapi/utils/response/support.rb +3 -3
- data/lib/jsonapi/utils/support/filter.rb +2 -3
- data/lib/jsonapi/utils/support/pagination.rb +33 -102
- data/lib/jsonapi/utils/support/sort.rb +28 -45
- data/lib/jsonapi/utils/version.rb +1 -1
- metadata +10 -11
- data/lib/jsonapi/utils/support/filter/custom.rb +0 -18
- data/lib/jsonapi/utils/support/filter/default.rb +0 -66
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e739a959755e7910791783ee16583499f32c06a6
|
4
|
+
data.tar.gz: 817a8fb3526e0fc8f15e4081a277a9e81d557340
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3307a7571da692f2606d056cb0d7c8b28acc3abcd9cd53b39e521d5a979ef4b95c4499f5eb41b4b816417cb47e59b31548cf19fd262c214844c3d81941deee2a
|
7
|
+
data.tar.gz: a210faeb4ea1aa675d236ef1e8993c81bcc2f273392f0fa80dd983d322ebdba6846019556cc2ccddcb1ae6afbc11bafe483ce75b95da12c19e46e4ffb5a1f30b
|
data/README.md
CHANGED
@@ -4,16 +4,47 @@
|
|
4
4
|
[](https://badge.fury.io/rb/jsonapi-utils)
|
5
5
|
[](https://travis-ci.org/b2beauty/jsonapi-utils)
|
6
6
|
|
7
|
-
Simple yet powerful way to
|
8
|
-
|
9
|
-
JSONAPI::Utils (JU)
|
7
|
+
Simple yet powerful way to get your Rails API compliant with [JSON API](http://jsonapi.org).
|
8
|
+
|
9
|
+
JSONAPI::Utils (JU) is built on top of [JSONAPI::Resources](https://github.com/cerebris/jsonapi-resources) taking advantage of its resource-driven style and bringing a Rails way to build modern APIs with no or less learning curve.
|
10
|
+
|
11
|
+
## Contents
|
12
|
+
|
13
|
+
* [Installation](#installation)
|
14
|
+
* [How does it work?](#how-does-it-work)
|
15
|
+
* [Usage](#usage)
|
16
|
+
* [Response](#response)
|
17
|
+
* [Rendes](#renders)
|
18
|
+
* [Formatters](#formatters)
|
19
|
+
* [Request](#request)
|
20
|
+
* [Params helpers](#params-helpers)
|
21
|
+
* [Full example](#full-example)
|
22
|
+
* [Models](#models)
|
23
|
+
* [Resources](#resources)
|
24
|
+
* [Routes & Controllers](routes--controllers)
|
25
|
+
* [Initializer](#initializer)
|
26
|
+
* [Requests & Responses](requests--responses)
|
27
|
+
* [Index](#index)
|
28
|
+
* [Index (options)](#index-options)
|
29
|
+
* [Show](#show)
|
30
|
+
* [Show (options)](#show-options)
|
31
|
+
* [Relationships (identifier objects)](#relationships-identifier-objects)
|
32
|
+
* [Nested resources](#nested-resources)
|
33
|
+
* [Development](#development)
|
34
|
+
* [Contributing](#contributing)
|
35
|
+
* [License](#license)
|
10
36
|
|
11
37
|
## Installation
|
12
38
|
|
39
|
+
For:
|
40
|
+
|
41
|
+
* Ruby ~> 2.0 with Rails ~> 4.0, use JU's `0.4.6` version (stable);
|
42
|
+
* Ruby ~> 2.1 with Rails 5, use JU's `0.5.0.beta1` version.
|
43
|
+
|
13
44
|
Add these lines to your application's Gemfile:
|
14
45
|
|
15
46
|
```ruby
|
16
|
-
gem 'jsonapi-utils', '~> 0.4.
|
47
|
+
gem 'jsonapi-utils', '~> 0.4.6'
|
17
48
|
```
|
18
49
|
|
19
50
|
And then execute:
|
@@ -171,6 +202,19 @@ Content-Type: application/vnd.api+json
|
|
171
202
|
}
|
172
203
|
```
|
173
204
|
|
205
|
+
#### Params helpers
|
206
|
+
|
207
|
+
JU brings helper methods as a shortcut to get values from permitted params based on the resource configuration.
|
208
|
+
|
209
|
+
- `resource_params`:
|
210
|
+
- Returns the permitted params present in the `attributes` JSON member;
|
211
|
+
- Example: `{ name: 'Bilbo', gender: 'male', city: 'Shire' }`
|
212
|
+
- Same of calling: `params.require(:data).require(:attributes).permit(:name, :gender, :city)`
|
213
|
+
- `relationship_params`:
|
214
|
+
- Returns the relationship `id`s, distinguished by key, present in `relationships` JSON member;
|
215
|
+
- Example: `{ author: 1, posts: [1, 2, 3] }`
|
216
|
+
- Same as calling: `params.require(:relationships).require(:author).require(:data).permit(:id)`
|
217
|
+
|
174
218
|
## Full example
|
175
219
|
|
176
220
|
In order to start working with JU after installing the gem you simply need to do the following:
|
@@ -224,7 +268,7 @@ end
|
|
224
268
|
|
225
269
|
### Routes & Controllers
|
226
270
|
|
227
|
-
Let's define our routes using the `jsonapi_resources` and `jsonapi_links`
|
271
|
+
Let's define our routes using the `jsonapi_resources` and `jsonapi_links` methods provied by the `jsonapi-resources` gem:
|
228
272
|
|
229
273
|
```ruby
|
230
274
|
Rails.application.routes.draw do
|
@@ -235,11 +279,13 @@ Rails.application.routes.draw do
|
|
235
279
|
end
|
236
280
|
```
|
237
281
|
|
238
|
-
In our
|
282
|
+
In our Rails controller we just need to include the `JSONAPI::Utils` module.
|
283
|
+
|
284
|
+
> Note: with JU default rendering can be defined, like in the below example with `jsonapi_render_not_found` for when ActiveRecord doesn't find a record.
|
239
285
|
|
240
286
|
```ruby
|
241
287
|
# app/controllers/base_controller.rb
|
242
|
-
class BaseController <
|
288
|
+
class BaseController < ActionController::Base
|
243
289
|
include JSONAPI::Utils
|
244
290
|
protect_from_forgery with: :null_session
|
245
291
|
rescue_from ActiveRecord::RecordNotFound, with: :jsonapi_render_not_found
|
@@ -250,49 +296,43 @@ Finally, having inhirited `JSONAPI::Utils` methods from the `BaseController` we
|
|
250
296
|
|
251
297
|
```ruby
|
252
298
|
# app/controllers/users_controller.rb
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
299
|
+
# GET /users
|
300
|
+
def index
|
301
|
+
users = User.all
|
302
|
+
jsonapi_render json: users
|
303
|
+
end
|
258
304
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
305
|
+
# GET /users/:id
|
306
|
+
def show
|
307
|
+
user = User.find(params[:id])
|
308
|
+
jsonapi_render json: user
|
309
|
+
end
|
264
310
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
end
|
311
|
+
# POST /users
|
312
|
+
def create
|
313
|
+
user = User.new(resource_params)
|
314
|
+
if user.save
|
315
|
+
jsonapi_render json: user, status: :created
|
316
|
+
else
|
317
|
+
jsonapi_render_errors json: user, status: :unprocessable_entity
|
273
318
|
end
|
319
|
+
end
|
274
320
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
# DELETE /users/:id
|
286
|
-
def destroy
|
287
|
-
User.find(params[:id]).destroy
|
288
|
-
head :no_content
|
321
|
+
# PATCH /users/:id
|
322
|
+
def update
|
323
|
+
user = User.find(params[:id])
|
324
|
+
if user.update(resource_params)
|
325
|
+
jsonapi_render json: user
|
326
|
+
else
|
327
|
+
jsonapi_render_errors json: user, status: :unprocessable_entity
|
289
328
|
end
|
329
|
+
end
|
290
330
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
331
|
+
# DELETE /users/:id
|
332
|
+
def destroy
|
333
|
+
User.find(params[:id]).destroy
|
334
|
+
head :no_content
|
335
|
+
end
|
296
336
|
```
|
297
337
|
|
298
338
|
And:
|
@@ -324,12 +364,7 @@ class PostsController < BaseController
|
|
324
364
|
private
|
325
365
|
|
326
366
|
def post_params
|
327
|
-
|
328
|
-
.merge(user_id: author_params[:id])
|
329
|
-
end
|
330
|
-
|
331
|
-
def author_params
|
332
|
-
params.require(:relationships).require(:author).require(:data).permit(:id)
|
367
|
+
resource_params.merge(user_id: relationship_params[:author])
|
333
368
|
end
|
334
369
|
|
335
370
|
def load_user
|
@@ -348,8 +383,6 @@ JSONAPI.configure do |config|
|
|
348
383
|
config.json_key_format = :underscored_key
|
349
384
|
config.route_format = :dasherized_route
|
350
385
|
|
351
|
-
config.operations_processor = :active_record
|
352
|
-
|
353
386
|
config.allow_include = true
|
354
387
|
config.allow_sort = true
|
355
388
|
config.allow_filter = true
|
@@ -387,7 +420,7 @@ Here's some examples of requests – based on those sample [controllers](#routes
|
|
387
420
|
* [Relationships (identifier objects)](#relationships-identifier-objects)
|
388
421
|
* [Nested resources](#nested-resources)
|
389
422
|
|
390
|
-
####
|
423
|
+
#### Index
|
391
424
|
|
392
425
|
Request:
|
393
426
|
|
@@ -457,7 +490,7 @@ Content-Type: application/vnd.api+json
|
|
457
490
|
}
|
458
491
|
```
|
459
492
|
|
460
|
-
####
|
493
|
+
#### Index (options)
|
461
494
|
|
462
495
|
Request:
|
463
496
|
|
@@ -542,7 +575,7 @@ Content-Type: application/vnd.api+json
|
|
542
575
|
}
|
543
576
|
```
|
544
577
|
|
545
|
-
####
|
578
|
+
#### Show
|
546
579
|
|
547
580
|
Request:
|
548
581
|
|
@@ -582,7 +615,7 @@ Content-Type: application/vnd.api+json
|
|
582
615
|
}
|
583
616
|
```
|
584
617
|
|
585
|
-
####
|
618
|
+
#### Show (options)
|
586
619
|
|
587
620
|
Request:
|
588
621
|
|
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'jsonapi/utils'
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +10,5 @@ require "jsonapi/utils"
|
|
10
10
|
# require "pry"
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
-
require
|
13
|
+
require 'irb'
|
14
14
|
IRB.start
|
data/lib/jsonapi/utils.rb
CHANGED
@@ -1,12 +1,8 @@
|
|
1
|
-
|
2
1
|
require 'jsonapi-resources'
|
3
2
|
require 'jsonapi/utils/version'
|
4
3
|
require 'jsonapi/utils/exceptions'
|
5
4
|
require 'jsonapi/utils/request'
|
6
5
|
require 'jsonapi/utils/response'
|
7
|
-
require 'jsonapi/utils/support/filter/custom'
|
8
|
-
|
9
|
-
JSONAPI::Resource.extend JSONAPI::Utils::Support::Filter::Custom
|
10
6
|
|
11
7
|
module JSONAPI
|
12
8
|
module Utils
|
@@ -1,87 +1,47 @@
|
|
1
|
-
module JSONAPI
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
check_request
|
9
|
-
end
|
10
|
-
|
11
|
-
# Instantiate the request object.
|
12
|
-
#
|
13
|
-
# @return [JSONAPI::RequestParser]
|
14
|
-
#
|
15
|
-
# @api public
|
16
|
-
def setup_request
|
17
|
-
@request ||= JSONAPI::RequestParser.new(
|
18
|
-
params,
|
19
|
-
context: context,
|
20
|
-
key_formatter: key_formatter,
|
21
|
-
server_error_callbacks: (self.class.server_error_callbacks || [])
|
22
|
-
)
|
23
|
-
end
|
24
|
-
|
25
|
-
# Render an error response if the parsed request got any error.
|
26
|
-
#
|
27
|
-
# @api public
|
28
|
-
def check_request
|
29
|
-
@request.errors.blank? || jsonapi_render_errors(json: @request)
|
30
|
-
end
|
1
|
+
module JSONAPI
|
2
|
+
module Utils
|
3
|
+
module Request
|
4
|
+
def jsonapi_request_handling
|
5
|
+
setup_request
|
6
|
+
check_request
|
7
|
+
end
|
31
8
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
process_operations
|
42
|
-
render_results(@operation_results)
|
43
|
-
rescue => e
|
44
|
-
handle_exceptions(e)
|
45
|
-
end
|
9
|
+
def setup_request
|
10
|
+
@request ||=
|
11
|
+
JSONAPI::RequestParser.new(
|
12
|
+
params.dup,
|
13
|
+
context: context,
|
14
|
+
key_formatter: key_formatter,
|
15
|
+
server_error_callbacks: (self.class.server_error_callbacks || [])
|
16
|
+
)
|
17
|
+
end
|
46
18
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
#
|
51
|
-
# @api public
|
52
|
-
def resource_params
|
53
|
-
build_params_for(:resource)
|
54
|
-
end
|
19
|
+
def check_request
|
20
|
+
@request.errors.blank? || jsonapi_render_errors(json: @request)
|
21
|
+
end
|
55
22
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
#
|
60
|
-
# @api public
|
61
|
-
def relationship_params
|
62
|
-
build_params_for(:relationship)
|
63
|
-
end
|
23
|
+
def resource_params
|
24
|
+
build_params_for(:resource)
|
25
|
+
end
|
64
26
|
|
65
|
-
|
27
|
+
def relationship_params
|
28
|
+
build_params_for(:relationship)
|
29
|
+
end
|
66
30
|
|
67
|
-
|
68
|
-
# for either the main resource or relationships.
|
69
|
-
#
|
70
|
-
# @return [Hash]
|
71
|
-
#
|
72
|
-
# @api private
|
73
|
-
def build_params_for(param_type)
|
74
|
-
return {} if @request.operations.empty?
|
31
|
+
private
|
75
32
|
|
76
|
-
|
77
|
-
|
33
|
+
def build_params_for(param_type)
|
34
|
+
return {} if @request.operations.empty?
|
78
35
|
|
79
|
-
|
80
|
-
{}
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
36
|
+
keys = %i(attributes to_one to_many)
|
37
|
+
operation = @request.operations.find { |e| e.options[:data].keys & keys == keys }
|
38
|
+
if operation.nil?
|
39
|
+
{}
|
40
|
+
elsif param_type == :relationship
|
41
|
+
operation.options[:data].values_at(:to_one, :to_many).compact.reduce(&:merge)
|
42
|
+
else
|
43
|
+
operation.options[:data][:attributes]
|
44
|
+
end
|
85
45
|
end
|
86
46
|
end
|
87
47
|
end
|
@@ -1,14 +1,14 @@
|
|
1
|
-
require 'jsonapi/utils/support/
|
2
|
-
require 'jsonapi/utils/support/filter/default'
|
1
|
+
require 'jsonapi/utils/support/filter'
|
3
2
|
require 'jsonapi/utils/support/pagination'
|
4
3
|
require 'jsonapi/utils/support/sort'
|
4
|
+
require 'jsonapi/utils/support/error'
|
5
5
|
|
6
6
|
module JSONAPI
|
7
7
|
module Utils
|
8
8
|
module Response
|
9
9
|
module Support
|
10
10
|
include ::JSONAPI::Utils::Support::Error
|
11
|
-
include ::JSONAPI::Utils::Support::Filter
|
11
|
+
include ::JSONAPI::Utils::Support::Filter
|
12
12
|
include ::JSONAPI::Utils::Support::Pagination
|
13
13
|
include ::JSONAPI::Utils::Support::Sort
|
14
14
|
|
@@ -19,9 +19,8 @@ module JSONAPI
|
|
19
19
|
@_filter_params ||=
|
20
20
|
case params[:filter]
|
21
21
|
when Hash, ActionController::Parameters
|
22
|
-
|
23
|
-
|
24
|
-
hash[unformatted_field] = params[:filter][field]
|
22
|
+
params[:filter].keys.each_with_object({}) do |resource, hash|
|
23
|
+
hash[resource] = params[:filter][resource]
|
25
24
|
end
|
26
25
|
end
|
27
26
|
end
|
@@ -2,133 +2,64 @@ module JSONAPI
|
|
2
2
|
module Utils
|
3
3
|
module Support
|
4
4
|
module Pagination
|
5
|
-
# Apply proper pagination to the records.
|
6
|
-
#
|
7
|
-
# @param records [ActiveRecord::Relation, Array] collection of records
|
8
|
-
# e.g.: User.all or [{ id: 1, name: 'Tiago' }, { id: 2, name: 'Doug' }]
|
9
|
-
#
|
10
|
-
# @param options [Hash] JU's options
|
11
|
-
# e.g.: { resource: V2::UserResource, count: 100 }
|
12
|
-
#
|
13
|
-
# @return [ActiveRecord::Relation, Array]
|
14
|
-
#
|
15
|
-
# @api public
|
16
5
|
def apply_pagination(records, options = {})
|
17
6
|
return records unless apply_pagination?(options)
|
18
|
-
records.is_a?(Array) ? records[paginate_with(:range)] : paginate_with(:paginator).apply(records, nil)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Mount pagination params for JSONAPI::ResourcesOperationResult.
|
22
|
-
# It can also be used anywhere else as a helper method.
|
23
|
-
#
|
24
|
-
# @param records [ActiveRecord::Relation, Array] collection of records
|
25
|
-
# e.g.: User.all or [{ id: 1, name: 'Tiago' }, { id: 2, name: 'Doug' }]
|
26
|
-
#
|
27
|
-
# @param options [Hash] JU's options
|
28
|
-
# e.g.: { resource: V2::UserResource, count: 100 }
|
29
|
-
#
|
30
|
-
# @return [Hash]
|
31
|
-
# e.g.: {"first"=>{"number"=>1, "size"=>2}, "next"=>{"number"=>2, "size"=>2}, "last"=>{"number"=>2, "size"=>2}}
|
32
|
-
#
|
33
|
-
# @api public
|
34
|
-
def pagination_params(records, options)
|
35
|
-
return {} unless JSONAPI.configuration.top_level_links_include_pagination
|
36
|
-
paginator.links_page_params(record_count: count_records(records, options))
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
7
|
|
41
|
-
|
42
|
-
#
|
43
|
-
# @return [PagedPaginator, OffsetPaginator]
|
44
|
-
#
|
45
|
-
# @api private
|
46
|
-
def paginator
|
47
|
-
@paginator ||= paginator_klass.new(page_params)
|
48
|
-
end
|
8
|
+
pagination = set_pagination
|
49
9
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
"#{JSONAPI.configuration.default_paginator}_paginator".classify.constantize
|
10
|
+
records =
|
11
|
+
if records.is_a?(Array)
|
12
|
+
records[pagination[:range]]
|
13
|
+
else
|
14
|
+
pagination[:paginator].apply(records, nil)
|
15
|
+
end
|
57
16
|
end
|
58
17
|
|
59
|
-
# Check whether pagination should be applied to the response.
|
60
|
-
#
|
61
|
-
# @return [Boolean]
|
62
|
-
#
|
63
|
-
# @api private
|
64
18
|
def apply_pagination?(options)
|
65
19
|
JSONAPI.configuration.default_paginator != :none &&
|
66
20
|
(options[:paginate].nil? || options[:paginate])
|
67
21
|
end
|
68
22
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
23
|
+
def pagination_params(records, options)
|
24
|
+
@paginator ||= paginator(params)
|
25
|
+
if @paginator && JSONAPI.configuration.top_level_links_include_pagination
|
26
|
+
options = {}
|
27
|
+
@paginator.class.requires_record_count &&
|
28
|
+
options[:record_count] = count_records(records, options)
|
29
|
+
@paginator.links_page_params(options)
|
30
|
+
else
|
31
|
+
{}
|
78
32
|
end
|
79
33
|
end
|
80
34
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
#
|
90
|
-
# @api private
|
91
|
-
def paginate_with(kind)
|
92
|
-
@pagination ||=
|
93
|
-
case kind
|
94
|
-
when :paginator then paginator
|
95
|
-
when :range then pagination_range
|
35
|
+
def paginator(params)
|
36
|
+
page_params = ActionController::Parameters.new(params[:page] || {})
|
37
|
+
|
38
|
+
@paginator ||=
|
39
|
+
if JSONAPI.configuration.default_paginator == :paged
|
40
|
+
PagedPaginator.new(page_params)
|
41
|
+
elsif JSONAPI.configuration.default_paginator == :offset
|
42
|
+
OffsetPaginator.new(page_params)
|
96
43
|
end
|
97
44
|
end
|
98
45
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
#
|
104
|
-
# @api private
|
105
|
-
def pagination_range
|
106
|
-
case JSONAPI.configuration.default_paginator
|
107
|
-
when :paged
|
46
|
+
def set_pagination
|
47
|
+
page_params = ActionController::Parameters.new(@request.params[:page] || {})
|
48
|
+
if JSONAPI.configuration.default_paginator == :paged
|
49
|
+
@_paginator ||= PagedPaginator.new(page_params)
|
108
50
|
number = page_params['number'].to_i.nonzero? || 1
|
109
51
|
size = page_params['size'].to_i.nonzero? || JSONAPI.configuration.default_page_size
|
110
|
-
(number - 1) * size..number * size - 1
|
111
|
-
|
52
|
+
{ paginator: @_paginator, range: (number - 1) * size..number * size - 1 }
|
53
|
+
elsif JSONAPI.configuration.default_paginator == :offset
|
54
|
+
@_paginator ||= OffsetPaginator.new(page_params)
|
112
55
|
offset = page_params['offset'].to_i.nonzero? || 0
|
113
56
|
limit = page_params['limit'].to_i.nonzero? || JSONAPI.configuration.default_page_size
|
114
|
-
offset..offset + limit - 1
|
57
|
+
{ paginator: @_paginator, range: offset..offset + limit - 1 }
|
115
58
|
else
|
116
|
-
|
59
|
+
{}
|
117
60
|
end
|
118
61
|
end
|
119
62
|
|
120
|
-
# Count records in order to build a proper pagination and to fill up the "record_count" response's member.
|
121
|
-
#
|
122
|
-
# @param records [ActiveRecord::Relation, Array] collection of records
|
123
|
-
# e.g.: User.all or [{ id: 1, name: 'Tiago' }, { id: 2, name: 'Doug' }]
|
124
|
-
#
|
125
|
-
# @param options [Hash] JU's options
|
126
|
-
# e.g.: { resource: V2::UserResource, count: 100 }
|
127
|
-
#
|
128
|
-
# @return [Integer]
|
129
|
-
# e.g.: 42
|
130
|
-
#
|
131
|
-
# @api private
|
132
63
|
def count_records(records, options)
|
133
64
|
if options[:count].present?
|
134
65
|
options[:count]
|
@@ -1,53 +1,36 @@
|
|
1
|
-
module JSONAPI
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
# e.g.: User.all or [{ id: 1, name: 'Tiago' }, { id: 2, name: 'Doug' }]
|
8
|
-
#
|
9
|
-
# @return [ActiveRecord::Relation, Array]
|
10
|
-
#
|
11
|
-
# @api public
|
12
|
-
def apply_sort(records)
|
13
|
-
return records unless params[:sort].present?
|
1
|
+
module JSONAPI
|
2
|
+
module Utils
|
3
|
+
module Support
|
4
|
+
module Sort
|
5
|
+
def apply_sort(records)
|
6
|
+
return records unless params[:sort].present?
|
14
7
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
8
|
+
if records.is_a?(Array)
|
9
|
+
records.sort { |a, b| comp = 0; eval(sort_criteria) }
|
10
|
+
elsif records.respond_to?(:order)
|
11
|
+
records.order(sort_params)
|
12
|
+
end
|
13
|
+
end
|
21
14
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
@sort_criteria ||=
|
30
|
-
sort_params.reduce('') do |sum, (key, value)|
|
31
|
-
comparables = ["a[:#{key}]", "b[:#{key}]"]
|
32
|
-
comparables.reverse! if value == :desc
|
33
|
-
sum + "comp = comp == 0 ? #{comparables.join(' <=> ')} : comp; "
|
15
|
+
def sort_criteria
|
16
|
+
@sort_criteria ||=
|
17
|
+
sort_params.reduce('') do |sum, (key, value)|
|
18
|
+
comparables = ["a[:#{key}]", "b[:#{key}]"]
|
19
|
+
comparables.reverse! if value == :desc
|
20
|
+
sum + "comp = comp == 0 ? #{comparables.join(' <=> ')} : comp; "
|
21
|
+
end
|
34
22
|
end
|
35
|
-
end
|
36
23
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
params[:sort].split(',').each_with_object({}) do |field, hash|
|
46
|
-
unformatted_field = @request.unformat_key(field)
|
47
|
-
desc, field = unformatted_field.to_s.match(/^([-_])?(\w+)$/i)[1..2]
|
48
|
-
hash[field] = desc.present? ? :desc : :asc
|
49
|
-
end
|
24
|
+
def sort_params
|
25
|
+
@_sort_params ||=
|
26
|
+
if params[:sort].present?
|
27
|
+
params[:sort].split(',').each_with_object({}) do |criteria, hash|
|
28
|
+
order, field = criteria.match(/(\-?)(\w+)/i)[1..2]
|
29
|
+
hash[field] = order == '-' ? :desc : :asc
|
30
|
+
end
|
31
|
+
end
|
50
32
|
end
|
33
|
+
end
|
51
34
|
end
|
52
35
|
end
|
53
36
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonapi-utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tiago Guedes
|
@@ -9,22 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-08-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: jsonapi-resources
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- -
|
18
|
+
- - '='
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 0.8.0
|
20
|
+
version: 0.8.0.beta1
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- -
|
25
|
+
- - '='
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 0.8.0
|
27
|
+
version: 0.8.0.beta1
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: bundler
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -174,8 +174,6 @@ files:
|
|
174
174
|
- lib/jsonapi/utils/response/support.rb
|
175
175
|
- lib/jsonapi/utils/support/error.rb
|
176
176
|
- lib/jsonapi/utils/support/filter.rb
|
177
|
-
- lib/jsonapi/utils/support/filter/custom.rb
|
178
|
-
- lib/jsonapi/utils/support/filter/default.rb
|
179
177
|
- lib/jsonapi/utils/support/pagination.rb
|
180
178
|
- lib/jsonapi/utils/support/sort.rb
|
181
179
|
- lib/jsonapi/utils/version.rb
|
@@ -194,14 +192,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
194
192
|
version: '0'
|
195
193
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
196
194
|
requirements:
|
197
|
-
- - "
|
195
|
+
- - ">"
|
198
196
|
- !ruby/object:Gem::Version
|
199
|
-
version:
|
197
|
+
version: 1.3.1
|
200
198
|
requirements: []
|
201
199
|
rubyforge_project:
|
202
|
-
rubygems_version: 2.6.
|
200
|
+
rubygems_version: 2.6.2
|
203
201
|
signing_key:
|
204
202
|
specification_version: 4
|
205
203
|
summary: JSON::Utils is a simple way to get a full-featured JSON API serialization
|
206
204
|
for your controller's responses.
|
207
205
|
test_files: []
|
206
|
+
has_rdoc:
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module JSONAPI::Utils::Support::Filter
|
2
|
-
module Custom
|
3
|
-
def _custom_filters
|
4
|
-
@_allowed_custom_filters || []
|
5
|
-
end
|
6
|
-
|
7
|
-
def custom_filters(*attrs)
|
8
|
-
attrs.each { |attr| custom_filter(attr) }
|
9
|
-
end
|
10
|
-
|
11
|
-
def custom_filter(attr)
|
12
|
-
attr = attr.to_sym
|
13
|
-
@_allowed_filters[attr] = {}
|
14
|
-
@_allowed_custom_filters ||= []
|
15
|
-
@_allowed_custom_filters |= [attr]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
module JSONAPI::Utils::Support::Filter
|
2
|
-
module Default
|
3
|
-
# Apply default equality filters.
|
4
|
-
# e.g.: User.where(name: 'Foobar')
|
5
|
-
#
|
6
|
-
# @param records [ActiveRecord::Relation, Array] collection of records
|
7
|
-
# e.g.: User.all or [{ id: 1, name: 'Tiago' }, { id: 2, name: 'Doug' }]
|
8
|
-
#
|
9
|
-
# @param options [Hash] JU's options
|
10
|
-
# e.g.: { filter: false, paginate: false }
|
11
|
-
#
|
12
|
-
# @return [ActiveRecord::Relation, Array]
|
13
|
-
#
|
14
|
-
# @api public
|
15
|
-
def apply_filter(records, options = {})
|
16
|
-
if apply_filter?(records, options)
|
17
|
-
records.where(filter_params)
|
18
|
-
else
|
19
|
-
records
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# Check whether default filters should be applied.
|
24
|
-
#
|
25
|
-
# @param records [ActiveRecord::Relation, Array] collection of records
|
26
|
-
# e.g.: User.all or [{ id: 1, name: 'Tiago' }, { id: 2, name: 'Doug' }]
|
27
|
-
#
|
28
|
-
# @param options [Hash] JU's options
|
29
|
-
# e.g.: { filter: false, paginate: false }
|
30
|
-
#
|
31
|
-
# @return [Boolean]
|
32
|
-
#
|
33
|
-
# @api public
|
34
|
-
def apply_filter?(records, options = {})
|
35
|
-
params[:filter].present? && records.respond_to?(:where) &&
|
36
|
-
(options[:filter].nil? || options[:filter])
|
37
|
-
end
|
38
|
-
|
39
|
-
# Build a Hash with the default filters.
|
40
|
-
#
|
41
|
-
# @return [Hash, NilClass]
|
42
|
-
#
|
43
|
-
# @api public
|
44
|
-
def filter_params
|
45
|
-
@_filter_params ||=
|
46
|
-
case params[:filter]
|
47
|
-
when Hash, ActionController::Parameters
|
48
|
-
default_filters.each_with_object({}) do |field, hash|
|
49
|
-
unformatted_field = @request.unformat_key(field)
|
50
|
-
hash[unformatted_field] = params[:filter][field]
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
# Take all allowed filters and remove the custom ones.
|
58
|
-
#
|
59
|
-
# @return [Array]
|
60
|
-
#
|
61
|
-
# @api private
|
62
|
-
def default_filters
|
63
|
-
params[:filter].keys.map(&:to_sym) - @request.resource_klass._custom_filters
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|