jsonapi-resources 0.9.12 → 0.10.7

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 (45) hide show
  1. checksums.yaml +4 -4
  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/active_relation/adapters/join_left_active_record_adapter.rb +27 -0
  7. data/lib/jsonapi/active_relation/join_manager.rb +303 -0
  8. data/lib/jsonapi/active_relation_resource.rb +884 -0
  9. data/lib/jsonapi/acts_as_resource_controller.rb +122 -106
  10. data/lib/jsonapi/basic_resource.rb +1162 -0
  11. data/lib/jsonapi/cached_response_fragment.rb +127 -0
  12. data/lib/jsonapi/compiled_json.rb +11 -1
  13. data/lib/jsonapi/configuration.rb +57 -8
  14. data/lib/jsonapi/error.rb +27 -0
  15. data/lib/jsonapi/error_codes.rb +2 -0
  16. data/lib/jsonapi/exceptions.rb +63 -40
  17. data/lib/jsonapi/formatter.rb +3 -3
  18. data/lib/jsonapi/include_directives.rb +18 -75
  19. data/lib/jsonapi/link_builder.rb +18 -25
  20. data/lib/jsonapi/operation.rb +16 -5
  21. data/lib/jsonapi/operation_result.rb +73 -15
  22. data/lib/jsonapi/paginator.rb +17 -0
  23. data/lib/jsonapi/path.rb +43 -0
  24. data/lib/jsonapi/path_segment.rb +76 -0
  25. data/lib/jsonapi/processor.rb +246 -111
  26. data/lib/jsonapi/relationship.rb +117 -24
  27. data/lib/jsonapi/request_parser.rb +383 -396
  28. data/lib/jsonapi/resource.rb +3 -1376
  29. data/lib/jsonapi/resource_controller_metal.rb +3 -0
  30. data/lib/jsonapi/resource_fragment.rb +47 -0
  31. data/lib/jsonapi/resource_id_tree.rb +112 -0
  32. data/lib/jsonapi/resource_identity.rb +42 -0
  33. data/lib/jsonapi/resource_serializer.rb +124 -286
  34. data/lib/jsonapi/resource_set.rb +176 -0
  35. data/lib/jsonapi/resources/railtie.rb +9 -0
  36. data/lib/jsonapi/resources/version.rb +1 -1
  37. data/lib/jsonapi/response_document.rb +104 -87
  38. data/lib/jsonapi/routing_ext.rb +19 -21
  39. data/lib/jsonapi-resources.rb +20 -4
  40. data/lib/tasks/check_upgrade.rake +52 -0
  41. metadata +34 -31
  42. data/lib/jsonapi/cached_resource_fragment.rb +0 -127
  43. data/lib/jsonapi/operation_dispatcher.rb +0 -88
  44. data/lib/jsonapi/operation_results.rb +0 -35
  45. data/lib/jsonapi/relationship_builder.rb +0 -167
@@ -1,8 +1,11 @@
1
1
  module JSONAPI
2
2
  class Relationship
3
3
  attr_reader :acts_as_set, :foreign_key, :options, :name,
4
- :class_name, :polymorphic, :always_include_linkage_data,
5
- :parent_resource, :eager_load_on_include
4
+ :class_name, :polymorphic, :always_include_optional_linkage_data,
5
+ :parent_resource, :eager_load_on_include, :custom_methods,
6
+ :inverse_relationship, :allow_include, :use_related_resource_records_for_joins
7
+
8
+ attr_writer :allow_include
6
9
 
7
10
  attr_accessor :_routed, :_warned_missing_route
8
11
 
@@ -14,26 +17,75 @@ module JSONAPI
14
17
  @parent_resource = options[:parent_resource]
15
18
  @relation_name = options.fetch(:relation_name, @name)
16
19
  @polymorphic = options.fetch(:polymorphic, false) == true
17
- @always_include_linkage_data = options.fetch(:always_include_linkage_data, false) == true
18
- @eager_load_on_include = options.fetch(:eager_load_on_include, true) == true
20
+ @polymorphic_types = options[:polymorphic_types]
21
+ if options[:polymorphic_relations]
22
+ ActiveSupport::Deprecation.warn('Use polymorphic_types instead of polymorphic_relations')
23
+ @polymorphic_types ||= options[:polymorphic_relations]
24
+ end
25
+
26
+ use_related_resource_records_for_joins_default = if options[:relation_name]
27
+ false
28
+ else
29
+ JSONAPI.configuration.use_related_resource_records_for_joins
30
+ end
31
+
32
+ @use_related_resource_records_for_joins = options.fetch(:use_related_resource_records_for_joins,
33
+ use_related_resource_records_for_joins_default) == true
34
+
35
+ @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
37
+ @allow_include = options[:allow_include]
38
+ @class_name = nil
39
+ @inverse_relationship = nil
40
+
19
41
  @_routed = false
20
42
  @_warned_missing_route = false
21
43
 
22
44
  exclude_links(options.fetch(:exclude_links, JSONAPI.configuration.default_exclude_links))
45
+
46
+ # Custom methods are reserved for future use
47
+ @custom_methods = options.fetch(:custom_methods, {})
23
48
  end
24
49
 
25
50
  alias_method :polymorphic?, :polymorphic
51
+ alias_method :parent_resource_klass, :parent_resource
26
52
 
27
53
  def primary_key
54
+ # :nocov:
28
55
  @primary_key ||= resource_klass._primary_key
56
+ # :nocov:
29
57
  end
30
58
 
31
59
  def resource_klass
32
- @resource_klass ||= @parent_resource.resource_for(@class_name)
60
+ @resource_klass ||= @parent_resource.resource_klass_for(@class_name)
33
61
  end
34
62
 
35
63
  def table_name
64
+ # :nocov:
36
65
  @table_name ||= resource_klass._table_name
66
+ # :nocov:
67
+ end
68
+
69
+ def self.polymorphic_types(name)
70
+ @poly_hash ||= {}.tap do |hash|
71
+ ObjectSpace.each_object do |klass|
72
+ next unless Module === klass
73
+ if ActiveRecord::Base > klass
74
+ klass.reflect_on_all_associations(:has_many).select{|r| r.options[:as] }.each do |reflection|
75
+ (hash[reflection.options[:as]] ||= []) << klass.name.underscore
76
+ end
77
+ end
78
+ end
79
+ end
80
+ @poly_hash[name.to_sym]
81
+ end
82
+
83
+ def resource_types
84
+ if polymorphic? && belongs_to?
85
+ @polymorphic_types ||= self.class.polymorphic_types(@relation_name).collect {|t| t.pluralize}
86
+ else
87
+ [resource_klass._type.to_s.pluralize]
88
+ end
37
89
  end
38
90
 
39
91
  def type
@@ -53,23 +105,14 @@ module JSONAPI
53
105
  end
54
106
  end
55
107
 
56
- def type_for_source(source)
57
- if polymorphic?
58
- # try polymorphic type column before asking it from the resource record
59
- if source._model.respond_to?(polymorphic_type)
60
- model_type = source._model.send(polymorphic_type)
61
- source.class.resource_for(model_type)._type if model_type
62
- else
63
- resource = source.public_send(name)
64
- resource.class._type if resource
65
- end
66
- else
67
- type
68
- end
69
- end
70
-
71
108
  def belongs_to?
109
+ # :nocov:
72
110
  false
111
+ # :nocov:
112
+ end
113
+
114
+ def readonly?
115
+ @options[:readonly]
73
116
  end
74
117
 
75
118
  def exclude_links(exclude)
@@ -101,39 +144,89 @@ module JSONAPI
101
144
  @class_name = options.fetch(:class_name, name.to_s.camelize)
102
145
  @foreign_key ||= "#{name}_id".to_sym
103
146
  @foreign_key_on = options.fetch(:foreign_key_on, :self)
147
+ if parent_resource
148
+ @inverse_relationship = options.fetch(:inverse_relationship, parent_resource._type)
149
+ end
104
150
  end
105
151
 
106
152
  def to_s
107
- # :nocov:
153
+ # :nocov: useful for debugging
108
154
  "#{parent_resource}.#{name}(#{belongs_to? ? 'BelongsToOne' : 'ToOne'})"
109
155
  # :nocov:
110
156
  end
111
157
 
112
158
  def belongs_to?
159
+ # :nocov:
113
160
  foreign_key_on == :self
161
+ # :nocov:
114
162
  end
115
163
 
116
164
  def polymorphic_type
117
165
  "#{name}_type" if polymorphic?
118
166
  end
167
+
168
+ def include_optional_linkage_data?
169
+ @always_include_optional_linkage_data || JSONAPI::configuration.always_include_to_one_linkage_data
170
+ end
171
+
172
+ def allow_include?(context = nil)
173
+ strategy = if @allow_include.nil?
174
+ JSONAPI.configuration.default_allow_include_to_one
175
+ else
176
+ @allow_include
177
+ end
178
+
179
+ if !!strategy == strategy #check for boolean
180
+ return strategy
181
+ elsif strategy.is_a?(Symbol) || strategy.is_a?(String)
182
+ parent_resource.send(strategy, context)
183
+ else
184
+ strategy.call(context)
185
+ end
186
+ end
119
187
  end
120
188
 
121
189
  class ToMany < Relationship
122
- attr_reader :reflect, :inverse_relationship
190
+ attr_reader :reflect
123
191
 
124
192
  def initialize(name, options = {})
125
193
  super
126
194
  @class_name = options.fetch(:class_name, name.to_s.camelize.singularize)
127
195
  @foreign_key ||= "#{name.to_s.singularize}_ids".to_sym
128
196
  @reflect = options.fetch(:reflect, true) == true
129
- @inverse_relationship = options.fetch(:inverse_relationship, parent_resource._type.to_s.singularize.to_sym) if parent_resource
197
+ if parent_resource
198
+ @inverse_relationship = options.fetch(:inverse_relationship, parent_resource._type.to_s.singularize.to_sym)
199
+ end
130
200
  end
131
201
 
132
202
  def to_s
133
- # :nocov:
203
+ # :nocov: useful for debugging
134
204
  "#{parent_resource}.#{name}(ToMany)"
135
205
  # :nocov:
136
206
  end
207
+
208
+ def include_optional_linkage_data?
209
+ # :nocov:
210
+ @always_include_optional_linkage_data || JSONAPI::configuration.always_include_to_many_linkage_data
211
+ # :nocov:
212
+ end
213
+
214
+ def allow_include?(context = nil)
215
+ strategy = if @allow_include.nil?
216
+ JSONAPI.configuration.default_allow_include_to_many
217
+ else
218
+ @allow_include
219
+ end
220
+
221
+ if !!strategy == strategy #check for boolean
222
+ return strategy
223
+ elsif strategy.is_a?(Symbol) || strategy.is_a?(String)
224
+ parent_resource.send(strategy, context)
225
+ else
226
+ strategy.call(context)
227
+ end
228
+ end
229
+
137
230
  end
138
231
  end
139
232
  end