jsonapi-resources 0.9.12 → 0.10.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE.txt +1 -1
  3. data/README.md +34 -11
  4. data/lib/bug_report_templates/rails_5_latest.rb +125 -0
  5. data/lib/bug_report_templates/rails_5_master.rb +140 -0
  6. data/lib/jsonapi-resources.rb +8 -3
  7. data/lib/jsonapi/active_relation_resource_finder.rb +640 -0
  8. data/lib/jsonapi/active_relation_resource_finder/join_tree.rb +126 -0
  9. data/lib/jsonapi/acts_as_resource_controller.rb +121 -106
  10. data/lib/jsonapi/{cached_resource_fragment.rb → cached_response_fragment.rb} +13 -30
  11. data/lib/jsonapi/compiled_json.rb +11 -1
  12. data/lib/jsonapi/configuration.rb +44 -18
  13. data/lib/jsonapi/error.rb +27 -0
  14. data/lib/jsonapi/exceptions.rb +43 -40
  15. data/lib/jsonapi/formatter.rb +3 -3
  16. data/lib/jsonapi/include_directives.rb +2 -45
  17. data/lib/jsonapi/link_builder.rb +87 -80
  18. data/lib/jsonapi/operation.rb +16 -5
  19. data/lib/jsonapi/operation_result.rb +74 -16
  20. data/lib/jsonapi/processor.rb +233 -112
  21. data/lib/jsonapi/relationship.rb +77 -53
  22. data/lib/jsonapi/request_parser.rb +378 -423
  23. data/lib/jsonapi/resource.rb +224 -524
  24. data/lib/jsonapi/resource_controller_metal.rb +2 -2
  25. data/lib/jsonapi/resource_fragment.rb +47 -0
  26. data/lib/jsonapi/resource_id_tree.rb +112 -0
  27. data/lib/jsonapi/resource_identity.rb +42 -0
  28. data/lib/jsonapi/resource_serializer.rb +133 -301
  29. data/lib/jsonapi/resource_set.rb +108 -0
  30. data/lib/jsonapi/resources/version.rb +1 -1
  31. data/lib/jsonapi/response_document.rb +100 -88
  32. data/lib/jsonapi/routing_ext.rb +21 -43
  33. metadata +29 -45
  34. data/lib/jsonapi/operation_dispatcher.rb +0 -88
  35. data/lib/jsonapi/operation_results.rb +0 -35
  36. data/lib/jsonapi/relationship_builder.rb +0 -167
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonapi-resources
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.12
4
+ version: 0.10.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Gebhardt
@@ -9,22 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-02-04 00:00:00.000000000 Z
12
+ date: 2019-01-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ">="
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: '0'
20
+ version: '1.5'
21
21
  type: :development
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'
27
+ version: '1.5'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: rake
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -43,16 +43,22 @@ dependencies:
43
43
  name: minitest
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - ">="
46
+ - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: '0'
48
+ version: '5.10'
49
+ - - "!="
50
+ - !ruby/object:Gem::Version
51
+ version: 5.10.2
49
52
  type: :development
50
53
  prerelease: false
51
54
  version_requirements: !ruby/object:Gem::Requirement
52
55
  requirements:
53
- - - ">="
56
+ - - "~>"
54
57
  - !ruby/object:Gem::Version
55
- version: '0'
58
+ version: '5.10'
59
+ - - "!="
60
+ - !ruby/object:Gem::Version
61
+ version: 5.10.2
56
62
  - !ruby/object:Gem::Dependency
57
63
  name: minitest-spec-rails
58
64
  requirement: !ruby/object:Gem::Requirement
@@ -109,34 +115,6 @@ dependencies:
109
115
  - - ">="
110
116
  - !ruby/object:Gem::Version
111
117
  version: '0'
112
- - !ruby/object:Gem::Dependency
113
- name: database_cleaner
114
- requirement: !ruby/object:Gem::Requirement
115
- requirements:
116
- - - ">="
117
- - !ruby/object:Gem::Version
118
- version: '0'
119
- type: :development
120
- prerelease: false
121
- version_requirements: !ruby/object:Gem::Requirement
122
- requirements:
123
- - - ">="
124
- - !ruby/object:Gem::Version
125
- version: '0'
126
- - !ruby/object:Gem::Dependency
127
- name: memory_profiler
128
- requirement: !ruby/object:Gem::Requirement
129
- requirements:
130
- - - ">="
131
- - !ruby/object:Gem::Version
132
- version: '0'
133
- type: :development
134
- prerelease: false
135
- version_requirements: !ruby/object:Gem::Requirement
136
- requirements:
137
- - - ">="
138
- - !ruby/object:Gem::Version
139
- version: '0'
140
118
  - !ruby/object:Gem::Dependency
141
119
  name: activerecord
142
120
  requirement: !ruby/object:Gem::Requirement
@@ -190,14 +168,18 @@ extra_rdoc_files: []
190
168
  files:
191
169
  - LICENSE.txt
192
170
  - README.md
171
+ - lib/bug_report_templates/rails_5_latest.rb
172
+ - lib/bug_report_templates/rails_5_master.rb
193
173
  - lib/generators/jsonapi/USAGE
194
174
  - lib/generators/jsonapi/controller_generator.rb
195
175
  - lib/generators/jsonapi/resource_generator.rb
196
176
  - lib/generators/jsonapi/templates/jsonapi_controller.rb
197
177
  - lib/generators/jsonapi/templates/jsonapi_resource.rb
198
178
  - lib/jsonapi-resources.rb
179
+ - lib/jsonapi/active_relation_resource_finder.rb
180
+ - lib/jsonapi/active_relation_resource_finder/join_tree.rb
199
181
  - lib/jsonapi/acts_as_resource_controller.rb
200
- - lib/jsonapi/cached_resource_fragment.rb
182
+ - lib/jsonapi/cached_response_fragment.rb
201
183
  - lib/jsonapi/callbacks.rb
202
184
  - lib/jsonapi/compiled_json.rb
203
185
  - lib/jsonapi/configuration.rb
@@ -210,18 +192,19 @@ files:
210
192
  - lib/jsonapi/mime_types.rb
211
193
  - lib/jsonapi/naive_cache.rb
212
194
  - lib/jsonapi/operation.rb
213
- - lib/jsonapi/operation_dispatcher.rb
214
195
  - lib/jsonapi/operation_result.rb
215
- - lib/jsonapi/operation_results.rb
216
196
  - lib/jsonapi/paginator.rb
217
197
  - lib/jsonapi/processor.rb
218
198
  - lib/jsonapi/relationship.rb
219
- - lib/jsonapi/relationship_builder.rb
220
199
  - lib/jsonapi/request_parser.rb
221
200
  - lib/jsonapi/resource.rb
222
201
  - lib/jsonapi/resource_controller.rb
223
202
  - lib/jsonapi/resource_controller_metal.rb
203
+ - lib/jsonapi/resource_fragment.rb
204
+ - lib/jsonapi/resource_id_tree.rb
205
+ - lib/jsonapi/resource_identity.rb
224
206
  - lib/jsonapi/resource_serializer.rb
207
+ - lib/jsonapi/resource_set.rb
225
208
  - lib/jsonapi/resources/version.rb
226
209
  - lib/jsonapi/response_document.rb
227
210
  - lib/jsonapi/routing_ext.rb
@@ -240,11 +223,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
240
223
  version: '2.1'
241
224
  required_rubygems_version: !ruby/object:Gem::Requirement
242
225
  requirements:
243
- - - ">="
226
+ - - ">"
244
227
  - !ruby/object:Gem::Version
245
- version: '0'
228
+ version: 1.3.1
246
229
  requirements: []
247
- rubygems_version: 3.0.3
230
+ rubyforge_project:
231
+ rubygems_version: 2.6.14.1
248
232
  signing_key:
249
233
  specification_version: 4
250
234
  summary: Easily support JSON API in Rails.
@@ -1,88 +0,0 @@
1
- module JSONAPI
2
- class OperationDispatcher
3
-
4
- def initialize(transaction: lambda { |&block| block.yield },
5
- rollback: lambda { },
6
- server_error_callbacks: [])
7
-
8
- @transaction = transaction
9
- @rollback = rollback
10
- @server_error_callbacks = server_error_callbacks
11
- end
12
-
13
- def process(operations)
14
- results = JSONAPI::OperationResults.new
15
-
16
- # Use transactions if more than one operation and if one of the operations can be transactional
17
- # Even if transactional transactions won't be used unless the derived OperationsProcessor supports them.
18
- transactional = false
19
-
20
- operations.each do |operation|
21
- transactional |= operation.transactional?
22
- end if JSONAPI.configuration.allow_transactions
23
-
24
- transaction(transactional) do
25
- # Links and meta data global to the set of operations
26
- operations_meta = {}
27
- operations_links = {}
28
- operations.each do |operation|
29
- results.add_result(process_operation(operation))
30
- rollback(transactional) if results.has_errors?
31
- end
32
- results.meta = operations_meta
33
- results.links = operations_links
34
- end
35
- results
36
- end
37
-
38
- private
39
-
40
- def transaction(transactional)
41
- if transactional
42
- @transaction.call do
43
- yield
44
- end
45
- else
46
- yield
47
- end
48
- end
49
-
50
- def rollback(transactional)
51
- if transactional
52
- @rollback.call
53
- end
54
- end
55
-
56
- def process_operation(operation)
57
- with_default_handling do
58
- operation.process
59
- end
60
- end
61
-
62
- def with_default_handling(&block)
63
- block.yield
64
- rescue => e
65
- if JSONAPI.configuration.exception_class_whitelisted?(e)
66
- raise e
67
- else
68
- @server_error_callbacks.each { |callback|
69
- safe_run_callback(callback, e)
70
- }
71
-
72
- internal_server_error = JSONAPI::Exceptions::InternalServerError.new(e)
73
- Rails.logger.error { "Internal Server Error: #{e.message} #{e.backtrace.join("\n")}" }
74
- return JSONAPI::ErrorsOperationResult.new(internal_server_error.errors[0].code, internal_server_error.errors)
75
- end
76
- end
77
-
78
- def safe_run_callback(callback, error)
79
- begin
80
- callback.call(error)
81
- rescue => e
82
- Rails.logger.error { "Error in error handling callback: #{e.message} #{e.backtrace.join("\n")}" }
83
- internal_server_error = JSONAPI::Exceptions::InternalServerError.new(e)
84
- return JSONAPI::ErrorsOperationResult.new(internal_server_error.errors[0].code, internal_server_error.errors)
85
- end
86
- end
87
- end
88
- end
@@ -1,35 +0,0 @@
1
- module JSONAPI
2
- class OperationResults
3
- attr_accessor :results
4
- attr_accessor :meta
5
- attr_accessor :links
6
-
7
- def initialize
8
- @results = []
9
- @has_errors = false
10
- @meta = {}
11
- @links = {}
12
- end
13
-
14
- def add_result(result)
15
- @has_errors = true if result.is_a?(JSONAPI::ErrorsOperationResult)
16
- @results.push(result)
17
- end
18
-
19
- def has_errors?
20
- @has_errors
21
- end
22
-
23
- def all_errors
24
- errors = []
25
- if @has_errors
26
- @results.each do |result|
27
- if result.is_a?(JSONAPI::ErrorsOperationResult)
28
- errors.concat(result.errors)
29
- end
30
- end
31
- end
32
- errors
33
- end
34
- end
35
- end
@@ -1,167 +0,0 @@
1
- module JSONAPI
2
- class RelationshipBuilder
3
- attr_reader :model_class, :options, :relationship_class
4
- delegate :register_relationship, to: :@resource_class
5
-
6
- def initialize(relationship_class, model_class, options)
7
- @relationship_class = relationship_class
8
- @model_class = model_class
9
- @resource_class = options[:parent_resource]
10
- @options = options
11
- end
12
-
13
- def define_relationship_methods(relationship_name)
14
- # Initialize from an ActiveRecord model's properties
15
- if model_class && model_class.ancestors.collect{|ancestor| ancestor.name}.include?('ActiveRecord::Base')
16
- model_association = model_class.reflect_on_association(relationship_name)
17
- if model_association
18
- options[:class_name] ||= model_association.class_name
19
- end
20
- end
21
-
22
- relationship = register_relationship(
23
- relationship_name,
24
- relationship_class.new(relationship_name, options)
25
- )
26
-
27
- foreign_key = define_foreign_key_setter(relationship.foreign_key)
28
-
29
- case relationship
30
- when JSONAPI::Relationship::ToOne
31
- associated = define_resource_relationship_accessor(:one, relationship_name)
32
- args = [relationship, foreign_key, associated, relationship_name]
33
-
34
- relationship.belongs_to? ? build_belongs_to(*args) : build_has_one(*args)
35
- when JSONAPI::Relationship::ToMany
36
- associated = define_resource_relationship_accessor(:many, relationship_name)
37
-
38
- build_to_many(relationship, foreign_key, associated, relationship_name)
39
- end
40
- end
41
-
42
- def define_foreign_key_setter(foreign_key)
43
- define_on_resource "#{foreign_key}=" do |value|
44
- @model.method("#{foreign_key}=").call(value)
45
- end
46
- foreign_key
47
- end
48
-
49
- def define_resource_relationship_accessor(type, relationship_name)
50
- associated_records_method_name = {
51
- one: "record_for_#{relationship_name}",
52
- many: "records_for_#{relationship_name}"
53
- }
54
- .fetch(type)
55
-
56
- define_on_resource associated_records_method_name do |options = {}|
57
- relationship = self.class._relationships[relationship_name]
58
- relation_name = relationship.relation_name(context: @context)
59
- records = records_for(relation_name)
60
-
61
- resource_klass = relationship.resource_klass
62
-
63
- records = resource_klass.apply_includes(records, options)
64
-
65
- filters = options.fetch(:filters, {})
66
- unless filters.nil? || filters.empty?
67
- records = resource_klass.apply_filters(records, filters, options)
68
- end
69
-
70
- sort_criteria = options.fetch(:sort_criteria, {})
71
- order_options = relationship.resource_klass.construct_order_options(sort_criteria)
72
- records = resource_klass.apply_sort(records, order_options, @context)
73
-
74
- paginator = options[:paginator]
75
- if paginator
76
- records = resource_klass.apply_pagination(records, paginator, order_options)
77
- end
78
-
79
- records
80
- end
81
-
82
- associated_records_method_name
83
- end
84
-
85
- def build_belongs_to(relationship, foreign_key, associated_records_method_name, relationship_name)
86
- # Calls method matching foreign key name on model instance
87
- define_on_resource foreign_key do
88
- @model.method(foreign_key).call
89
- end
90
-
91
- # Returns instantiated related resource object or nil
92
- define_on_resource relationship_name do |options = {}|
93
- relationship = self.class._relationships[relationship_name]
94
-
95
- if relationship.polymorphic?
96
- associated_model = public_send(associated_records_method_name)
97
- resource_klass = self.class.resource_for_model(associated_model) if associated_model
98
- return resource_klass.new(associated_model, @context) if resource_klass
99
- else
100
- resource_klass = relationship.resource_klass
101
- if resource_klass
102
- associated_model = public_send(associated_records_method_name)
103
- return associated_model ? resource_klass.new(associated_model, @context) : nil
104
- end
105
- end
106
- end
107
- end
108
-
109
- def build_has_one(relationship, foreign_key, associated_records_method_name, relationship_name)
110
- # Returns primary key name of related resource class
111
- define_on_resource foreign_key do
112
- relationship = self.class._relationships[relationship_name]
113
-
114
- record = public_send(associated_records_method_name)
115
- return nil if record.nil?
116
- record.public_send(relationship.resource_klass._primary_key)
117
- end
118
-
119
- # Returns instantiated related resource object or nil
120
- define_on_resource relationship_name do |options = {}|
121
- relationship = self.class._relationships[relationship_name]
122
-
123
- if relationship.polymorphic?
124
- associated_model = public_send(associated_records_method_name)
125
- resource_klass = self.class.resource_for_model(associated_model) if associated_model
126
- return resource_klass.new(associated_model, @context) if resource_klass && associated_model
127
- else
128
- resource_klass = relationship.resource_klass
129
- if resource_klass
130
- associated_model = public_send(associated_records_method_name)
131
- return associated_model ? resource_klass.new(associated_model, @context) : nil
132
- end
133
- end
134
- end
135
- end
136
-
137
- def build_to_many(relationship, foreign_key, associated_records_method_name, relationship_name)
138
- # Returns array of primary keys of related resource classes
139
- define_on_resource foreign_key do
140
- records = public_send(associated_records_method_name)
141
- return records.collect do |record|
142
- record.public_send(relationship.resource_klass._primary_key)
143
- end
144
- end
145
-
146
- # Returns array of instantiated related resource objects
147
- define_on_resource relationship_name do |options = {}|
148
- relationship = self.class._relationships[relationship_name]
149
-
150
- resource_klass = relationship.resource_klass
151
- records = public_send(associated_records_method_name, options)
152
-
153
- return records.collect do |record|
154
- if relationship.polymorphic?
155
- resource_klass = self.class.resource_for_model(record)
156
- end
157
- resource_klass.new(record, @context)
158
- end
159
- end
160
- end
161
-
162
- def define_on_resource(method_name, &block)
163
- return if @resource_class.method_defined?(method_name)
164
- @resource_class.inject_method_definition(method_name, block)
165
- end
166
- end
167
- end