jsonapi-resources 0.9.3 → 0.10.5

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 +5 -5
  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 +879 -0
  9. data/lib/jsonapi/acts_as_resource_controller.rb +122 -105
  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 +63 -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 -65
  19. data/lib/jsonapi/link_builder.rb +74 -80
  20. data/lib/jsonapi/operation.rb +16 -5
  21. data/lib/jsonapi/operation_result.rb +74 -16
  22. data/lib/jsonapi/path.rb +43 -0
  23. data/lib/jsonapi/path_segment.rb +76 -0
  24. data/lib/jsonapi/processor.rb +237 -110
  25. data/lib/jsonapi/relationship.rb +144 -15
  26. data/lib/jsonapi/request_parser.rb +412 -357
  27. data/lib/jsonapi/resource.rb +3 -1263
  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 +143 -285
  33. data/lib/jsonapi/resource_set.rb +176 -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 +105 -83
  37. data/lib/jsonapi/routing_ext.rb +48 -26
  38. data/lib/jsonapi-resources.rb +20 -4
  39. data/lib/tasks/check_upgrade.rake +52 -0
  40. metadata +47 -17
  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,13 @@
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
9
+
10
+ attr_accessor :_routed, :_warned_missing_route
6
11
 
7
12
  def initialize(name, options = {})
8
13
  @name = name.to_s
@@ -12,22 +17,66 @@ module JSONAPI
12
17
  @parent_resource = options[:parent_resource]
13
18
  @relation_name = options.fetch(:relation_name, @name)
14
19
  @polymorphic = options.fetch(:polymorphic, false) == true
15
- @always_include_linkage_data = options.fetch(:always_include_linkage_data, false) == true
16
- @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
+
32
+ @_routed = false
33
+ @_warned_missing_route = false
34
+
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, {})
17
39
  end
18
40
 
19
41
  alias_method :polymorphic?, :polymorphic
42
+ alias_method :parent_resource_klass, :parent_resource
20
43
 
21
44
  def primary_key
45
+ # :nocov:
22
46
  @primary_key ||= resource_klass._primary_key
47
+ # :nocov:
23
48
  end
24
49
 
25
50
  def resource_klass
26
- @resource_klass ||= @parent_resource.resource_for(@class_name)
51
+ @resource_klass ||= @parent_resource.resource_klass_for(@class_name)
27
52
  end
28
53
 
29
54
  def table_name
55
+ # :nocov:
30
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.underscore
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
31
80
  end
32
81
 
33
82
  def type
@@ -47,17 +96,35 @@ module JSONAPI
47
96
  end
48
97
  end
49
98
 
50
- def type_for_source(source)
51
- if polymorphic?
52
- resource = source.public_send(name)
53
- resource.class._type if resource
54
- else
55
- type
99
+ def belongs_to?
100
+ # :nocov:
101
+ false
102
+ # :nocov:
103
+ end
104
+
105
+ def readonly?
106
+ @options[:readonly]
107
+ end
108
+
109
+ def exclude_links(exclude)
110
+ case exclude
111
+ when :default, "default"
112
+ @_exclude_links = [:self, :related]
113
+ when :none, "none"
114
+ @_exclude_links = []
115
+ when Array
116
+ @_exclude_links = exclude.collect {|link| link.to_sym}
117
+ else
118
+ fail "Invalid exclude_links"
56
119
  end
57
120
  end
58
121
 
59
- def belongs_to?
60
- false
122
+ def _exclude_links
123
+ @_exclude_links ||= []
124
+ end
125
+
126
+ def exclude_link?(link)
127
+ _exclude_links.include?(link.to_sym)
61
128
  end
62
129
 
63
130
  class ToOne < Relationship
@@ -68,27 +135,89 @@ module JSONAPI
68
135
  @class_name = options.fetch(:class_name, name.to_s.camelize)
69
136
  @foreign_key ||= "#{name}_id".to_sym
70
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
141
+ end
142
+
143
+ def to_s
144
+ # :nocov: useful for debugging
145
+ "#{parent_resource}.#{name}(#{belongs_to? ? 'BelongsToOne' : 'ToOne'})"
146
+ # :nocov:
71
147
  end
72
148
 
73
149
  def belongs_to?
150
+ # :nocov:
74
151
  foreign_key_on == :self
152
+ # :nocov:
75
153
  end
76
154
 
77
155
  def polymorphic_type
78
156
  "#{name}_type" if polymorphic?
79
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
80
178
  end
81
179
 
82
180
  class ToMany < Relationship
83
- attr_reader :reflect, :inverse_relationship
181
+ attr_reader :reflect
84
182
 
85
183
  def initialize(name, options = {})
86
184
  super
87
185
  @class_name = options.fetch(:class_name, name.to_s.camelize.singularize)
88
186
  @foreign_key ||= "#{name.to_s.singularize}_ids".to_sym
89
187
  @reflect = options.fetch(:reflect, true) == true
90
- @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
191
+ end
192
+
193
+ def to_s
194
+ # :nocov: useful for debugging
195
+ "#{parent_resource}.#{name}(ToMany)"
196
+ # :nocov:
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:
91
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
+
92
221
  end
93
222
  end
94
223
  end