jsonapi-utils 0.7.2 → 0.7.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 81b9858b8125f047d7c6b26ed950d98072c6af8b
4
- data.tar.gz: b7436b63bbc441f6592f6ada45cedace0633fa9c
2
+ SHA256:
3
+ metadata.gz: 56b5970b70c6944e7c5c536f0b92c2bd8d2503d5447886862b72bfabcf85e943
4
+ data.tar.gz: c07bf056d10c8550c511bdd180dec8393858e45a5de37450ef323367bcc243aa
5
5
  SHA512:
6
- metadata.gz: 1285cd935d1acab08e5f950290c2eabb744420aeac9312877e856ee1a9a16e0dace61d6797b60ed8b48994e67860fbc2f299c0a2169a48ef1939c9a52565425c
7
- data.tar.gz: 9ab8279a639f27b412c8b7aec1857f4c4db9e7f928487950b6118afe6c30c5ecd40b9b97e2035f706e9eea4557d6e5772776dff848ddc424c382e676fc6df999
6
+ metadata.gz: 4aa949f97e9e0795dc6686d393767c4a1ad6c9084815a4f1aa10c0f912fc5901192b194204510936cb55a8136ef3467534aaa76132f334dd7f9127920281bc32
7
+ data.tar.gz: 26e1483f33628891ab311e6e9e3b71e88de5c3e5a9da4d3ae425ae62ea7efd7496acf0a99707de58db4a04d4b3bf33e911d4e11ec8996ba9e9f519e7ffd74c3b
data/README.md CHANGED
@@ -54,7 +54,7 @@ end
54
54
  Support:
55
55
 
56
56
  * Ruby 1.9+ with Rails 4
57
- * Ruby 2.3+ with Rails 5
57
+ * Ruby 2.4+ with Rails 5
58
58
 
59
59
  For Rails 4 add this to your application's Gemfile:
60
60
 
@@ -62,10 +62,10 @@ For Rails 4 add this to your application's Gemfile:
62
62
  gem 'jsonapi-utils', '~> 0.4.9'
63
63
  ```
64
64
 
65
- For Rails 5:
65
+ For Rails 5+:
66
66
 
67
67
  ```ruby
68
- gem 'jsonapi-utils', '~> 0.7.2'
68
+ gem 'jsonapi-utils', '~> 0.7.3'
69
69
  ```
70
70
 
71
71
  And then execute:
@@ -225,12 +225,12 @@ class CustomPaginator < JSONAPI::Paginator
225
225
  end
226
226
  ```
227
227
 
228
- And then it can be either set at the resource class level (e.g. UserResource.paginator :custom_paginator) or via config initializer:
228
+ And then it can be either set at the resource class level (e.g. UserResource.paginator :custom) or via config initializer:
229
229
 
230
230
  ```ruby
231
231
  # config/initializers/jsonapi_resources.rb
232
232
  JSONAPI.configure do |config|
233
- config.default_paginator = :custom_paginator
233
+ config.default_paginator = :custom
234
234
  end
235
235
  ```
236
236
 
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'rspec' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("rspec-core", "rspec")
@@ -6,6 +6,11 @@ module JSONAPI::Utils
6
6
  def jsonapi_request_handling
7
7
  setup_request
8
8
  check_request
9
+ rescue JSONAPI::Exceptions::InvalidResource,
10
+ JSONAPI::Exceptions::InvalidField,
11
+ JSONAPI::Exceptions::InvalidInclude,
12
+ JSONAPI::Exceptions::InvalidSortCriteria => err
13
+ jsonapi_render_errors(json: err)
9
14
  end
10
15
 
11
16
  # Instantiate the request object.
@@ -15,6 +15,11 @@ module JSONAPI
15
15
  # @option options [JSONAPI::Resource] resource: it tells the formatter which resource
16
16
  # class to be used rather than use an infered one (default behaviour)
17
17
  #
18
+ # @option options [JSONAPI::Resource] source: it tells the formatter that this response is from a related resource
19
+ # and the result should be interpreted as a related resources response
20
+ #
21
+ # @option options [String, Symbol] relationship_type: it tells that the formatter which relationship the data is from
22
+ #
18
23
  # @option options [ActiveRecord::Base] model: ActiveRecord model class to be instantiated
19
24
  # when a Hash or Array of Hashes is passed as the "object" argument
20
25
  #
@@ -27,7 +32,7 @@ module JSONAPI
27
32
  # @api public
28
33
  def jsonapi_format(object, options = {})
29
34
  if object.is_a?(Hash)
30
- hash = object.with_indifferent_access
35
+ hash = object.with_indifferent_access
31
36
  object = hash_to_active_record(hash[:data], options[:model])
32
37
  end
33
38
  fix_custom_request_options(object)
@@ -51,7 +56,7 @@ module JSONAPI
51
56
  # @api public
52
57
  def jsonapi_format_errors(object)
53
58
  if active_record_obj?(object)
54
- object = JSONAPI::Utils::Exceptions::ActiveRecord.new(object, @request.resource_klass, context)
59
+ object = JSONAPI::Utils::Exceptions::ActiveRecord.new(object, @request.resource_klass, context)
55
60
  end
56
61
  errors = object.respond_to?(:errors) ? object.errors : object
57
62
  JSONAPI::Utils::Support::Error.sanitize(errors).uniq
@@ -77,12 +82,15 @@ module JSONAPI
77
82
  # Build the full response document.
78
83
  #
79
84
  # @param object [ActiveRecord::Base, ActiveRecord::Relation, Hash, Array<Hash>]
80
- # Object to be formatted into JSON
81
- # e.g.: User.first, User.all, { data: { id: 1, first_name: 'Tiago' } },
82
- # [{ data: { id: 1, first_name: 'Tiago' } }]
85
+ # Object to be formatted into JSON.
83
86
  #
84
- # @option options [JSONAPI::Resource] resource: it tells the builder which resource
85
- # class to be used rather than use an infered one (default behaviour)
87
+ # @option options [JSONAPI::Resource] :resource which resource class to be used
88
+ # rather than using the default one (inferred)
89
+ #
90
+ # @option options [ActiveRecord::Base, JSONAPI::Resource] :source source of related resource,
91
+ # the result should be interpreted as a related resources response
92
+ #
93
+ # @option options [String, Symbol] :relationship which relationship the data is from
86
94
  #
87
95
  # @option options [Integer] count: if it's rendering a collection of resources, the default
88
96
  # gem's counting method can be bypassed by the use of this options. It's shows then the total
@@ -95,8 +103,7 @@ module JSONAPI
95
103
  results = JSONAPI::OperationResults.new
96
104
 
97
105
  if object.respond_to?(:to_ary)
98
- records = build_collection(object, options)
99
- results.add_result(JSONAPI::ResourcesOperationResult.new(:ok, records, result_options(object, options)))
106
+ results.add_result(build_collection_result(object, options))
100
107
  else
101
108
  record = turn_into_resource(object, options)
102
109
  results.add_result(JSONAPI::ResourceOperationResult.new(:ok, record))
@@ -105,6 +112,68 @@ module JSONAPI
105
112
  @_response_document = create_response_document(results)
106
113
  end
107
114
 
115
+ # Build the result operation object for collection actions.
116
+ #
117
+ # @param object [ActiveRecord::Relation, Array<Hash>]
118
+ # Object to be formatted into JSON.
119
+ #
120
+ # @option options [JSONAPI::Resource] :resource which resource class to be used
121
+ # rather than using the default one (inferred)
122
+ #
123
+ # @option options [ActiveRecord::Base, JSONAPI::Resource] :source parent model/resource
124
+ # of the related resource
125
+ #
126
+ # @option options [String, Symbol] :relationship which relationship the data is from
127
+ #
128
+ # @option options [Integer] count: if it's rendering a collection of resources, the default
129
+ # gem's counting method can be bypassed by the use of this options. It's shows then the total
130
+ # records resulting from that request and also calculates the pagination.
131
+ #
132
+ # @return [JSONAPI::ResourcesOperationResult, JSONAPI::RelatedResourcesOperationResult]
133
+ #
134
+ # @api private
135
+ def build_collection_result(object, options)
136
+ records = build_collection(object, options)
137
+ result_options = result_options(object, options)
138
+
139
+ if related_resource_operation?(options)
140
+ source_resource = turn_source_into_resource(options[:source])
141
+ relationship_type = get_source_relationship(options)
142
+
143
+ JSONAPI::RelatedResourcesOperationResult.new(
144
+ :ok,
145
+ source_resource,
146
+ relationship_type,
147
+ records,
148
+ result_options
149
+ )
150
+ else
151
+ JSONAPI::ResourcesOperationResult.new(:ok, records, result_options)
152
+ end
153
+ end
154
+
155
+ # Is this a request for related resources?
156
+ #
157
+ # In order to answer that it needs to check for some {options}
158
+ # controller params like {params[:source]} and {params[:relationship]}.
159
+ #
160
+ # @option options [Boolean] :related when true, jsonapi-utils infers the parent and
161
+ # related resources from controller's {params} values.
162
+ #
163
+ # @option options [ActiveRecord::Base, JSONAPI::Resource] :source parent model/resource
164
+ # of the related resource
165
+ #
166
+ # @option options [String, Symbol] :relationship which relationship the data is from
167
+ #
168
+ # @return [Boolean]
169
+ #
170
+ # @api private
171
+ def related_resource_operation?(options)
172
+ (options[:related] || options[:source].present?) &&
173
+ params[:source].present? &&
174
+ params[:relationship].present?
175
+ end
176
+
108
177
  # Apply a proper action setup for custom requests/actions.
109
178
  #
110
179
  # @note The setup_(index|show)_action comes from JSONAPI::Resources' API.
@@ -134,10 +203,9 @@ module JSONAPI
134
203
  # Objects to be instantiated as JSONAPI::Resource ones.
135
204
  # e.g.: User.all, [{ data: { id: 1, first_name: 'Tiago' } }]
136
205
  #
137
- # @option options [JSONAPI::Resource] resource: it tells the buider which resource
138
- # class to be used rather than use an infered one (default behaviour)
206
+ # @option options [JSONAPI::Resource] :resource it resource class to be used rather than default one (infered)
139
207
  #
140
- # @option options [Integer] count: if it's rendering a collection of resources, the default
208
+ # @option options [Integer] :count if it's rendering a collection of resources, the default
141
209
  # gem's counting method can be bypassed by the use of this options. It's shows then the total
142
210
  # records resulting from that request and also calculates the pagination.
143
211
  #
@@ -171,6 +239,30 @@ module JSONAPI
171
239
  end
172
240
  end
173
241
 
242
+ # Get JSONAPI::Resource for source object
243
+ #
244
+ # @param record [ActiveRecord::Base, JSONAPI::Resource]
245
+ #
246
+ # @return [JSONAPI::Resource]
247
+ #
248
+ # @api private
249
+ def turn_source_into_resource(record)
250
+ return record if record.kind_of?(JSONAPI::Resource)
251
+ @request.source_klass.new(record, context)
252
+ end
253
+
254
+ # Get relationship type of source object
255
+ #
256
+ # @option options [Symbol] relationship: it tells which relationship
257
+ # to be used rather than use an infered one (default behaviour)
258
+ #
259
+ # @return [Symbol]
260
+ #
261
+ # @api private
262
+ def get_source_relationship(options)
263
+ options[:relationship]&.to_sym || @request.resource_klass._type
264
+ end
265
+
174
266
  # Apply some result options like pagination params and record count to collection responses.
175
267
  #
176
268
  # @param records [ActiveRecord::Relation, Hash, Array<Hash>]
@@ -186,8 +278,7 @@ module JSONAPI
186
278
  # @api private
187
279
  def result_options(records, options)
188
280
  {}.tap do |data|
189
- if JSONAPI.configuration.default_paginator != :none &&
190
- JSONAPI.configuration.top_level_links_include_pagination
281
+ if include_pagination_links?
191
282
  data[:pagination_params] = pagination_params(records, options)
192
283
  end
193
284
 
@@ -195,7 +286,7 @@ module JSONAPI
195
286
  data[:record_count] = record_count_for(records, options)
196
287
  end
197
288
 
198
- if JSONAPI.configuration.top_level_meta_include_page_count
289
+ if include_page_count?
199
290
  data[:page_count] = page_count_for(data[:record_count])
200
291
  end
201
292
  end
@@ -14,6 +14,11 @@ module JSONAPI
14
14
  #
15
15
  # @option options [JSONAPI::Resource] resource: it tells the render which resource
16
16
  # class to be used rather than use an infered one (default behaviour)
17
+ #
18
+ # @option options [JSONAPI::Resource] source_resource: it tells the render that this response is from a related resource
19
+ # and the result should be interpreted as a related resources response
20
+ #
21
+ # @option options [String, Symbol] relationship_type: it tells that the render which relationship the data is from
17
22
  #
18
23
  # @option options [ActiveRecord::Base] model: ActiveRecord model class to be instantiated
19
24
  # when a Hash or Array of Hashes is passed to the "json" key argument
@@ -4,20 +4,40 @@ module JSONAPI
4
4
  module Pagination
5
5
  RecordCountError = Class.new(ArgumentError)
6
6
 
7
+ # Check whether pagination links should be included.
8
+ #
9
+ # @api public
10
+ # @return [Boolean]
11
+ def include_pagination_links?
12
+ JSONAPI.configuration.default_paginator != :none &&
13
+ JSONAPI.configuration.top_level_links_include_pagination
14
+ end
15
+
16
+ # Check whether pagination's page count should be included
17
+ # on the "meta" key.
18
+ #
19
+ # @api public
20
+ # @return [Boolean]
21
+ def include_page_count?
22
+ JSONAPI.configuration.top_level_meta_include_page_count
23
+ end
24
+
7
25
  # Apply proper pagination to the records.
8
26
  #
9
27
  # @param records [ActiveRecord::Relation, Array] collection of records
10
28
  # e.g.: User.all or [{ id: 1, name: 'Tiago' }, { id: 2, name: 'Doug' }]
11
29
  #
12
- # @param options [Hash] JU's options
30
+ # @param options [Hash] JSONAPI::Utils' options
13
31
  # e.g.: { resource: V2::UserResource, count: 100 }
14
32
  #
15
33
  # @return [ActiveRecord::Relation, Array]
16
34
  #
17
35
  # @api public
18
36
  def apply_pagination(records, options = {})
19
- return records unless apply_pagination?(options)
20
- records.is_a?(Array) ? records[paginate_with(:range)] : paginate_with(:paginator).apply(records, nil)
37
+ if !apply_pagination?(options) then records
38
+ elsif records.is_a?(Array) then records[paginate_with(:range)]
39
+ else paginate_with(:paginator).apply(records, nil)
40
+ end
21
41
  end
22
42
 
23
43
  # Mount pagination params for JSONAPI::ResourcesOperationResult.
@@ -32,9 +52,10 @@ module JSONAPI
32
52
  # @return [Hash]
33
53
  # e.g.: {"first"=>{"number"=>1, "size"=>2}, "next"=>{"number"=>2, "size"=>2}, "last"=>{"number"=>2, "size"=>2}}
34
54
  #
55
+ #
35
56
  # @api public
36
57
  def pagination_params(records, options)
37
- return {} unless JSONAPI.configuration.top_level_links_include_pagination
58
+ return {} unless include_pagination_links?
38
59
  paginator.links_page_params(record_count: record_count_for(records, options))
39
60
  end
40
61
 
@@ -1,5 +1,5 @@
1
1
  module JSONAPI
2
2
  module Utils
3
- VERSION = '0.7.2'.freeze
3
+ VERSION = '0.7.3'.freeze
4
4
  end
5
5
  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.7.2
4
+ version: 0.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Guedes
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2018-04-25 00:00:00.000000000 Z
12
+ date: 2020-04-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: jsonapi-resources
@@ -17,98 +17,122 @@ dependencies:
17
17
  requirements:
18
18
  - - '='
19
19
  - !ruby/object:Gem::Version
20
- version: 0.9.0
20
+ version: 0.9.11
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.9.0
27
+ version: 0.9.11
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: bundler
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '1.10'
34
+ version: '1.14'
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '1.14'
35
38
  type: :development
36
39
  prerelease: false
37
40
  version_requirements: !ruby/object:Gem::Requirement
38
41
  requirements:
39
42
  - - "~>"
40
43
  - !ruby/object:Gem::Version
41
- version: '1.10'
44
+ version: '1.14'
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '1.14'
42
48
  - !ruby/object:Gem::Dependency
43
49
  name: rake
44
50
  requirement: !ruby/object:Gem::Requirement
45
51
  requirements:
46
52
  - - "~>"
47
53
  - !ruby/object:Gem::Version
48
- version: '10.0'
54
+ version: '12.3'
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 12.3.3
49
58
  type: :development
50
59
  prerelease: false
51
60
  version_requirements: !ruby/object:Gem::Requirement
52
61
  requirements:
53
62
  - - "~>"
54
63
  - !ruby/object:Gem::Version
55
- version: '10.0'
64
+ version: '12.3'
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 12.3.3
56
68
  - !ruby/object:Gem::Dependency
57
69
  name: rails
58
70
  requirement: !ruby/object:Gem::Requirement
59
71
  requirements:
60
72
  - - "~>"
61
73
  - !ruby/object:Gem::Version
62
- version: '5.1'
74
+ version: '5.2'
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 5.2.4
63
78
  type: :development
64
79
  prerelease: false
65
80
  version_requirements: !ruby/object:Gem::Requirement
66
81
  requirements:
67
82
  - - "~>"
68
83
  - !ruby/object:Gem::Version
69
- version: '5.1'
84
+ version: '5.2'
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: 5.2.4
70
88
  - !ruby/object:Gem::Dependency
71
89
  name: sqlite3
72
90
  requirement: !ruby/object:Gem::Requirement
73
91
  requirements:
74
- - - ">="
92
+ - - "~>"
75
93
  - !ruby/object:Gem::Version
76
- version: '0'
94
+ version: '1.4'
77
95
  type: :development
78
96
  prerelease: false
79
97
  version_requirements: !ruby/object:Gem::Requirement
80
98
  requirements:
81
- - - ">="
99
+ - - "~>"
82
100
  - !ruby/object:Gem::Version
83
- version: '0'
101
+ version: '1.4'
84
102
  - !ruby/object:Gem::Dependency
85
103
  name: rspec-rails
86
104
  requirement: !ruby/object:Gem::Requirement
87
105
  requirements:
88
106
  - - "~>"
89
107
  - !ruby/object:Gem::Version
90
- version: '3.1'
108
+ version: '3.9'
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: 3.9.0
91
112
  type: :development
92
113
  prerelease: false
93
114
  version_requirements: !ruby/object:Gem::Requirement
94
115
  requirements:
95
116
  - - "~>"
96
117
  - !ruby/object:Gem::Version
97
- version: '3.1'
118
+ version: '3.9'
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: 3.9.0
98
122
  - !ruby/object:Gem::Dependency
99
- name: factory_girl
123
+ name: factory_bot
100
124
  requirement: !ruby/object:Gem::Requirement
101
125
  requirements:
102
126
  - - "~>"
103
127
  - !ruby/object:Gem::Version
104
- version: '4.8'
128
+ version: '5.1'
105
129
  type: :development
106
130
  prerelease: false
107
131
  version_requirements: !ruby/object:Gem::Requirement
108
132
  requirements:
109
133
  - - "~>"
110
134
  - !ruby/object:Gem::Version
111
- version: '4.8'
135
+ version: '5.1'
112
136
  - !ruby/object:Gem::Dependency
113
137
  name: smart_rspec
114
138
  requirement: !ruby/object:Gem::Requirement
@@ -129,28 +153,40 @@ dependencies:
129
153
  requirements:
130
154
  - - "~>"
131
155
  - !ruby/object:Gem::Version
132
- version: 0.10.3
156
+ version: '0.12'
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: 0.12.2
133
160
  type: :development
134
161
  prerelease: false
135
162
  version_requirements: !ruby/object:Gem::Requirement
136
163
  requirements:
137
164
  - - "~>"
138
165
  - !ruby/object:Gem::Version
139
- version: 0.10.3
166
+ version: '0.12'
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ version: 0.12.2
140
170
  - !ruby/object:Gem::Dependency
141
171
  name: pry-byebug
142
172
  requirement: !ruby/object:Gem::Requirement
143
173
  requirements:
174
+ - - "~>"
175
+ - !ruby/object:Gem::Version
176
+ version: '3.7'
144
177
  - - ">="
145
178
  - !ruby/object:Gem::Version
146
- version: '0'
179
+ version: 3.7.0
147
180
  type: :development
148
181
  prerelease: false
149
182
  version_requirements: !ruby/object:Gem::Requirement
150
183
  requirements:
184
+ - - "~>"
185
+ - !ruby/object:Gem::Version
186
+ version: '3.7'
151
187
  - - ">="
152
188
  - !ruby/object:Gem::Version
153
- version: '0'
189
+ version: 3.7.0
154
190
  description: Build JSON API-compliant APIs on Rails with no (or less) learning curve.
155
191
  email:
156
192
  - tiagopog@gmail.com
@@ -163,6 +199,7 @@ files:
163
199
  - LICENSE.txt
164
200
  - README.md
165
201
  - bin/console
202
+ - bin/rspec
166
203
  - bin/setup
167
204
  - lib/jsonapi/utils.rb
168
205
  - lib/jsonapi/utils/exceptions.rb
@@ -199,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
199
236
  version: '0'
200
237
  requirements: []
201
238
  rubyforge_project:
202
- rubygems_version: 2.5.2
239
+ rubygems_version: 2.7.7
203
240
  signing_key:
204
241
  specification_version: 4
205
242
  summary: JSON::Utils is a simple way to get a full-featured JSON API on your Rails