jsonapi-utils 0.3.5 → 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
  SHA1:
3
- metadata.gz: 1e857579e82b9b5550ec7224bd1c2659b4e06e9f
4
- data.tar.gz: 468183964c826b06cff256ccfd2b4305b43f68bb
3
+ metadata.gz: 768ad917f0e0006484fcca29a138f05c0b2f9a7b
4
+ data.tar.gz: 8be72ed0a02e3e86f0b73edd822a0f791992cb36
5
5
  SHA512:
6
- metadata.gz: 597e131379f735cda8fb5f980256966089d0dacc4d5a552709a20524f30e4b5ab94e8ee01a3a0a22f861911bbeefa470341c35c5946badbc0319437353c34e02
7
- data.tar.gz: 9715af2a8aeae7cda56d8f24e8f43f982774ab9db0d64e0c15aef2ada82a9f7714f4556895adfc06583a8a76539cd5dc2bee0a9b8df4c97d9d8beab8d0711510
6
+ metadata.gz: 3fd1c7fa5ca1e4c2d075be52fe75d058555a840fb0c70b43d94bf687f13fd7740d340f74f50fc6f64c4d90a171493c27425661ca26a6b7a99992472d697bc96a
7
+ data.tar.gz: 3a31efa4514d307eaccaf1c244db587cafccbca885bd2eafbbd8c846829a0d5ed0e4f86697a4e31b5cf46429e8f38b16bf4b0d16e85487dd52d09751ce94f4bc
data/.gitignore CHANGED
@@ -9,6 +9,8 @@
9
9
  /spec/test_db
10
10
  /spec/reports/
11
11
  /tmp/
12
+ /log/
13
+ *.log
12
14
  *.bundle
13
15
  *.so
14
16
  *.sw*
@@ -16,5 +18,5 @@
16
18
  *.a
17
19
  *.gem
18
20
  .DS_Store
19
- mkmf.log
21
+ test_db
20
22
 
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # JSONAPI::Utils
2
2
 
3
+ [![Code Climate](https://codeclimate.com/github/b2beauty/jsonapi-utils/badges/gpa.svg)](https://codeclimate.com/github/b2beauty/jsonapi-utils)
4
+ [![Gem Version](https://badge.fury.io/rb/jsonapi-utils.svg)](https://badge.fury.io/rb/jsonapi-utils)
5
+
3
6
  JSON::Utils is a simple way to get a full-featured [JSON API](jsonapi.org) serialization in your
4
7
  controller's responses. This gem works on top of the awesome gem [jsonapi-resources](https://github.com/cerebris/jsonapi-resources),
5
8
  bringing to controllers a Rails-native way to render data.
@@ -9,7 +12,7 @@ bringing to controllers a Rails-native way to render data.
9
12
  Add these lines to your application's Gemfile:
10
13
 
11
14
  ```ruby
12
- gem 'jsonapi-resources', '~> 0.5.7'
15
+ gem 'jsonapi-resources', '~> 0.7.0'
13
16
  gem 'jsonapi-utils'
14
17
  ```
15
18
 
@@ -10,20 +10,24 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["tiagopog@gmail.com", "douglas@beautydate.com.br"]
11
11
 
12
12
  spec.summary = %q{JSON::Utils is a simple way to get a full-featured JSON API serialization for your controller's responses.}
13
- spec.description = %q{A Rails way to get your API's data following the JSON API's specs (http://jsosapi.org)}
13
+ spec.description = %q{A Rails way to get your API's data serialized through JSON API's specs (http://jsosapi.org)}
14
14
  spec.homepage = "https://github.com/b2beauty/jsonapi-utils"
15
15
  spec.license = "MIT"
16
16
 
17
17
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
18
  spec.bindir = "exe"
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
- spec.require_paths = ["lib"]
20
+ spec.require_paths = ['lib']
21
21
 
22
22
  spec.add_development_dependency 'bundler', '~> 1.10'
23
23
  spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'rspec'
24
25
  spec.add_development_dependency 'rspec-rails'
26
+ spec.add_development_dependency 'smart_rspec'
27
+ spec.add_development_dependency 'pry'
25
28
  spec.add_development_dependency 'sqlite3'
26
29
  spec.add_development_dependency 'factory_girl', '~> 4.5'
27
- spec.add_development_dependency 'jsonapi-resources', '~> 0.5.7'
28
- spec.add_development_dependency 'rails', '>= 4.0'
30
+ spec.add_development_dependency 'jsonapi-resources', '~> 0.7.0'
31
+
32
+ spec.add_dependency 'rails', '>= 4.0'
29
33
  end
data/lib/jsonapi/utils.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  require 'jsonapi/utils/version'
2
+ require 'active_support/concern'
2
3
  require 'jsonapi/utils/exceptions'
4
+ require 'pry'
3
5
 
4
6
  module JSONAPI
5
7
  module Utils
6
- extend ActiveSupport::Concern
8
+ extend ::ActiveSupport::Concern
7
9
 
8
10
  include do
9
11
  helper_method :jsonapi_serialize
@@ -13,7 +15,14 @@ module JSONAPI
13
15
  if options.has_key?(:json)
14
16
  response = jsonapi_serialize(options[:json], options[:options] || {})
15
17
  render json: response, status: options[:status] || :ok
18
+ else
19
+ raise ArgumentError.new('":json" key must be set to JSONAPI::Utils#jsonapi_render')
16
20
  end
21
+ rescue => e
22
+ raise e unless e.class.name.starts_with?('JSONAPI::Exceptions')
23
+ handle_exceptions(e)
24
+ ensure
25
+ headers['Content-Type'] = JSONAPI::MEDIA_TYPE
17
26
  end
18
27
 
19
28
  def jsonapi_render_errors(exception)
@@ -33,8 +42,8 @@ module JSONAPI
33
42
  jsonapi_render_errors(::JSONAPI::Utils::Exceptions::BadRequest.new)
34
43
  end
35
44
 
36
- def jsonapi_render_not_found(exception)
37
- id = exception.message.match(/=(\d+)/)[1]
45
+ def jsonapi_render_not_found
46
+ id = extract_ids(@request.params)
38
47
  jsonapi_render_errors(JSONAPI::Exceptions::RecordNotFound.new(id))
39
48
  end
40
49
 
@@ -43,17 +52,18 @@ module JSONAPI
43
52
  end
44
53
 
45
54
  def jsonapi_serialize(records, options = {})
55
+ setup_request
46
56
  results = JSONAPI::OperationResults.new
47
57
 
48
58
  fix_request_options(params, records)
49
59
 
50
60
  if records.respond_to?(:to_ary)
51
- records = fix_when_hash(records, options) if needs_to_be_fixed?(records)
52
- @_records = build_collection(records, options)
53
- results.add_result(JSONAPI::ResourcesOperationResult.new(:ok, @_records, result_options(records, options)))
61
+ records = fix_when_hash(records, options) if needs_to_be_fixed?(records)
62
+ @resources = build_collection(records, options)
63
+ results.add_result(JSONAPI::ResourcesOperationResult.new(:ok, @resources, result_options(options)))
54
64
  else
55
- @_record = turn_into_resource(records, options)
56
- results.add_result(JSONAPI::ResourceOperationResult.new(:ok, @_record))
65
+ @resource = turn_into_resource(records, options)
66
+ results.add_result(JSONAPI::ResourceOperationResult.new(:ok, @resource))
57
67
  end
58
68
 
59
69
  create_response_document(results).contents
@@ -61,6 +71,11 @@ module JSONAPI
61
71
 
62
72
  private
63
73
 
74
+ def extract_ids(hash)
75
+ ids = hash.keys.select { |e| e =~ /id$/i }.map { |e| hash[e] }
76
+ ids.first rescue '(id not identified)'
77
+ end
78
+
64
79
  def fix_request_options(params, records)
65
80
  return if request.method !~ /get/i ||
66
81
  params.nil? ||
@@ -73,142 +88,87 @@ module JSONAPI
73
88
  records.is_a?(Array) && records.all? { |e| e.is_a?(Hash) }
74
89
  end
75
90
 
76
- def result_options(records, options)
77
- {}.tap do |data|
78
- if JSONAPI.configuration.top_level_links_include_pagination
79
- data[:pagination_params] = pagination_params(records, options)
80
- end
91
+ def result_options(options)
92
+ hash = {}
81
93
 
82
- if JSONAPI.configuration.top_level_meta_include_record_count
83
- data[:record_count] = count_records(records, options)
84
- end
94
+ if JSONAPI.configuration.top_level_links_include_pagination
95
+ hash[:pagination_params] = pagination_params(options)
85
96
  end
86
- end
87
97
 
88
- def pagination_params(records, options)
89
- data = {}
90
- if @_paginator && JSONAPI.configuration.top_level_links_include_pagination
91
- @_paginator.class.requires_record_count &&
92
- data[:record_count] = count_records(records, options)
93
- @_paginator.links_page_params(data)
94
- else
95
- data
98
+ if JSONAPI.configuration.top_level_meta_include_record_count
99
+ hash[:record_count] = count_records(@resources, options)
96
100
  end
97
- end
98
101
 
99
- def build_collection(records, options = {})
100
- records = apply_filter(records, options)
101
- records = apply_pagination(records, options)
102
- records = apply_sort(records)
103
- records.respond_to?(:to_ary) ? records.map { |record| turn_into_resource(record, options) } : []
102
+ hash
104
103
  end
105
104
 
106
- def turn_into_resource(record, options = {})
107
- if options[:resource]
108
- options[:resource].to_s.constantize.new(record)
105
+ def pagination_params(options)
106
+ @paginator ||= paginator(params)
107
+ if @paginator && JSONAPI.configuration.top_level_links_include_pagination
108
+ options = {}
109
+ @paginator.class.requires_record_count &&
110
+ options[:record_count] = count_records(@resources, options)
111
+ @paginator.links_page_params(options)
109
112
  else
110
- @request.resource_klass.new(record)
111
- end
112
- end
113
-
114
- def apply_filter(records, options = {})
115
- if apply_filter?(records, options)
116
- records.where(filter_params)
117
- else
118
- records
113
+ {}
119
114
  end
120
115
  end
121
116
 
122
- def apply_filter?(records, options = {})
123
- params[:filter].present? && records.respond_to?(:where) &&
124
- (options[:filter].nil? || options[:filter])
125
- end
126
-
127
- def filter_params
128
- @_filter_params =
129
- params[:filter].keys.each_with_object({}) do |resource, hash|
130
- hash[resource] = params[:filter][resource]
131
- end
132
- end
133
-
134
- def apply_pagination(records, options = {})
135
- return records unless apply_pagination?(options)
136
- pagination = set_pagination(options)
117
+ def paginator(params)
118
+ page_params = ActionController::Parameters.new(params[:page])
137
119
 
138
- records =
139
- if records.is_a?(Array)
140
- records[pagination[:range]]
141
- else
142
- pagination[:paginator].apply(records, nil)
120
+ @paginator ||=
121
+ if JSONAPI.configuration.default_paginator == :paged
122
+ PagedPaginator.new(page_params)
123
+ elsif JSONAPI.configuration.default_paginator == :offset
124
+ OffsetPaginator.new(page_params)
143
125
  end
144
126
  end
145
127
 
146
- def apply_sort(records)
147
- return records unless params[:sort].present?
148
-
149
- if records.is_a?(Array)
150
- records.sort { |a, b| comp = 0; eval(sort_criteria) }
151
- elsif records.respond_to?(:order)
152
- records.order(sort_params)
153
- end
154
- end
155
-
156
- def sort_criteria
157
- sort_params.reduce('') do |sum, hash|
158
- foo = ["a[:#{hash[0]}]", "b[:#{hash[0]}]"]
159
- foo.reverse! if hash[1] == :desc
160
- sum + "comp = comp == 0 ? #{foo.join(' <=> ')} : comp; "
128
+ def build_collection(records, options = {})
129
+ unless JSONAPI.configuration.default_paginator == :none
130
+ records = paginator(@request.params).apply(records, nil)
161
131
  end
132
+ records.respond_to?(:to_ary) ? records.map { |record| turn_into_resource(record, options) } : []
162
133
  end
163
134
 
164
- def sort_params
165
- @_sort_params ||=
166
- params[:sort].split(',').each_with_object({}) do |criteria, hash|
167
- order, field = criteria.match(/(\-?)(\w+)/i)[1..2]
168
- hash[field] = order == '-' ? :desc : :asc
169
- end
170
- end
171
-
172
- def set_pagination(options)
173
- page_params = ActionController::Parameters.new(@request.params[:page])
174
- if JSONAPI.configuration.default_paginator == :paged
175
- @_paginator ||= PagedPaginator.new(page_params)
176
- number = page_params['number'].to_i.nonzero? || 1
177
- size = page_params['size'].to_i.nonzero? || JSONAPI.configuration.default_page_size
178
- { paginator: @_paginator, range: (number - 1) * size..number * size - 1 }
179
- elsif JSONAPI.configuration.default_paginator == :offset
180
- @_paginator ||= OffsetPaginator.new(page_params)
181
- offset = page_params['offset'].to_i.nonzero? || 0
182
- limit = page_params['limit'].to_i.nonzero? || JSONAPI.configuration.default_page_size
183
- { paginator: @_paginator, range: offset..offset + limit - 1 }
135
+ def turn_into_resource(record, options = {})
136
+ if options[:resource]
137
+ options[:resource].to_s.constantize.new(record, context)
184
138
  else
185
- {}
139
+ @request.resource_klass.new(record, context)
186
140
  end
187
141
  end
188
142
 
189
- def apply_pagination?(options)
190
- JSONAPI.configuration.default_paginator != :none &&
191
- (options[:paginate].nil? || options[:paginate])
192
- end
193
-
194
143
  def fix_when_hash(records, options)
195
144
  return [] unless options[:model]
196
145
  records.map { |hash| options[:model].new(hash) }
197
- rescue ActiveRecord::UnknownAttributeError
146
+ rescue
198
147
  ids = records.map { |e| e[:id] || e['id'] }
199
148
  scope = options[:scope] ? options[:model].send(options[:scope]) : options[:model]
200
149
  scope.where(id: ids)
201
150
  end
202
151
 
203
152
  def count_records(records, options)
204
- if options[:count].present?
205
- options[:count]
206
- elsif records.is_a?(Array)
207
- records.length
153
+ if records.size.zero? then 0
154
+ elsif options[:count] then options[:count]
155
+ elsif options[:model] && options[:scope] then options[:model].send(options[:scope]).count
156
+ elsif options[:model] then options[:model].count
208
157
  else
209
- records = apply_filter(records, options) if params[:filter].present?
210
- records.except(:group, :order).count("DISTINCT #{records.table.name}.id")
158
+ record = records.first
159
+ model = record.try(:model) || record.try(:_model)
160
+ model.class.count
211
161
  end
212
162
  end
163
+
164
+ def setup_request
165
+ @request ||=
166
+ JSONAPI::Request.new(
167
+ params,
168
+ context: context,
169
+ key_formatter: key_formatter,
170
+ server_error_callbacks: (self.class.server_error_callbacks || [])
171
+ )
172
+ end
213
173
  end
214
174
  end
@@ -1,5 +1,5 @@
1
1
  module JSONAPI
2
2
  module Utils
3
- VERSION = '0.3.5'
3
+ VERSION = '0.4.0'
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.3.5
4
+ version: 0.4.0
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: 2016-04-04 00:00:00.000000000 Z
12
+ date: 2016-03-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -39,6 +39,20 @@ dependencies:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
41
  version: '10.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
42
56
  - !ruby/object:Gem::Dependency
43
57
  name: rspec-rails
44
58
  requirement: !ruby/object:Gem::Requirement
@@ -53,6 +67,34 @@ dependencies:
53
67
  - - ">="
54
68
  - !ruby/object:Gem::Version
55
69
  version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: smart_rspec
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: pry
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
56
98
  - !ruby/object:Gem::Dependency
57
99
  name: sqlite3
58
100
  requirement: !ruby/object:Gem::Requirement
@@ -87,14 +129,14 @@ dependencies:
87
129
  requirements:
88
130
  - - "~>"
89
131
  - !ruby/object:Gem::Version
90
- version: 0.5.7
132
+ version: 0.7.0
91
133
  type: :development
92
134
  prerelease: false
93
135
  version_requirements: !ruby/object:Gem::Requirement
94
136
  requirements:
95
137
  - - "~>"
96
138
  - !ruby/object:Gem::Version
97
- version: 0.5.7
139
+ version: 0.7.0
98
140
  - !ruby/object:Gem::Dependency
99
141
  name: rails
100
142
  requirement: !ruby/object:Gem::Requirement
@@ -102,14 +144,15 @@ dependencies:
102
144
  - - ">="
103
145
  - !ruby/object:Gem::Version
104
146
  version: '4.0'
105
- type: :development
147
+ type: :runtime
106
148
  prerelease: false
107
149
  version_requirements: !ruby/object:Gem::Requirement
108
150
  requirements:
109
151
  - - ">="
110
152
  - !ruby/object:Gem::Version
111
153
  version: '4.0'
112
- description: A Rails way to get your API's data following the JSON API's specs (http://jsosapi.org)
154
+ description: A Rails way to get your API's data serialized through JSON API's specs
155
+ (http://jsosapi.org)
113
156
  email:
114
157
  - tiagopog@gmail.com
115
158
  - douglas@beautydate.com.br
@@ -151,7 +194,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
151
194
  version: '0'
152
195
  requirements: []
153
196
  rubyforge_project:
154
- rubygems_version: 2.6.2
197
+ rubygems_version: 2.4.5.1
155
198
  signing_key:
156
199
  specification_version: 4
157
200
  summary: JSON::Utils is a simple way to get a full-featured JSON API serialization