jsonapi-resources 0.10.7 → 0.11.0.beta2

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +39 -2
  4. data/lib/generators/jsonapi/controller_generator.rb +2 -0
  5. data/lib/generators/jsonapi/resource_generator.rb +2 -0
  6. data/lib/jsonapi/active_relation/adapters/join_left_active_record_adapter.rb +3 -2
  7. data/lib/jsonapi/active_relation/join_manager.rb +30 -18
  8. data/lib/jsonapi/active_relation/join_manager_v10.rb +305 -0
  9. data/lib/jsonapi/active_relation_retrieval.rb +885 -0
  10. data/lib/jsonapi/active_relation_retrieval_v09.rb +715 -0
  11. data/lib/jsonapi/{active_relation_resource.rb → active_relation_retrieval_v10.rb} +113 -135
  12. data/lib/jsonapi/acts_as_resource_controller.rb +49 -49
  13. data/lib/jsonapi/cached_response_fragment.rb +4 -2
  14. data/lib/jsonapi/callbacks.rb +2 -0
  15. data/lib/jsonapi/compiled_json.rb +2 -0
  16. data/lib/jsonapi/configuration.rb +35 -15
  17. data/lib/jsonapi/error.rb +2 -0
  18. data/lib/jsonapi/error_codes.rb +2 -0
  19. data/lib/jsonapi/exceptions.rb +2 -0
  20. data/lib/jsonapi/formatter.rb +2 -0
  21. data/lib/jsonapi/include_directives.rb +77 -19
  22. data/lib/jsonapi/link_builder.rb +2 -0
  23. data/lib/jsonapi/mime_types.rb +6 -10
  24. data/lib/jsonapi/naive_cache.rb +2 -0
  25. data/lib/jsonapi/operation.rb +2 -0
  26. data/lib/jsonapi/operation_result.rb +2 -0
  27. data/lib/jsonapi/paginator.rb +2 -17
  28. data/lib/jsonapi/path.rb +2 -0
  29. data/lib/jsonapi/path_segment.rb +4 -2
  30. data/lib/jsonapi/processor.rb +100 -153
  31. data/lib/jsonapi/relationship.rb +89 -35
  32. data/lib/jsonapi/{request_parser.rb → request.rb} +157 -164
  33. data/lib/jsonapi/resource.rb +7 -2
  34. data/lib/jsonapi/{basic_resource.rb → resource_common.rb} +187 -88
  35. data/lib/jsonapi/resource_controller.rb +2 -0
  36. data/lib/jsonapi/resource_controller_metal.rb +2 -0
  37. data/lib/jsonapi/resource_fragment.rb +17 -15
  38. data/lib/jsonapi/resource_identity.rb +6 -0
  39. data/lib/jsonapi/resource_serializer.rb +20 -4
  40. data/lib/jsonapi/resource_set.rb +36 -16
  41. data/lib/jsonapi/resource_tree.rb +191 -0
  42. data/lib/jsonapi/resources/railtie.rb +3 -1
  43. data/lib/jsonapi/resources/version.rb +3 -1
  44. data/lib/jsonapi/response_document.rb +4 -2
  45. data/lib/jsonapi/routing_ext.rb +4 -2
  46. data/lib/jsonapi/simple_resource.rb +13 -0
  47. data/lib/jsonapi-resources.rb +10 -4
  48. data/lib/tasks/check_upgrade.rake +3 -1
  49. metadata +47 -15
  50. data/lib/jsonapi/resource_id_tree.rb +0 -112
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module JSONAPI
2
4
  class Relationship
3
5
  attr_reader :acts_as_set, :foreign_key, :options, :name,
4
- :class_name, :polymorphic, :always_include_optional_linkage_data,
6
+ :class_name, :polymorphic, :always_include_optional_linkage_data, :exclude_linkage_data,
5
7
  :parent_resource, :eager_load_on_include, :custom_methods,
6
- :inverse_relationship, :allow_include, :use_related_resource_records_for_joins
8
+ :inverse_relationship, :allow_include, :hidden, :use_related_resource_records_for_joins
7
9
 
8
10
  attr_writer :allow_include
9
11
 
@@ -15,7 +17,7 @@ module JSONAPI
15
17
  @acts_as_set = options.fetch(:acts_as_set, false) == true
16
18
  @foreign_key = options[:foreign_key] ? options[:foreign_key].to_sym : nil
17
19
  @parent_resource = options[:parent_resource]
18
- @relation_name = options.fetch(:relation_name, @name)
20
+ @relation_name = options[:relation_name]
19
21
  @polymorphic = options.fetch(:polymorphic, false) == true
20
22
  @polymorphic_types = options[:polymorphic_types]
21
23
  if options[:polymorphic_relations]
@@ -28,15 +30,19 @@ module JSONAPI
28
30
  else
29
31
  JSONAPI.configuration.use_related_resource_records_for_joins
30
32
  end
31
-
33
+
32
34
  @use_related_resource_records_for_joins = options.fetch(:use_related_resource_records_for_joins,
33
35
  use_related_resource_records_for_joins_default) == true
34
36
 
37
+ @hidden = options.fetch(:hidden, false) == true
38
+
39
+ @exclude_linkage_data = options[:exclude_linkage_data]
35
40
  @always_include_optional_linkage_data = options.fetch(:always_include_optional_linkage_data, false) == true
36
- @eager_load_on_include = options.fetch(:eager_load_on_include, false) == true
41
+ @eager_load_on_include = options.fetch(:eager_load_on_include, true) == true
37
42
  @allow_include = options[:allow_include]
38
43
  @class_name = nil
39
- @inverse_relationship = nil
44
+
45
+ @inverse_relationship = options[:inverse_relationship]&.to_sym
40
46
 
41
47
  @_routed = false
42
48
  @_warned_missing_route = false
@@ -66,12 +72,26 @@ module JSONAPI
66
72
  # :nocov:
67
73
  end
68
74
 
75
+ def inverse_relationship
76
+ unless @inverse_relationship
77
+ @inverse_relationship ||= if resource_klass._relationship(@parent_resource._type.to_s.singularize).present?
78
+ @parent_resource._type.to_s.singularize.to_sym
79
+ elsif resource_klass._relationship(@parent_resource._type).present?
80
+ @parent_resource._type.to_sym
81
+ else
82
+ nil
83
+ end
84
+ end
85
+
86
+ @inverse_relationship
87
+ end
88
+
69
89
  def self.polymorphic_types(name)
70
90
  @poly_hash ||= {}.tap do |hash|
71
91
  ObjectSpace.each_object do |klass|
72
92
  next unless Module === klass
73
93
  if ActiveRecord::Base > klass
74
- klass.reflect_on_all_associations(:has_many).select{|r| r.options[:as] }.each do |reflection|
94
+ klass.reflect_on_all_associations(:has_many).select { |r| r.options[:as] }.each do |reflection|
75
95
  (hash[reflection.options[:as]] ||= []) << klass.name.underscore
76
96
  end
77
97
  end
@@ -82,7 +102,7 @@ module JSONAPI
82
102
 
83
103
  def resource_types
84
104
  if polymorphic? && belongs_to?
85
- @polymorphic_types ||= self.class.polymorphic_types(@relation_name).collect {|t| t.pluralize}
105
+ @polymorphic_types ||= self.class.polymorphic_types(_relation_name).collect { |t| t.pluralize }
86
106
  else
87
107
  [resource_klass._type.to_s.pluralize]
88
108
  end
@@ -93,15 +113,15 @@ module JSONAPI
93
113
  end
94
114
 
95
115
  def relation_name(options)
96
- case @relation_name
97
- when Symbol
98
- # :nocov:
99
- @relation_name
100
- # :nocov:
101
- when String
102
- @relation_name.to_sym
103
- when Proc
104
- @relation_name.call(options)
116
+ case _relation_name
117
+ when Symbol
118
+ # :nocov:
119
+ _relation_name
120
+ # :nocov:
121
+ when String
122
+ _relation_name.to_sym
123
+ when Proc
124
+ _relation_name.call(options)
105
125
  end
106
126
  end
107
127
 
@@ -117,14 +137,14 @@ module JSONAPI
117
137
 
118
138
  def exclude_links(exclude)
119
139
  case exclude
120
- when :default, "default"
121
- @_exclude_links = [:self, :related]
122
- when :none, "none"
123
- @_exclude_links = []
124
- when Array
125
- @_exclude_links = exclude.collect {|link| link.to_sym}
126
- else
127
- fail "Invalid exclude_links"
140
+ when :default, "default"
141
+ @_exclude_links = [:self, :related]
142
+ when :none, "none"
143
+ @_exclude_links = []
144
+ when Array
145
+ @_exclude_links = exclude.collect { |link| link.to_sym }
146
+ else
147
+ fail "Invalid exclude_links"
128
148
  end
129
149
  end
130
150
 
@@ -136,6 +156,10 @@ module JSONAPI
136
156
  _exclude_links.include?(link.to_sym)
137
157
  end
138
158
 
159
+ def _relation_name
160
+ @relation_name || @name
161
+ end
162
+
139
163
  class ToOne < Relationship
140
164
  attr_reader :foreign_key_on
141
165
 
@@ -144,9 +168,16 @@ module JSONAPI
144
168
  @class_name = options.fetch(:class_name, name.to_s.camelize)
145
169
  @foreign_key ||= "#{name}_id".to_sym
146
170
  @foreign_key_on = options.fetch(:foreign_key_on, :self)
147
- if parent_resource
148
- @inverse_relationship = options.fetch(:inverse_relationship, parent_resource._type)
171
+ # if parent_resource
172
+ # @inverse_relationship = options.fetch(:inverse_relationship, parent_resource._type)
173
+ # end
174
+
175
+ if options.fetch(:create_implicit_polymorphic_type_relationships, true) == true && polymorphic?
176
+ # Setup the implicit relationships for the polymorphic types and exclude linkage data
177
+ setup_implicit_relationships_for_polymorphic_types
149
178
  end
179
+
180
+ @polymorphic_type_relationship_for = options[:polymorphic_type_relationship_for]
150
181
  end
151
182
 
152
183
  def to_s
@@ -161,11 +192,30 @@ module JSONAPI
161
192
  # :nocov:
162
193
  end
163
194
 
195
+ def hidden?
196
+ @hidden || @polymorphic_type_relationship_for.present?
197
+ end
198
+
164
199
  def polymorphic_type
165
200
  "#{name}_type" if polymorphic?
166
201
  end
167
202
 
203
+ def setup_implicit_relationships_for_polymorphic_types(exclude_linkage_data: true)
204
+ types = self.class.polymorphic_types(_relation_name)
205
+ unless types.present?
206
+ warn "No polymorphic types found for #{parent_resource.name} #{_relation_name}"
207
+ return
208
+ end
209
+
210
+ types.each do |type|
211
+ parent_resource.has_one(type.to_s.underscore.singularize,
212
+ exclude_linkage_data: exclude_linkage_data,
213
+ polymorphic_type_relationship_for: name)
214
+ end
215
+ end
216
+
168
217
  def include_optional_linkage_data?
218
+ return false if @exclude_linkage_data
169
219
  @always_include_optional_linkage_data || JSONAPI::configuration.always_include_to_one_linkage_data
170
220
  end
171
221
 
@@ -176,10 +226,10 @@ module JSONAPI
176
226
  @allow_include
177
227
  end
178
228
 
179
- if !!strategy == strategy #check for boolean
229
+ if !!strategy == strategy # check for boolean
180
230
  return strategy
181
231
  elsif strategy.is_a?(Symbol) || strategy.is_a?(String)
182
- parent_resource.send(strategy, context)
232
+ parent_resource_klass.send(strategy, context)
183
233
  else
184
234
  strategy.call(context)
185
235
  end
@@ -194,17 +244,21 @@ module JSONAPI
194
244
  @class_name = options.fetch(:class_name, name.to_s.camelize.singularize)
195
245
  @foreign_key ||= "#{name.to_s.singularize}_ids".to_sym
196
246
  @reflect = options.fetch(:reflect, true) == true
197
- if parent_resource
198
- @inverse_relationship = options.fetch(:inverse_relationship, parent_resource._type.to_s.singularize.to_sym)
199
- end
247
+ # if parent_resource
248
+ # @inverse_relationship = options.fetch(:inverse_relationship, parent_resource._type.to_s.singularize.to_sym)
249
+ # end
200
250
  end
201
251
 
202
252
  def to_s
203
253
  # :nocov: useful for debugging
204
- "#{parent_resource}.#{name}(ToMany)"
254
+ "#{parent_resource_klass}.#{name}(ToMany)"
205
255
  # :nocov:
206
256
  end
207
257
 
258
+ def hidden?
259
+ @hidden
260
+ end
261
+
208
262
  def include_optional_linkage_data?
209
263
  # :nocov:
210
264
  @always_include_optional_linkage_data || JSONAPI::configuration.always_include_to_many_linkage_data
@@ -218,10 +272,10 @@ module JSONAPI
218
272
  @allow_include
219
273
  end
220
274
 
221
- if !!strategy == strategy #check for boolean
275
+ if !!strategy == strategy # check for boolean
222
276
  return strategy
223
277
  elsif strategy.is_a?(Symbol) || strategy.is_a?(String)
224
- parent_resource.send(strategy, context)
278
+ parent_resource_klass.send(strategy, context)
225
279
  else
226
280
  strategy.call(context)
227
281
  end