jsonapi-resources 0.9.0 → 0.10.6

Sign up to get free protection for your applications and to get access to all the features.
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 +303 -0
  8. data/lib/jsonapi/active_relation_resource.rb +884 -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 +71 -8
  14. data/lib/jsonapi/error.rb +27 -0
  15. data/lib/jsonapi/error_codes.rb +2 -0
  16. data/lib/jsonapi/exceptions.rb +80 -50
  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 +239 -111
  25. data/lib/jsonapi/relationship.rb +153 -15
  26. data/lib/jsonapi/request_parser.rb +430 -367
  27. data/lib/jsonapi/resource.rb +3 -1253
  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 +50 -20
  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, :use_related_resource_records_for_joins
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,75 @@ 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
+ 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
+
41
+ @_routed = false
42
+ @_warned_missing_route = false
43
+
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, {})
17
48
  end
18
49
 
19
50
  alias_method :polymorphic?, :polymorphic
51
+ alias_method :parent_resource_klass, :parent_resource
20
52
 
21
53
  def primary_key
54
+ # :nocov:
22
55
  @primary_key ||= resource_klass._primary_key
56
+ # :nocov:
23
57
  end
24
58
 
25
59
  def resource_klass
26
- @resource_klass ||= @parent_resource.resource_for(@class_name)
60
+ @resource_klass ||= @parent_resource.resource_klass_for(@class_name)
27
61
  end
28
62
 
29
63
  def table_name
64
+ # :nocov:
30
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
31
89
  end
32
90
 
33
91
  def type
@@ -47,17 +105,35 @@ module JSONAPI
47
105
  end
48
106
  end
49
107
 
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
108
+ def belongs_to?
109
+ # :nocov:
110
+ false
111
+ # :nocov:
112
+ end
113
+
114
+ def readonly?
115
+ @options[:readonly]
116
+ end
117
+
118
+ def exclude_links(exclude)
119
+ 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"
56
128
  end
57
129
  end
58
130
 
59
- def belongs_to?
60
- false
131
+ def _exclude_links
132
+ @_exclude_links ||= []
133
+ end
134
+
135
+ def exclude_link?(link)
136
+ _exclude_links.include?(link.to_sym)
61
137
  end
62
138
 
63
139
  class ToOne < Relationship
@@ -68,27 +144,89 @@ module JSONAPI
68
144
  @class_name = options.fetch(:class_name, name.to_s.camelize)
69
145
  @foreign_key ||= "#{name}_id".to_sym
70
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
150
+ end
151
+
152
+ def to_s
153
+ # :nocov: useful for debugging
154
+ "#{parent_resource}.#{name}(#{belongs_to? ? 'BelongsToOne' : 'ToOne'})"
155
+ # :nocov:
71
156
  end
72
157
 
73
158
  def belongs_to?
159
+ # :nocov:
74
160
  foreign_key_on == :self
161
+ # :nocov:
75
162
  end
76
163
 
77
164
  def polymorphic_type
78
165
  "#{name}_type" if polymorphic?
79
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
80
187
  end
81
188
 
82
189
  class ToMany < Relationship
83
- attr_reader :reflect, :inverse_relationship
190
+ attr_reader :reflect
84
191
 
85
192
  def initialize(name, options = {})
86
193
  super
87
194
  @class_name = options.fetch(:class_name, name.to_s.camelize.singularize)
88
195
  @foreign_key ||= "#{name.to_s.singularize}_ids".to_sym
89
196
  @reflect = options.fetch(:reflect, true) == true
90
- @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
200
+ end
201
+
202
+ def to_s
203
+ # :nocov: useful for debugging
204
+ "#{parent_resource}.#{name}(ToMany)"
205
+ # :nocov:
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:
91
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
+
92
230
  end
93
231
  end
94
232
  end