Class: JSONAPI::Deserializer
- Inherits:
-
Object
- Object
- JSONAPI::Deserializer
show all
- Includes:
- ActiveStorageSupport
- Defined in:
- lib/json_api/serialization/deserializer.rb
Instance Method Summary
collapse
-
#apply_virtual_attribute_transformers(attrs) ⇒ Object
-
#attributes ⇒ Object
-
#call_setters(attrs, definition_instance) ⇒ Object
-
#create_definition_instance_for_setters ⇒ Object
-
#empty_array?(data) ⇒ Boolean
-
#extract_attributes_from_params ⇒ Object
-
#extract_data_from_value(value_hash) ⇒ Object
-
#extract_id_from_identifier(identifier) ⇒ Object
-
#extract_ids_from_data(data) ⇒ Object
-
#extract_relationship_data(relationship) ⇒ Object
-
#find_relationship(relationship_name) ⇒ Object
-
#handle_empty_array_relationship(attrs, param_name, association_name) ⇒ Object
-
#handle_null_relationship(attrs, param_name, association_name) ⇒ Object
-
#has_setter?(definition_instance, attr_sym) ⇒ Boolean
-
#initialize(params, model_class:, action: :create) ⇒ Deserializer
constructor
A new instance of Deserializer.
-
#invoke_setter_methods(attrs) ⇒ Object
-
#merge_transformed_params(attrs, transformed_params) ⇒ Object
-
#normalize_relationship_value(value) ⇒ Object
-
#permitted_attributes_for_action ⇒ Object
-
#process_non_polymorphic_relationship(attrs, association_name, param_name, id, type) ⇒ Object
-
#process_polymorphic_relationship(attrs, association_name, param_name, id, type) ⇒ Object
-
#process_regular_to_one_relationship(attrs, association_name, param_name, id, type) ⇒ Object
-
#process_relationship(attrs, association_name, value) ⇒ Object
-
#process_relationship_data(attrs, association_name, param_name, data) ⇒ Object
-
#process_relationships(attrs) ⇒ Object
-
#process_to_many_relationship(attrs, association_name, param_name, data) ⇒ Object
-
#process_to_one_relationship(attrs, association_name, param_name, data) ⇒ Object
-
#relationship_id(relationship_name) ⇒ Object
-
#relationship_ids(relationship_name) ⇒ Object
-
#relationships ⇒ Object
-
#to_model_attributes ⇒ Object
-
#validate_and_get_class_name(type, association_name) ⇒ Object
-
#validate_relationship_data_format!(data, association_name) ⇒ Object
#append_only_enabled?, #attach_active_storage_files, #extract_active_storage_params_from_hash, #filter_active_storage_from_includes, #filter_polymorphic_from_includes, #find_blob_by_signed_id, #process_active_storage_attachment, #purge_on_nil_enabled?, #serialize_active_storage_relationship, #serialize_blob_identifier
Constructor Details
#initialize(params, model_class:, action: :create) ⇒ Deserializer
Returns a new instance of Deserializer.
9
10
11
12
13
14
|
# File 'lib/json_api/serialization/deserializer.rb', line 9
def initialize(params, model_class:, action: :create)
@params = ParamHelpers.deep_symbolize_params(params)
@model_class = model_class
@definition = ResourceLoader.find_for_model(model_class)
@action = action.to_sym
end
|
Instance Method Details
84
85
86
87
88
89
|
# File 'lib/json_api/serialization/deserializer.rb', line 84
def apply_virtual_attribute_transformers(attrs)
transformed_params, attributes_with_setters = invoke_setter_methods(attrs)
attributes_with_setters.each { |attr_sym| attrs.delete(attr_sym) }
merge_transformed_params(attrs, transformed_params)
attrs
end
|
#attributes ⇒ Object
16
17
18
19
20
21
|
# File 'lib/json_api/serialization/deserializer.rb', line 16
def attributes
attrs =
attrs = attrs.transform_keys(&:to_sym) if attrs.respond_to?(:transform_keys)
permitted_attrs = permitted_attributes_for_action
attrs.slice(*permitted_attrs)
end
|
#call_setters(attrs, definition_instance) ⇒ Object
124
125
126
127
128
129
130
131
132
133
|
# File 'lib/json_api/serialization/deserializer.rb', line 124
def call_setters(attrs, definition_instance)
attributes_with_setters = []
attrs.each do |attr_sym, attr_value|
next unless has_setter?(definition_instance, attr_sym)
definition_instance.public_send(:"#{attr_sym}=", attr_value)
attributes_with_setters << attr_sym
end
attributes_with_setters
end
|
#create_definition_instance_for_setters ⇒ Object
120
121
122
|
# File 'lib/json_api/serialization/deserializer.rb', line 120
def create_definition_instance_for_setters
@definition.new(nil, {})
end
|
#empty_array?(data) ⇒ Boolean
161
162
163
|
# File 'lib/json_api/serialization/deserializer.rb', line 161
def empty_array?(data)
data.is_a?(Array) && data.empty?
end
|
23
24
25
|
# File 'lib/json_api/serialization/deserializer.rb', line 23
def
@params.dig(:data, :attributes) || @params[:attributes] || {}
end
|
157
158
159
|
# File 'lib/json_api/serialization/deserializer.rb', line 157
def (value_hash)
value_hash[:data]
end
|
69
70
71
|
# File 'lib/json_api/serialization/deserializer.rb', line 69
def (identifier)
RelationshipHelpers.(identifier)
end
|
61
62
63
64
65
66
67
|
# File 'lib/json_api/serialization/deserializer.rb', line 61
def (data)
if data.is_a?(Array)
data.map { |r| (r) }
else
[(data)]
end
end
|
57
58
59
|
# File 'lib/json_api/serialization/deserializer.rb', line 57
def (relationship)
relationship[:data]
end
|
#find_relationship(relationship_name) ⇒ Object
53
54
55
|
# File 'lib/json_api/serialization/deserializer.rb', line 53
def find_relationship(relationship_name)
relationships[relationship_name.to_sym]
end
|
#handle_empty_array_relationship(attrs, param_name, association_name) ⇒ Object
175
176
177
178
179
180
181
182
|
# File 'lib/json_api/serialization/deserializer.rb', line 175
def handle_empty_array_relationship(attrs, param_name, association_name)
if active_storage_attachment?(association_name)
attrs[association_name.to_s] = []
else
attrs["#{param_name.singularize}_ids"] = []
end
end
|
#handle_null_relationship(attrs, param_name, association_name) ⇒ Object
165
166
167
168
169
170
171
172
173
|
# File 'lib/json_api/serialization/deserializer.rb', line 165
def handle_null_relationship(attrs, param_name, association_name)
if active_storage_attachment?(association_name)
attrs[association_name.to_s] = nil
else
attrs["#{param_name}_id"] = nil
attrs["#{param_name}_type"] = nil if polymorphic_association?(association_name)
end
end
|
#has_setter?(definition_instance, attr_sym) ⇒ Boolean
135
136
137
|
# File 'lib/json_api/serialization/deserializer.rb', line 135
def has_setter?(definition_instance, attr_sym)
definition_instance.respond_to?(:"#{attr_sym}=", false)
end
|
#invoke_setter_methods(attrs) ⇒ Object
112
113
114
115
116
117
118
|
# File 'lib/json_api/serialization/deserializer.rb', line 112
def invoke_setter_methods(attrs)
definition_instance = create_definition_instance_for_setters
return [{}, []] unless definition_instance.respond_to?(:transformed_params, true)
attributes_with_setters = call_setters(attrs, definition_instance)
[definition_instance.transformed_params, attributes_with_setters]
end
|
91
92
93
94
95
96
97
|
# File 'lib/json_api/serialization/deserializer.rb', line 91
def merge_transformed_params(attrs, transformed_params)
return attrs unless transformed_params.is_a?(Hash) && transformed_params.any?
transformed_params_symbolized = transformed_params.transform_keys(&:to_sym)
attrs.merge!(transformed_params_symbolized)
attrs
end
|
#normalize_relationship_value(value) ⇒ Object
153
154
155
|
# File 'lib/json_api/serialization/deserializer.rb', line 153
def normalize_relationship_value(value)
value.is_a?(Hash) ? value : value.to_h
end
|
#permitted_attributes_for_action ⇒ Object
27
28
29
30
31
32
33
34
|
# File 'lib/json_api/serialization/deserializer.rb', line 27
def permitted_attributes_for_action
fields = if @action == :create
@definition.permitted_creatable_fields
else
@definition.permitted_updatable_fields
end
fields.map(&:to_sym)
end
|
#process_non_polymorphic_relationship(attrs, association_name, param_name, id, type) ⇒ Object
247
248
249
250
|
# File 'lib/json_api/serialization/deserializer.rb', line 247
def process_non_polymorphic_relationship(attrs, association_name, param_name, id, type)
validate_relationship_type(association_name, type)
attrs["#{param_name}_id"] = id
end
|
#process_polymorphic_relationship(attrs, association_name, param_name, id, type) ⇒ Object
231
232
233
234
235
|
# File 'lib/json_api/serialization/deserializer.rb', line 231
def process_polymorphic_relationship(attrs, association_name, param_name, id, type)
class_name = validate_and_get_class_name(type, association_name)
attrs["#{param_name}_id"] = id
attrs["#{param_name}_type"] = class_name
end
|
#process_regular_to_one_relationship(attrs, association_name, param_name, id, type) ⇒ Object
223
224
225
226
227
228
229
|
# File 'lib/json_api/serialization/deserializer.rb', line 223
def process_regular_to_one_relationship(attrs, association_name, param_name, id, type)
if polymorphic_association?(association_name)
process_polymorphic_relationship(attrs, association_name, param_name, id, type)
else
process_non_polymorphic_relationship(attrs, association_name, param_name, id, type)
end
end
|
#process_relationship(attrs, association_name, value) ⇒ Object
139
140
141
142
143
144
145
146
147
148
149
150
151
|
# File 'lib/json_api/serialization/deserializer.rb', line 139
def process_relationship(attrs, association_name, value)
value_hash = normalize_relationship_value(value)
data = (value_hash)
param_name = association_param_name(association_name)
ensure_relationship_writable!(association_name)
return handle_null_relationship(attrs, param_name, association_name) if data.nil?
return handle_empty_array_relationship(attrs, param_name, association_name) if empty_array?(data)
validate_relationship_data_format!(data, association_name)
process_relationship_data(attrs, association_name, param_name, data)
end
|
#process_relationship_data(attrs, association_name, param_name, data) ⇒ Object
190
191
192
193
194
195
196
|
# File 'lib/json_api/serialization/deserializer.rb', line 190
def process_relationship_data(attrs, association_name, param_name, data)
if data.is_a?(Array)
process_to_many_relationship(attrs, association_name, param_name, data)
else
process_to_one_relationship(attrs, association_name, param_name, data)
end
end
|
#process_relationships(attrs) ⇒ Object
99
100
101
102
103
104
105
106
107
108
109
110
|
# File 'lib/json_api/serialization/deserializer.rb', line 99
def process_relationships(attrs)
permitted_relationships = @definition.relationship_names.map(&:to_s)
relationships.each do |key, value|
association_name = key.to_s
next unless permitted_relationships.include?(association_name)
process_relationship(attrs, association_name, value)
end
attrs
end
|
#process_to_many_relationship(attrs, association_name, param_name, data) ⇒ Object
198
199
200
201
202
203
204
205
206
207
208
209
210
|
# File 'lib/json_api/serialization/deserializer.rb', line 198
def process_to_many_relationship(attrs, association_name, param_name, data)
ids = data.map { |r| (r) }
types = data.map { |r| (r) }
if types.any? && self.class.active_storage_blob_type?(types.first)
process_active_storage_attachment(attrs, association_name, ids, singular: false)
return
end
validate_relationship_type(association_name, types.first) unless polymorphic_association?(association_name)
attrs["#{param_name.singularize}_ids"] = ids
end
|
#process_to_one_relationship(attrs, association_name, param_name, data) ⇒ Object
212
213
214
215
216
217
218
219
220
221
|
# File 'lib/json_api/serialization/deserializer.rb', line 212
def process_to_one_relationship(attrs, association_name, param_name, data)
id = (data)
type = (data)
if self.class.active_storage_blob_type?(type)
return process_active_storage_attachment(attrs, association_name, id, singular: true)
end
process_regular_to_one_relationship(attrs, association_name, param_name, id, type)
end
|
#relationship_id(relationship_name) ⇒ Object
73
74
75
|
# File 'lib/json_api/serialization/deserializer.rb', line 73
def relationship_id(relationship_name)
relationship_ids(relationship_name).first
end
|
#relationship_ids(relationship_name) ⇒ Object
43
44
45
46
47
48
49
50
51
|
# File 'lib/json_api/serialization/deserializer.rb', line 43
def relationship_ids(relationship_name)
relationship = find_relationship(relationship_name)
return [] unless relationship
data = (relationship)
return [] unless data
(data)
end
|
#relationships ⇒ Object
36
37
38
39
40
41
|
# File 'lib/json_api/serialization/deserializer.rb', line 36
def relationships
rels = @params.dig(:data, :relationships) || @params[:relationships] || {}
rels = rels.to_h if rels.respond_to?(:to_h)
rels.is_a?(Hash) ? rels : {}
end
|
#to_model_attributes ⇒ Object
77
78
79
80
81
82
|
# File 'lib/json_api/serialization/deserializer.rb', line 77
def to_model_attributes
attrs = attributes.dup
attrs = apply_virtual_attribute_transformers(attrs)
attrs = process_relationships(attrs)
attrs.transform_keys(&:to_s)
end
|
#validate_and_get_class_name(type, association_name) ⇒ Object
237
238
239
240
241
242
243
244
245
|
# File 'lib/json_api/serialization/deserializer.rb', line 237
def validate_and_get_class_name(type, association_name)
class_name = RelationshipHelpers.type_to_class_name(type)
class_name.constantize
class_name
rescue NameError
raise ArgumentError,
"Invalid relationship type for #{association_name}: " \
"'#{type}' does not correspond to a valid model class"
end
|
184
185
186
187
188
|
# File 'lib/json_api/serialization/deserializer.rb', line 184
def validate_relationship_data_format!(data, association_name)
return if valid_relationship_data?(data)
raise ArgumentError, "Invalid relationship data for #{association_name}: missing type or id"
end
|