jsonapi-resources 0.9.12 → 0.10.0.beta1
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 +5 -5
- data/LICENSE.txt +1 -1
- data/README.md +34 -11
- data/lib/bug_report_templates/rails_5_latest.rb +125 -0
- data/lib/bug_report_templates/rails_5_master.rb +140 -0
- data/lib/jsonapi-resources.rb +8 -3
- data/lib/jsonapi/active_relation_resource_finder.rb +640 -0
- data/lib/jsonapi/active_relation_resource_finder/join_tree.rb +126 -0
- data/lib/jsonapi/acts_as_resource_controller.rb +121 -106
- data/lib/jsonapi/{cached_resource_fragment.rb → cached_response_fragment.rb} +13 -30
- data/lib/jsonapi/compiled_json.rb +11 -1
- data/lib/jsonapi/configuration.rb +44 -18
- data/lib/jsonapi/error.rb +27 -0
- data/lib/jsonapi/exceptions.rb +43 -40
- data/lib/jsonapi/formatter.rb +3 -3
- data/lib/jsonapi/include_directives.rb +2 -45
- data/lib/jsonapi/link_builder.rb +87 -80
- data/lib/jsonapi/operation.rb +16 -5
- data/lib/jsonapi/operation_result.rb +74 -16
- data/lib/jsonapi/processor.rb +233 -112
- data/lib/jsonapi/relationship.rb +77 -53
- data/lib/jsonapi/request_parser.rb +378 -423
- data/lib/jsonapi/resource.rb +224 -524
- data/lib/jsonapi/resource_controller_metal.rb +2 -2
- data/lib/jsonapi/resource_fragment.rb +47 -0
- data/lib/jsonapi/resource_id_tree.rb +112 -0
- data/lib/jsonapi/resource_identity.rb +42 -0
- data/lib/jsonapi/resource_serializer.rb +133 -301
- data/lib/jsonapi/resource_set.rb +108 -0
- data/lib/jsonapi/resources/version.rb +1 -1
- data/lib/jsonapi/response_document.rb +100 -88
- data/lib/jsonapi/routing_ext.rb +21 -43
- metadata +29 -45
- data/lib/jsonapi/operation_dispatcher.rb +0 -88
- data/lib/jsonapi/operation_results.rb +0 -35
- 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.
|
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:
|
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: '
|
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: '
|
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: '
|
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: '
|
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/
|
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:
|
228
|
+
version: 1.3.1
|
246
229
|
requirements: []
|
247
|
-
|
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
|