jsonapi-utils 0.4.9 → 0.5.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/jsonapi-utils.svg)](https://badge.fury.io/rb/jsonapi-utils)
|
5
5
|
[![Build Status](https://travis-ci.org/b2beauty/jsonapi-utils.svg?branch=master)](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
|