jsonapi_compliable 0.11.34 → 1.0.alpha.2

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 (73) hide show
  1. checksums.yaml +5 -5
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +1 -2
  4. data/Rakefile +7 -3
  5. data/jsonapi_compliable.gemspec +7 -3
  6. data/lib/generators/jsonapi/resource_generator.rb +8 -79
  7. data/lib/generators/jsonapi/templates/application_resource.rb.erb +2 -1
  8. data/lib/generators/jsonapi/templates/controller.rb.erb +19 -64
  9. data/lib/generators/jsonapi/templates/resource.rb.erb +5 -47
  10. data/lib/generators/jsonapi/templates/resource_reads_spec.rb.erb +62 -0
  11. data/lib/generators/jsonapi/templates/resource_writes_spec.rb.erb +63 -0
  12. data/lib/jsonapi_compliable.rb +87 -18
  13. data/lib/jsonapi_compliable/adapters/abstract.rb +202 -45
  14. data/lib/jsonapi_compliable/adapters/active_record.rb +6 -130
  15. data/lib/jsonapi_compliable/adapters/active_record/base.rb +247 -0
  16. data/lib/jsonapi_compliable/adapters/active_record/belongs_to_sideload.rb +17 -0
  17. data/lib/jsonapi_compliable/adapters/active_record/has_many_sideload.rb +17 -0
  18. data/lib/jsonapi_compliable/adapters/active_record/has_one_sideload.rb +17 -0
  19. data/lib/jsonapi_compliable/adapters/active_record/inferrence.rb +12 -0
  20. data/lib/jsonapi_compliable/adapters/active_record/many_to_many_sideload.rb +30 -0
  21. data/lib/jsonapi_compliable/adapters/null.rb +177 -6
  22. data/lib/jsonapi_compliable/base.rb +33 -320
  23. data/lib/jsonapi_compliable/context.rb +16 -0
  24. data/lib/jsonapi_compliable/deserializer.rb +14 -39
  25. data/lib/jsonapi_compliable/errors.rb +227 -24
  26. data/lib/jsonapi_compliable/extensions/extra_attribute.rb +3 -1
  27. data/lib/jsonapi_compliable/filter_operators.rb +25 -0
  28. data/lib/jsonapi_compliable/hash_renderer.rb +57 -0
  29. data/lib/jsonapi_compliable/query.rb +190 -202
  30. data/lib/jsonapi_compliable/rails.rb +12 -6
  31. data/lib/jsonapi_compliable/railtie.rb +64 -0
  32. data/lib/jsonapi_compliable/renderer.rb +60 -0
  33. data/lib/jsonapi_compliable/resource.rb +35 -663
  34. data/lib/jsonapi_compliable/resource/configuration.rb +239 -0
  35. data/lib/jsonapi_compliable/resource/dsl.rb +138 -0
  36. data/lib/jsonapi_compliable/resource/interface.rb +32 -0
  37. data/lib/jsonapi_compliable/resource/polymorphism.rb +68 -0
  38. data/lib/jsonapi_compliable/resource/sideloading.rb +102 -0
  39. data/lib/jsonapi_compliable/resource_proxy.rb +127 -0
  40. data/lib/jsonapi_compliable/responders.rb +19 -0
  41. data/lib/jsonapi_compliable/runner.rb +25 -0
  42. data/lib/jsonapi_compliable/scope.rb +37 -79
  43. data/lib/jsonapi_compliable/scoping/extra_attributes.rb +29 -0
  44. data/lib/jsonapi_compliable/scoping/filter.rb +39 -58
  45. data/lib/jsonapi_compliable/scoping/filterable.rb +9 -14
  46. data/lib/jsonapi_compliable/scoping/paginate.rb +9 -3
  47. data/lib/jsonapi_compliable/scoping/sort.rb +16 -4
  48. data/lib/jsonapi_compliable/sideload.rb +221 -347
  49. data/lib/jsonapi_compliable/sideload/belongs_to.rb +34 -0
  50. data/lib/jsonapi_compliable/sideload/has_many.rb +16 -0
  51. data/lib/jsonapi_compliable/sideload/has_one.rb +9 -0
  52. data/lib/jsonapi_compliable/sideload/many_to_many.rb +24 -0
  53. data/lib/jsonapi_compliable/sideload/polymorphic_belongs_to.rb +108 -0
  54. data/lib/jsonapi_compliable/stats/payload.rb +4 -8
  55. data/lib/jsonapi_compliable/types.rb +172 -0
  56. data/lib/jsonapi_compliable/util/attribute_check.rb +88 -0
  57. data/lib/jsonapi_compliable/util/persistence.rb +29 -7
  58. data/lib/jsonapi_compliable/util/relationship_payload.rb +4 -4
  59. data/lib/jsonapi_compliable/util/render_options.rb +4 -32
  60. data/lib/jsonapi_compliable/util/serializer_attributes.rb +98 -0
  61. data/lib/jsonapi_compliable/util/validation_response.rb +15 -9
  62. data/lib/jsonapi_compliable/version.rb +1 -1
  63. metadata +105 -24
  64. data/lib/generators/jsonapi/field_generator.rb +0 -0
  65. data/lib/generators/jsonapi/templates/create_request_spec.rb.erb +0 -29
  66. data/lib/generators/jsonapi/templates/destroy_request_spec.rb.erb +0 -20
  67. data/lib/generators/jsonapi/templates/index_request_spec.rb.erb +0 -22
  68. data/lib/generators/jsonapi/templates/payload.rb.erb +0 -39
  69. data/lib/generators/jsonapi/templates/serializer.rb.erb +0 -25
  70. data/lib/generators/jsonapi/templates/show_request_spec.rb.erb +0 -19
  71. data/lib/generators/jsonapi/templates/update_request_spec.rb.erb +0 -33
  72. data/lib/jsonapi_compliable/adapters/active_record_sideloading.rb +0 -152
  73. data/lib/jsonapi_compliable/scoping/extra_fields.rb +0 -58
@@ -0,0 +1,30 @@
1
+ module JsonapiCompliable
2
+ module Adapters
3
+ module ActiveRecord
4
+ class ManyToManySideload < Sideload::ManyToMany
5
+ def default_base_scope
6
+ resource_class.model.all
7
+ end
8
+
9
+ def through_table_name
10
+ @through_table_name ||= parent_resource_class.model
11
+ .reflections[through.to_s].klass.table_name
12
+ end
13
+
14
+ def scope(parent_ids)
15
+ base_scope
16
+ .includes(through)
17
+ .where(through_table_name => { true_foreign_key => parent_ids })
18
+ .distinct
19
+ end
20
+
21
+ def infer_foreign_key
22
+ parent_model = parent_resource_class.model
23
+ key = parent_model.reflections[name.to_s].options[:through]
24
+ value = parent_model.reflections[key.to_s].foreign_key.to_sym
25
+ { key => value }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -4,11 +4,186 @@ module JsonapiCompliable
4
4
  # Useful when your customization does not support all possible
5
5
  # configuration (e.g. the service you hit does not support sorting)
6
6
  class Null < Abstract
7
- # (see Adapters::Abstract#filter)
8
- def filter(scope, attribute, value)
7
+ def filter_string_eq(scope, attribute, value)
9
8
  scope
10
9
  end
11
10
 
11
+ def filter_string_eql(scope, attribute, value)
12
+ scope
13
+ end
14
+
15
+ def filter_string_not_eq(scope, attribute, value)
16
+ scope
17
+ end
18
+
19
+ def filter_string_not_eql(scope, attribute, value)
20
+ scope
21
+ end
22
+
23
+ def filter_string_prefix_eq(scope, attribute, value)
24
+ scope
25
+ end
26
+
27
+ def filter_string_not_prefix_eq(scope, attribute, value)
28
+ scope
29
+ end
30
+
31
+ def filter_string_suffix_eq(scope, attribute, value)
32
+ scope
33
+ end
34
+
35
+ def filter_string_not_suffix_eq(scope, attribute, value)
36
+ scope
37
+ end
38
+
39
+ def filter_string_like_eq(scope, attribute, value)
40
+ scope
41
+ end
42
+
43
+ def filter_string_not_like_eq(scope, attribute, value)
44
+ scope
45
+ end
46
+
47
+ def filter_integer_eq(scope, attribute, value)
48
+ scope
49
+ end
50
+
51
+ def filter_integer_not_eq(scope, attribute, value)
52
+ scope
53
+ end
54
+
55
+ def filter_integer_gt(scope, attribute, value)
56
+ scope
57
+ end
58
+
59
+ def filter_integer_gte(scope, attribute, value)
60
+ scope
61
+ end
62
+
63
+ def filter_integer_lt(scope, attribute, value)
64
+ scope
65
+ end
66
+
67
+ def filter_integer_lte(scope, attribute, value)
68
+ scope
69
+ end
70
+
71
+ def filter_datetime_eq(scope, attribute, value)
72
+ scope
73
+ end
74
+
75
+ def filter_datetime_not_eq(scope, attribute, value)
76
+ scope
77
+ end
78
+
79
+ def filter_datetime_lte(scope, attribute, value)
80
+ scope
81
+ end
82
+
83
+ def filter_float_eq(scope, attribute, value)
84
+ scope
85
+ end
86
+
87
+ def filter_float_not_eq(scope, attribute, value)
88
+ scope
89
+ end
90
+
91
+ def filter_float_gt(scope, attribute, value)
92
+ scope
93
+ end
94
+
95
+ def filter_float_gte(scope, attribute, value)
96
+ scope
97
+ end
98
+
99
+ def filter_float_lt(scope, attribute, value)
100
+ scope
101
+ end
102
+
103
+ def filter_float_lte(scope, attribute, value)
104
+ scope
105
+ end
106
+
107
+ def filter_decimal_eq(scope, attribute, value)
108
+ scope
109
+ end
110
+
111
+ def filter_decimal_not_eq(scope, attribute, value)
112
+ scope
113
+ end
114
+
115
+ def filter_decimal_gt(scope, attribute, value)
116
+ scope
117
+ end
118
+
119
+ def filter_decimal_gte(scope, attribute, value)
120
+ scope
121
+ end
122
+
123
+ def filter_decimal_lt(scope, attribute, value)
124
+ scope
125
+ end
126
+
127
+ def filter_decimal_lte(scope, attribute, value)
128
+ scope
129
+ end
130
+
131
+ def filter_datetime_eq(scope, attribute, value)
132
+ scope
133
+ end
134
+
135
+ def filter_datetime_not_eq(scope, attribute, value)
136
+ scope
137
+ end
138
+
139
+ def filter_datetime_gt(scope, attribute, value)
140
+ scope
141
+ end
142
+
143
+ def filter_datetime_gte(scope, attribute, value)
144
+ scope
145
+ end
146
+
147
+ def filter_datetime_lt(scope, attribute, value)
148
+ scope
149
+ end
150
+
151
+ def filter_datetime_lte(scope, attribute, value)
152
+ scope
153
+ end
154
+
155
+ def filter_date_eq(scope, attribute, value)
156
+ scope
157
+ end
158
+
159
+ def filter_date_not_eq(scope, attribute, value)
160
+ scope
161
+ end
162
+
163
+ def filter_date_gt(scope, attribute, value)
164
+ scope
165
+ end
166
+
167
+ def filter_date_gte(scope, attribute, value)
168
+ scope
169
+ end
170
+
171
+ def filter_date_lt(scope, attribute, value)
172
+ scope
173
+ end
174
+
175
+ def filter_date_lte(scope, attribute, value)
176
+ scope
177
+ end
178
+
179
+ def filter_boolean_eq(scope, attribute, value)
180
+ scope
181
+ end
182
+
183
+ def base_scope(model)
184
+ raise 'Null adapter has no base scope!'
185
+ end
186
+
12
187
  # (see Adapters::Abstract#order)
13
188
  def order(scope, attribute, direction)
14
189
  scope
@@ -56,10 +231,6 @@ module JsonapiCompliable
56
231
  def resolve(scope)
57
232
  scope
58
233
  end
59
-
60
- # (see Adapters::Abstract#associate)
61
- def associate(parent, child, association_name, association_type)
62
- end
63
234
  end
64
235
  end
65
236
  end
@@ -1,357 +1,70 @@
1
1
  module JsonapiCompliable
2
- # Provides main interface to jsonapi_compliable
3
- #
4
- # This gets mixed in to a "context" class, such as a Rails controller.
5
2
  module Base
6
3
  extend ActiveSupport::Concern
7
4
 
8
- included do
9
- class << self
10
- attr_accessor :_jsonapi_compliable, :_sideload_whitelist
11
- end
12
-
13
- def self.inherited(klass)
14
- super
15
- klass._jsonapi_compliable = Class.new(_jsonapi_compliable)
16
- klass._sideload_whitelist = _sideload_whitelist.dup if _sideload_whitelist
17
- end
18
- end
19
-
20
- # @!classmethods
21
- module ClassMethods
22
- # Define your JSONAPI configuration
23
- #
24
- # @example Inline Resource
25
- # # 'Quick and Dirty' solution that does not require a separate
26
- # # Resource object
27
- # class PostsController < ApplicationController
28
- # jsonapi do
29
- # type :posts
30
- # use_adapter JsonapiCompliable::Adapters::ActiveRecord
31
- #
32
- # allow_filter :title
33
- # end
34
- # end
35
- #
36
- # @example Resource Class (preferred)
37
- # # Make code reusable by encapsulating it in a Resource class
38
- # class PostsController < ApplicationController
39
- # jsonapi resource: PostResource
40
- # end
41
- #
42
- # @see Resource
43
- # @param resource [Resource] the Resource class associated to this endpoint
44
- # @return [void]
45
- def jsonapi(foo = 'bar', resource: nil, &blk)
46
- if resource
47
- self._jsonapi_compliable = resource
48
- else
49
- if !self._jsonapi_compliable
50
- self._jsonapi_compliable = Class.new(JsonapiCompliable::Resource)
51
- end
52
- end
53
-
54
- self._jsonapi_compliable.class_eval(&blk) if blk
55
- end
56
-
57
- # Set the sideload whitelist. You may want to omit sideloads for
58
- # security or performance reasons.
59
- #
60
- # Uses JSONAPI::IncludeDirective from {{http://jsonapi-rb.org jsonapi-rb}}
61
- #
62
- # @example Whitelisting Relationships
63
- # # Given the following whitelist
64
- # class PostsController < ApplicationResource
65
- # jsonapi resource: MyResource
66
- #
67
- # sideload_whitelist({
68
- # index: [:blog],
69
- # show: [:blog, { comments: :author }]
70
- # })
71
- #
72
- # # ... code ...
73
- # end
74
- #
75
- # # A request to sideload 'tags'
76
- # #
77
- # # GET /posts/1?include=tags
78
- # #
79
- # # ...will silently fail.
80
- # #
81
- # # A request for comments and tags:
82
- # #
83
- # # GET /posts/1?include=tags,comments
84
- # #
85
- # # ...will only sideload comments
86
- #
87
- # @param [Hash, Array, Symbol] whitelist
88
- # @see Query#include_hash
89
- def sideload_whitelist(hash)
90
- self._sideload_whitelist = JSONAPI::IncludeDirective.new(hash).to_hash
91
- end
92
- end
93
-
94
- # @api private
95
- def sideload_whitelist
96
- self.class._sideload_whitelist || {}
97
- end
98
-
99
- # Returns an instance of the associated Resource
100
- #
101
- # In other words, if you configured your controller as:
102
- #
103
- # jsonapi resource: MyResource
104
- #
105
- # This returns MyResource.new
106
- #
107
- # @return [Resource] the configured Resource for this controller
108
5
  def jsonapi_resource
109
- @jsonapi_resource ||= begin
110
- resource = self.class._jsonapi_compliable
111
- if resource.is_a?(Hash)
112
- resource[action_name.to_sym].new
113
- else
114
- resource.new
115
- end
116
- end
6
+ @jsonapi_resource
117
7
  end
118
8
 
119
- # Instantiates the relevant Query object
120
- #
121
- # @see Query
122
- # @return [Query] the Query object for this resource/params
123
9
  def query
124
10
  @query ||= Query.new(jsonapi_resource, params)
125
11
  end
126
12
 
127
- # @see Query#to_hash
128
- # @return [Hash] the normalized query hash for only the *current* resource
129
13
  def query_hash
130
- @query_hash ||= query.to_hash[jsonapi_resource.type]
14
+ @query_hash ||= query.to_hash
131
15
  end
132
16
 
133
- # Tracks the current context so we can refer to it within any
134
- # random object. Helpful for easy-access to things like the current
135
- # user.
136
- #
137
- # @api private
138
- # @yieldreturn Code to run within the current context
139
17
  def wrap_context
140
- jsonapi_resource.with_context(jsonapi_context, action_name.to_sym) do
18
+ JsonapiCompliable.with_context(jsonapi_context, action_name.to_sym) do
141
19
  yield
142
20
  end
143
21
  end
144
22
 
145
- # Override if you'd like the "context" to be something other than
146
- # an instance of this class.
147
- # In Rails, context is the controller instance.
148
- #
149
- # @example Overriding
150
- # # within your controller
151
- # def jsonapi_context
152
- # current_user
153
- # end
154
- #
155
- # # within a resource
156
- # default_filter :by_user do |scope, context|
157
- # scope.where(user_id: context.id)
158
- # end
159
- #
160
- # @return the context object you'd like
161
23
  def jsonapi_context
162
24
  self
163
25
  end
164
26
 
165
- # Use when direct, low-level access to the scope is required.
166
- #
167
- # @example Show Action
168
- # # Scope#resolve returns an array, but we only want to render
169
- # # one object, not an array
170
- # scope = jsonapi_scope(Employee.where(id: params[:id]))
171
- # render_jsonapi(scope.resolve.first, scope: false)
172
- #
173
- # @example Scope Chaining
174
- # # Chain onto scope after running through typical DSL
175
- # # Here, we'll add active: true to our hash if the user
176
- # # is filtering on something
177
- # scope = jsonapi_scope({})
178
- # scope.object.merge!(active: true) if scope.object[:filter]
179
- #
180
- # @see Resource#build_scope
181
- # @return [Scope] the configured scope
182
27
  def jsonapi_scope(scope, opts = {})
183
28
  jsonapi_resource.build_scope(scope, query, opts)
184
29
  end
185
30
 
186
- # @see Deserializer#initialize
187
- # @return [Deserializer]
188
- def deserialized_params
189
- @deserialized_params ||= JsonapiCompliable::Deserializer.new(params, request.env)
190
- end
191
-
192
- # Create the resource model and process all nested relationships via the
193
- # serialized parameters. Any error, including validation errors, will roll
194
- # back the transaction.
195
- #
196
- # @example Basic Rails
197
- # # Example Resource must have 'model'
198
- # #
199
- # # class PostResource < ApplicationResource
200
- # # model Post
201
- # # end
202
- # def create
203
- # post, success = jsonapi_create.to_a
204
- #
205
- # if success
206
- # render_jsonapi(post, scope: false)
207
- # else
208
- # render_errors_for(post)
209
- # end
210
- # end
211
- #
212
- # @see Resource.model
213
- # @see #resource
214
- # @see #deserialized_params
215
- # @return [Util::ValidationResponse]
216
- def jsonapi_create
217
- _persist do
218
- jsonapi_resource.persist_with_relationships \
219
- deserialized_params.meta,
220
- deserialized_params.attributes,
221
- deserialized_params.relationships
31
+ def normalized_params
32
+ normalized = params
33
+ if normalized.respond_to?(:to_unsafe_h)
34
+ normalized = normalized.to_unsafe_h.deep_symbolize_keys
222
35
  end
36
+ normalized
223
37
  end
224
38
 
225
- # Update the resource model and process all nested relationships via the
226
- # serialized parameters. Any error, including validation errors, will roll
227
- # back the transaction.
228
- #
229
- # @example Basic Rails
230
- # # Example Resource must have 'model'
231
- # #
232
- # # class PostResource < ApplicationResource
233
- # # model Post
234
- # # end
235
- # def update
236
- # post, success = jsonapi_update.to_a
237
- #
238
- # if success
239
- # render_jsonapi(post, scope: false)
240
- # else
241
- # render_errors_for(post)
242
- # end
243
- # end
244
- #
245
- # @see #jsonapi_create
246
- # @return [Util::ValidationResponse]
247
- def jsonapi_update
248
- _persist do
249
- jsonapi_resource.persist_with_relationships \
250
- deserialized_params.meta,
251
- deserialized_params.attributes,
252
- deserialized_params.relationships
253
- end
254
- end
255
-
256
- # Delete the model
257
- # Any error, including validation errors, will roll back the transaction.
258
- #
259
- # Note: +before_commit+ hooks still run unless excluded
260
- #
261
- # @return [Util::ValidationResponse]
262
- def jsonapi_destroy
263
- jsonapi_resource.transaction do
264
- model = jsonapi_resource.destroy(params[:id])
265
- validator = ::JsonapiCompliable::Util::ValidationResponse.new \
266
- model, deserialized_params
267
- validator.validate!
268
- jsonapi_resource.before_commit(model, :destroy)
269
- validator
270
- end
271
- end
272
-
273
- # Similar to +render :json+ or +render :jsonapi+
274
- #
275
- # By default, this will "build" the scope via +#jsonapi_scope+. To avoid
276
- # this, pass +scope: false+
277
- #
278
- # This builds relevant options and sends them to
279
- # +JSONAPI::Serializable::SuccessRenderer#render+from
280
- # {http://jsonapi-rb.org jsonapi-rb}
281
- #
282
- # @example Build Scope by Default
283
- # # Employee.all returns an ActiveRecord::Relation. No SQL is fired at this point.
284
- # # We further 'chain' onto this scope, applying pagination, sorting,
285
- # # filters, etc that the user has requested.
286
- # def index
287
- # employees = Employee.all
288
- # render_jsonapi(employees)
289
- # end
290
- #
291
- # @example Avoid Building Scope by Default
292
- # # Maybe we already manually scoped, and don't want to fire the logic twice
293
- # # This code is equivalent to the above example
294
- # def index
295
- # scope = jsonapi_scope(Employee.all)
296
- # # ... do other things with the scope ...
297
- # render_jsonapi(scope.resolve, scope: false)
298
- # end
299
- #
300
- # @param scope [Scope, Object] the scope to build or render.
301
- # @param [Hash] opts the render options passed to {http://jsonapi-rb.org jsonapi-rb}
302
- # @option opts [Boolean] :scope Default: true. Should we call #jsonapi_scope on this object?
303
- # @see #jsonapi_scope
304
- def render_jsonapi(scope, opts = {})
305
- scope = jsonapi_scope(scope) unless opts[:scope] == false || scope.is_a?(JsonapiCompliable::Scope)
306
- opts = default_jsonapi_render_options.merge(opts)
307
- opts = Util::RenderOptions.generate(scope, query_hash, opts)
308
- opts[:expose][:context] = self
309
-
310
- if opts[:include].empty? && force_includes?
311
- opts[:include] = deserialized_params.include_directive
312
- end
313
-
314
- perform_render_jsonapi(opts)
315
- end
316
-
317
- # Define a hash that will be automatically merged into your
318
- # render_jsonapi call
319
- #
320
- # @example
321
- # # this
322
- # render_jsonapi(foo)
323
- # # is equivalent to this
324
- # render jsonapi: foo, default_jsonapi_render_options
325
- #
326
- # @see #render_jsonapi
327
- # @return [Hash] the options hash you define
328
- def default_jsonapi_render_options
329
- {}.tap do |options|
330
- end
331
- end
332
-
333
- private
334
-
335
- def _persist
336
- jsonapi_resource.transaction do
337
- ::JsonapiCompliable::Util::Hooks.record do
338
- model = yield
339
- validator = ::JsonapiCompliable::Util::ValidationResponse.new \
340
- model, deserialized_params
341
- validator.validate!
342
- validator
39
+ def deserialized_params
40
+ @deserialized_params ||= begin
41
+ payload = normalized_params
42
+ if payload[:data] && payload[:data][:type]
43
+ JsonapiCompliable::Deserializer.new(payload)
343
44
  end
344
45
  end
345
46
  end
346
47
 
347
- def force_includes?
348
- not (deserialized_params.data.nil? || deserialized_params.data.empty?)
349
- end
350
-
351
- def perform_render_jsonapi(opts)
352
- # TODO(beauby): Reuse renderer.
353
- JSONAPI::Serializable::Renderer.new
354
- .render(opts.delete(:jsonapi), opts).to_json
48
+ def jsonapi_render_options
49
+ options = {}
50
+ options.merge!(default_jsonapi_render_options)
51
+ options[:meta] ||= {}
52
+ options[:expose] ||= {}
53
+ options[:expose][:context] = jsonapi_context
54
+ options
55
+ end
56
+
57
+ def proxy(base = nil, opts = {})
58
+ base ||= jsonapi_resource.base_scope
59
+ scope_opts = opts.slice :sideload_parent_length,
60
+ :default_paginate, :after_resolve
61
+ scope = jsonapi_scope(base, scope_opts)
62
+ ResourceProxy.new jsonapi_resource,
63
+ scope,
64
+ query,
65
+ payload: deserialized_params,
66
+ single: opts[:single],
67
+ raise_on_missing: opts[:raise_on_missing]
355
68
  end
356
69
  end
357
70
  end