11require 'jsonapi/deserializable'
22require 'jsonapi/parser'
3+ require 'jsonapi/rails/configuration'
34
45module JSONAPI
56 module Rails
67 module Deserializable
8+ # @private
79 class Resource < JSONAPI ::Deserializable ::Resource
810 id
911 type
@@ -20,22 +22,56 @@ class Resource < JSONAPI::Deserializable::Resource
2022 end
2123 end
2224
25+ # ActionController methods and hooks for JSON API deserialization and
26+ # rendering.
2327 module Controller
2428 extend ActiveSupport ::Concern
2529
26- JSONAPI_POINTERS_KEY = 'jsonapi_deserializable .jsonapi_pointers' . freeze
30+ JSONAPI_POINTERS_KEY = 'jsonapi-rails .jsonapi_pointers' . freeze
2731
2832 class_methods do
33+ # Declare a deserializable resource.
34+ #
35+ # @param key [Symbol] The key under which the deserialized hash will be
36+ # available within the `params` hash.
37+ # @param options [Hash]
38+ # @option class [Class] A custom deserializer class. Optional.
39+ # @option only List of actions for which deserialization should happen.
40+ # Optional.
41+ # @option except List of actions for which deserialization should not
42+ # happen. Optional.
43+ # @yieldreturn Optional block for in-line definition of custom
44+ # deserializers.
45+ #
46+ # @example
47+ # class ArticlesController < ActionController::Base
48+ # deserializable_resource :article, only: [:create, :update]
49+ #
50+ # def create
51+ # article = Article.new(params[:article])
52+ #
53+ # if article.save
54+ # render jsonapi: article
55+ # else
56+ # render jsonapi_errors: article.errors
57+ # end
58+ # end
59+ #
60+ # # ...
61+ # end
62+ #
63+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
2964 def deserializable_resource ( key , options = { } , &block )
3065 options = options . dup
3166 klass = options . delete ( :class ) ||
3267 Class . new ( JSONAPI ::Rails ::Deserializable ::Resource , &block )
3368
3469 before_action ( options ) do |controller |
70+ # TODO(lucas): Fail with helpful error message if _jsonapi not
71+ # present.
3572 hash = controller . params [ :_jsonapi ] . to_unsafe_hash
36- ActiveSupport ::Notifications . instrument ( 'parse.jsonapi' ,
37- payload : hash ,
38- class : klass ) do
73+ ActiveSupport ::Notifications
74+ . instrument ( 'parse.jsonapi' , payload : hash , class : klass ) do
3975 JSONAPI ::Parser ::Resource . parse! ( hash )
4076 resource = klass . new ( hash [ :data ] )
4177 controller . request . env [ JSONAPI_POINTERS_KEY ] =
@@ -44,24 +80,46 @@ def deserializable_resource(key, options = {}, &block)
4480 end
4581 end
4682 end
83+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
4784 end
4885
86+ # Hook for serializable class mapping (for resources).
87+ # Overridden by the `class` renderer option.
88+ # @return [Hash{Symbol=>Class}]
89+ def jsonapi_class
90+ JSONAPI ::Rails . config [ :jsonapi_class ]
91+ end
92+
93+ # Hook for serializable class mapping (for errors).
94+ # Overridden by the `class` renderer option.
95+ # @return [Hash{Symbol=>Class}]
96+ def jsonapi_errors_class
97+ JSONAPI ::Rails . config [ :jsonapi_errors_class ]
98+ end
99+
100+ # Hook for the jsonapi object.
101+ # Overridden by the `jsonapi_object` renderer option.
102+ # @return [Hash]
49103 def jsonapi_object
50- nil
104+ JSONAPI :: Rails . config [ :jsonapi_object ]
51105 end
52106
107+ # Hook for default exposures.
108+ # @return [Hash]
53109 def jsonapi_expose
54- {
55- url_helpers : ::Rails . application . routes . url_helpers
56- }
110+ JSONAPI ::Rails . config [ :jsonapi_expose ]
57111 end
58112
59- def jsonapi_pagination ( _collection )
60- nil
113+ # Hook for pagination scheme.
114+ # @return [Hash]
115+ def jsonapi_pagination ( resources )
116+ instance_exec ( resources , &JSONAPI ::Rails . config [ :jsonapi_pagination ] )
61117 end
62118
119+ # JSON pointers for deserialized fields.
120+ # @return [Hash{Symbol=>String}]
63121 def jsonapi_pointers
64- request . env [ JSONAPI_POINTERS_KEY ]
122+ request . env [ JSONAPI_POINTERS_KEY ] || { }
65123 end
66124 end
67125 end
0 commit comments