Class: Railsful::Deserializer
- Inherits:
-
Object
- Object
- Railsful::Deserializer
- Defined in:
- lib/railsful/deserializer.rb
Overview
The deserializer class handles the “unwrapping” of incoming parameters. It translates jsonapi compliant params to those that Rails understands.
Instance Attribute Summary collapse
-
#params ⇒ Object
readonly
Returns the value of attribute params.
Instance Method Summary collapse
-
#attributes(params) ⇒ Hash
First level attributes from data object.
-
#belongs_to_relationship(type, data) ⇒ Object
rubocop:enable Naming/PredicateName.
-
#deserialize ⇒ Object
Deserializes the given params.
-
#get_included(relation, included) ⇒ Hash, NilClass
Fetch the included object for a given relationship.
-
#has_many_relationship(type, data) ⇒ Object
rubocop:disable Naming/PredicateName.
-
#included_hash(params) ⇒ Hash
Fetches all included associations/relationships from the included hash.
-
#initialize(params) ⇒ Deserializer
constructor
A new instance of Deserializer.
- #relationship(type, payload) ⇒ Object
Constructor Details
#initialize(params) ⇒ Deserializer
Returns a new instance of Deserializer.
12 13 14 |
# File 'lib/railsful/deserializer.rb', line 12 def initialize(params) @params = params end |
Instance Attribute Details
#params ⇒ Object (readonly)
Returns the value of attribute params.
10 11 12 |
# File 'lib/railsful/deserializer.rb', line 10 def params @params end |
Instance Method Details
#attributes(params) ⇒ Hash
First level attributes from data object.
:reek:FeatureEnvy
35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/railsful/deserializer.rb', line 35 def attributes(params) data = params.fetch(:data, {}) # Merge the resources attributes. Also merge the id since jsonapi does # not allow ids in the attribute body. attrs = data.fetch(:attributes, {}).merge(id: data[:id]) # Get the already existing relationships data.fetch(:relationships, {}).each do |type, payload| attrs.merge!(relationship(type, payload)) end attrs.compact end |
#belongs_to_relationship(type, data) ⇒ Object
rubocop:enable Naming/PredicateName
131 132 133 134 135 136 137 138 139 140 |
# File 'lib/railsful/deserializer.rb', line 131 def belongs_to_relationship(type, data) # Fetch a possible id from the data. relation_id = data[:id] # If no ID is provided skip it. return {} unless relation_id # Build the relationship hash. { :"#{type}_id" => relation_id } end |
#deserialize ⇒ Object
Deserializes the given params.
:reek:FeatureEnvy
19 20 21 22 23 24 25 26 27 28 |
# File 'lib/railsful/deserializer.rb', line 19 def deserialize # Fetch attributes including resource id. deserialized = attributes(params) # Get the included elements. deserialized.deeper_merge!(included_hash(params)) # Return the deserialized params. ActionController::Parameters.new(deserialized) end |
#get_included(relation, included) ⇒ Hash, NilClass
Fetch the included object for a given relationship.
:reek:UtilityFunction
98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/railsful/deserializer.rb', line 98 def get_included(relation, included) # Return the attributes of the last found element. But there SHOULD only # be one element with the same tempid. If there is a mistake by the client # we always take the last. found = included.reverse .detect { |inc| inc[:tempid] == relation[:tempid] } return nil unless found # Return the attributes of the found include hash or an empty hash. found.fetch(:attributes, {}) end |
#has_many_relationship(type, data) ⇒ Object
rubocop:disable Naming/PredicateName
120 121 122 123 124 125 126 127 128 |
# File 'lib/railsful/deserializer.rb', line 120 def has_many_relationship(type, data) return {} unless data.is_a?(Array) ids = data.map { |relation| relation[:id] }.compact return {} if ids.empty? { :"#{type}_ids" => ids } end |
#included_hash(params) ⇒ Hash
Fetches all included associations/relationships from the included hash.
:reek:UtilityFunction :reek:FeatureEnvy
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/railsful/deserializer.rb', line 57 def included_hash(params) # Gather all necessary data we are working on. included = params.fetch(:included, []) relationships = params.fetch(:data, {}).fetch(:relationships, {}) result = {} # Make sure that both +included+ and +relationships+ are given. # Otherwise we can't do anything and return an empty hash. return result if included.empty? || relationships.empty? # Iterate over all relationships. relationships.each do |type, payload| # Get the data value. data = payload[:data] # Check if we are dealing with a +has_many+ (Array) or +belongs_to+ # (Hash) relationship. if data.is_a?(Array) result["#{type}_attributes"] = [] data.each do |element| result["#{type}_attributes"] << get_included(element, included) end # Remove all nil includes. result["#{type}_attributes"].compact! else result["#{type}_attributes"] = get_included(data, included) end end # Remove all nil includes. result.compact end |
#relationship(type, payload) ⇒ Object
111 112 113 114 115 116 117 |
# File 'lib/railsful/deserializer.rb', line 111 def relationship(type, payload) data = payload[:data] return has_many_relationship(type, data) if data.is_a?(Array) belongs_to_relationship(type, data) end |