jsonapi-scopes 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +46 -2
- data/lib/jsonapi/scopes.rb +1 -0
- data/lib/jsonapi/scopes/includes.rb +48 -0
- data/lib/jsonapi/scopes/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7de8095eaab5c863a6c9f5b400a7457cb89231751c5d1c7005a62b221e9399ad
|
4
|
+
data.tar.gz: b706f80a2097cc969e82b6a1b7894ce0ebc47dfa62dbacf5f5f44d167fbcfe00
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad5bf7eac4bb99005274a0d8d0fc83e87af270edea7af5b93666471fc8566d3d57a320e21e508c3680412b0d6566d7bde5416497e1020fdb7ff4b1ec8451cede
|
7
|
+
data.tar.gz: 14281865842d6ca46f28ee9c0ce6be5820a2f82fa2196df9ccfc28b7cd646e33015cb2bb9b685b661e59b968eaead5f3e9c674fd3b70ffea7f7a5bb326a7ead8
|
data/README.md
CHANGED
@@ -40,7 +40,7 @@ class Contact < ActiveRecord::Base
|
|
40
40
|
end
|
41
41
|
```
|
42
42
|
|
43
|
-
You can use `apply_filter` in your controller to use the scopes defined with the previous `filter` method
|
43
|
+
You can use `apply_filter` in your controller to use the scopes defined with the previous `filter` method:
|
44
44
|
|
45
45
|
```ruby
|
46
46
|
class ContactsController < ApplicationController
|
@@ -68,7 +68,7 @@ class Contact < ActiveRecord::Base
|
|
68
68
|
end
|
69
69
|
```
|
70
70
|
|
71
|
-
You can use `apply_sort` in your controller
|
71
|
+
You can use `apply_sort` in your controller:
|
72
72
|
|
73
73
|
```ruby
|
74
74
|
class ContactsController < ApplicationController
|
@@ -96,6 +96,50 @@ Or use negative sort `/contacts?sort=-firstname` to sort by firstname in `desc`
|
|
96
96
|
You can even combine multiple sort `/contacts?sort=lastname,-firstname`
|
97
97
|
|
98
98
|
|
99
|
+
### Included relationships
|
100
|
+
This gem supports [request include params](https://jsonapi.org/format/#fetching-includes). It's very useful when you need to load related resources on client side.
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
class Post < ActiveRecord::Base
|
104
|
+
include Jsonapi::Include
|
105
|
+
|
106
|
+
has_many :comments
|
107
|
+
belongs_to :author
|
108
|
+
|
109
|
+
allowed_includes 'comments', 'author.posts' # List of allowed includes
|
110
|
+
end
|
111
|
+
```
|
112
|
+
|
113
|
+
You can use `apply_include` in your controller:
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
class PostsController < ApplicationController
|
117
|
+
def index
|
118
|
+
@posts = Post.apply_include(params)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
```
|
122
|
+
|
123
|
+
`apply_include` accepts a second parameter to override data set with `allowed_includes` for a specific controller.
|
124
|
+
```ruby
|
125
|
+
class PostsController < ApplicationController
|
126
|
+
def index
|
127
|
+
@posts = Post.apply_sort(params, allowed: 'comments') # to allow only comments.
|
128
|
+
# Or @posts = Post.apply_sort(params, allowed: ['comments', 'author'])
|
129
|
+
end
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
133
|
+
Then you can hit `/posts?include=comments`. You can even combine multiple includes like `/posts?include=comments,author`.
|
134
|
+
|
135
|
+
The gem only handle `include` on the ActiveRecord level. If you want to serialize the data, you must do it in your controller.
|
136
|
+
|
137
|
+
#### Nested relationships
|
138
|
+
|
139
|
+
You can load nested relationships using the dot `.` notation:
|
140
|
+
|
141
|
+
`/posts?include=author.posts`.
|
142
|
+
|
99
143
|
### Rescuing a Bad Request in Rails
|
100
144
|
|
101
145
|
Jsonapi::scope raises a `Jsonapi::InvalidAttributeError` you can [rescue_from](https://guides.rubyonrails.org/action_controller_overview.html#rescue-from) in your `ApplicationController`.
|
data/lib/jsonapi/scopes.rb
CHANGED
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jsonapi
|
4
|
+
module Include
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
@allowed_includes ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def allowed_includes(*fields)
|
13
|
+
@allowed_includes = fields
|
14
|
+
end
|
15
|
+
|
16
|
+
def apply_include(params = {}, options = { allowed: [] })
|
17
|
+
records = all
|
18
|
+
fields = params.dig(:include).to_s
|
19
|
+
|
20
|
+
return records if fields.blank?
|
21
|
+
|
22
|
+
allowed_fields = (Array.wrap(options[:allowed]).presence || @allowed_includes).map(&:to_s)
|
23
|
+
|
24
|
+
fields.split(',').each do |field|
|
25
|
+
raise InvalidAttributeError, "#{field} is not valid as include attribute." unless allowed_fields.include?(field)
|
26
|
+
end
|
27
|
+
|
28
|
+
records.includes(convert_includes_as_hash(fields))
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def convert_includes_as_hash(includes)
|
34
|
+
includes.split(',').map(&:squish).each_with_object({}) do |value, hash|
|
35
|
+
params = value.split('.')
|
36
|
+
key = params.first.to_sym
|
37
|
+
hash[key] ||= {}
|
38
|
+
|
39
|
+
next if params.size <= 1
|
40
|
+
|
41
|
+
remaining_fields = params[1..-1].join('.')
|
42
|
+
|
43
|
+
hash[key].merge!(convert_includes_as_hash(remaining_fields))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonapi-scopes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Guillaume Briday
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-09-
|
11
|
+
date: 2019-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -51,6 +51,7 @@ files:
|
|
51
51
|
- lib/jsonapi/exceptions.rb
|
52
52
|
- lib/jsonapi/scopes.rb
|
53
53
|
- lib/jsonapi/scopes/filters.rb
|
54
|
+
- lib/jsonapi/scopes/includes.rb
|
54
55
|
- lib/jsonapi/scopes/sorts.rb
|
55
56
|
- lib/jsonapi/scopes/version.rb
|
56
57
|
homepage: https://github.com/guillaumebriday/jsonapi-scopes
|