jsonapi-resources 0.10.7 → 0.11.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
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