|
1 |
| -require 'jsonapi/deserializable' |
2 |
| -require 'jsonapi/parser' |
3 |
| -require 'jsonapi/rails/configuration' |
| 1 | +require 'jsonapi/rails/controller/deserialization' |
| 2 | +require 'jsonapi/rails/controller/hooks' |
4 | 3 |
|
5 | 4 | module JSONAPI
|
6 | 5 | module Rails
|
7 |
| - module Deserializable |
8 |
| - # @private |
9 |
| - class Resource < JSONAPI::Deserializable::Resource |
10 |
| - id |
11 |
| - type |
12 |
| - attributes |
13 |
| - has_one do |_rel, id, type, key| |
14 |
| - type = type.to_s.singularize.camelize |
15 |
| - { "#{key}_id".to_sym => id, "#{key}_type".to_sym => type } |
16 |
| - end |
17 |
| - has_many do |_rel, ids, types, key| |
18 |
| - key = key.to_s.singularize |
19 |
| - types = types.map { |t| t.to_s.singularize.camelize } |
20 |
| - { "#{key}_ids".to_sym => ids, "#{key}_types".to_sym => types } |
21 |
| - end |
22 |
| - end |
23 |
| - end |
24 |
| - |
25 | 6 | # ActionController methods and hooks for JSON API deserialization and
|
26 | 7 | # rendering.
|
27 | 8 | module Controller
|
28 |
| - extend ActiveSupport::Concern |
29 |
| - |
30 |
| - JSONAPI_POINTERS_KEY = 'jsonapi-rails.jsonapi_pointers'.freeze |
31 |
| - |
32 |
| - 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 |
64 |
| - def deserializable_resource(key, options = {}, &block) |
65 |
| - options = options.dup |
66 |
| - klass = options.delete(:class) || |
67 |
| - Class.new(JSONAPI::Rails::Deserializable::Resource, &block) |
68 |
| - |
69 |
| - before_action(options) do |controller| |
70 |
| - hash = controller.params.to_unsafe_hash[:_jsonapi] |
71 |
| - if hash.nil? |
72 |
| - JSONAPI::Rails.config[:logger].warn do |
73 |
| - "Unable to deserialize #{key} because no JSON API payload was" \ |
74 |
| - " found. (#{controller.controller_name}##{params[:action]})" |
75 |
| - end |
76 |
| - next |
77 |
| - end |
78 |
| - |
79 |
| - ActiveSupport::Notifications |
80 |
| - .instrument('parse.jsonapi-rails', |
81 |
| - key: key, payload: hash, class: klass) do |
82 |
| - JSONAPI::Parser::Resource.parse!(hash) |
83 |
| - resource = klass.new(hash[:data]) |
84 |
| - controller.request.env[JSONAPI_POINTERS_KEY] = |
85 |
| - resource.reverse_mapping |
86 |
| - controller.params[key.to_sym] = resource.to_hash |
87 |
| - end |
88 |
| - end |
89 |
| - end |
90 |
| - # rubocop:enable Metrics/MethodLength, Metrics/AbcSize |
91 |
| - end |
92 |
| - |
93 |
| - # Hook for serializable class mapping (for resources). |
94 |
| - # Overridden by the `class` renderer option. |
95 |
| - # @return [Hash{Symbol=>Class}] |
96 |
| - def jsonapi_class |
97 |
| - JSONAPI::Rails.config[:jsonapi_class].dup |
98 |
| - end |
99 |
| - |
100 |
| - # Hook for serializable class mapping (for errors). |
101 |
| - # Overridden by the `class` renderer option. |
102 |
| - # @return [Hash{Symbol=>Class}] |
103 |
| - def jsonapi_errors_class |
104 |
| - JSONAPI::Rails.config[:jsonapi_errors_class].dup |
105 |
| - end |
106 |
| - |
107 |
| - # Hook for the jsonapi object. |
108 |
| - # Overridden by the `jsonapi_object` renderer option. |
109 |
| - # @return [Hash,nil] |
110 |
| - def jsonapi_object |
111 |
| - JSONAPI::Rails.config[:jsonapi_object] |
112 |
| - end |
113 |
| - |
114 |
| - # Hook for default exposures. |
115 |
| - # @return [Hash] |
116 |
| - def jsonapi_expose |
117 |
| - instance_exec(&JSONAPI::Rails.config[:jsonapi_expose]) |
118 |
| - end |
119 |
| - |
120 |
| - # Hook for default cache. |
121 |
| - # @return [#fetch_multi] |
122 |
| - def jsonapi_cache |
123 |
| - instance_exec(&JSONAPI::Rails.config[:jsonapi_cache]) |
124 |
| - end |
125 |
| - |
126 |
| - # Hook for default fields. |
127 |
| - # @return [Hash{Symbol=>Array<Symbol>},nil] |
128 |
| - def jsonapi_fields |
129 |
| - instance_exec(&JSONAPI::Rails.config[:jsonapi_fields]) |
130 |
| - end |
131 |
| - |
132 |
| - # Hook for default includes. |
133 |
| - # @return [IncludeDirective] |
134 |
| - def jsonapi_include |
135 |
| - instance_exec(&JSONAPI::Rails.config[:jsonapi_include]) |
136 |
| - end |
137 |
| - |
138 |
| - # Hook for default links. |
139 |
| - # @return [Hash] |
140 |
| - def jsonapi_links |
141 |
| - instance_exec(&JSONAPI::Rails.config[:jsonapi_links]) |
142 |
| - end |
143 |
| - |
144 |
| - # Hook for default meta. |
145 |
| - # @return [Hash,nil] |
146 |
| - def jsonapi_meta |
147 |
| - instance_exec(&JSONAPI::Rails.config[:jsonapi_meta]) |
148 |
| - end |
149 |
| - |
150 |
| - # Hook for pagination scheme. |
151 |
| - # @return [Hash] |
152 |
| - def jsonapi_pagination(resources) |
153 |
| - instance_exec(resources, &JSONAPI::Rails.config[:jsonapi_pagination]) |
154 |
| - end |
155 |
| - |
156 |
| - # JSON pointers for deserialized fields. |
157 |
| - # @return [Hash{Symbol=>String}] |
158 |
| - def jsonapi_pointers |
159 |
| - request.env[JSONAPI_POINTERS_KEY] || {} |
160 |
| - end |
| 9 | + include Deserialization |
| 10 | + include Hooks |
161 | 11 | end
|
162 | 12 | end
|
163 | 13 | end
|
0 commit comments