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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cef6f1279f2c02d4fa7c4672b6c74f7920c17875b05d2bad161d0e6c0776ce45
4
- data.tar.gz: 0ffe8a25b91a4f5df7e58fa2cadc449912f654c3dddb9497403db5e66a8bffae
3
+ metadata.gz: 7de8095eaab5c863a6c9f5b400a7457cb89231751c5d1c7005a62b221e9399ad
4
+ data.tar.gz: b706f80a2097cc969e82b6a1b7894ce0ebc47dfa62dbacf5f5f44d167fbcfe00
5
5
  SHA512:
6
- metadata.gz: b91918c357e2745abd0813d9b5ce181e8fd9e7262d000591fe5910cf2c3d97942ddc65fc659b00120abd89246d1e3b2e2075fe66d85091d0477fe5ea7617fd45
7
- data.tar.gz: c6771c3aa0d76a0b4f176df986ca3bd556f6417723f6af5d6fcbc037415fce66333b8d56d163662c3093bbee5b70d42ea3e4b72b29acea29d4b03a30e06ae3d9
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`.
@@ -3,3 +3,4 @@
3
3
  require 'jsonapi/exceptions'
4
4
  require 'jsonapi/scopes/filters'
5
5
  require 'jsonapi/scopes/sorts'
6
+ require 'jsonapi/scopes/includes'
@@ -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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jsonapi
4
4
  module Scopes
5
- VERSION = '0.3.0'
5
+ VERSION = '0.4.0'
6
6
  end
7
7
  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.3.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-16 00:00:00.000000000 Z
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