jsonapi-resources 0.9.12 → 0.10.0

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