Class: Railsful::Deserializer

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

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

#paramsObject (readonly)

Returns the value of attribute params.



10
11
12
# File 'lib/railsful/deserializer.rb', line 10

def params
  @params
end

Instance Method Details

#belongs_to_relationship(type, data) ⇒ Object

rubocop:enable Naming/PredicateName



88
89
90
91
92
93
94
95
96
97
# File 'lib/railsful/deserializer.rb', line 88

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

#deserializeObject

Deserializes the given params.

:reek:FeatureEnvy



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/railsful/deserializer.rb', line 19

def deserialize
  deserialized = {}

  data = params.fetch(:data, {})

  # Merge the resources attributes
  deserialized.merge!(data.fetch(:attributes, {}))

  # Get the already existing relationships
  data.fetch(:relationships, {}).each do |type, payload|
    deserialized.merge!(relationship(type, payload))
  end

  # Get the included elements.
  deserialized.deeper_merge!(included_hash(params))

  # Return the deserialized params.
  ActionController::Parameters.new(deserialized)
end

#has_many_relationship(type, data) ⇒ Object

rubocop:disable Naming/PredicateName



77
78
79
80
81
82
83
84
85
# File 'lib/railsful/deserializer.rb', line 77

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) ⇒ Object

Fetches all included associations/relationships from the included hash.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/railsful/deserializer.rb', line 41

def included_hash(params)
  included_hash = {}

  params.fetch(:included, []).each do |inc|
    type = inc[:type].to_sym
    attrs = inc[:attributes]

    if params.dig(:data, :relationships, type, :data).is_a?(Array)
      # We pluralize the type since we are dealing with a
      # +has_many+ relationship.
      plural = ActiveSupport::Inflector.pluralize(type)

      included_hash["#{plural}_attributes"] ||= []
      included_hash["#{plural}_attributes"] << attrs
    else
      # When the data value is not an Array we are assuming that we
      # deal with a +has_one+ association. To be on the safe side we also
      # call singularize on the type.
      singular = ActiveSupport::Inflector.singularize(type)

      included_hash["#{singular}_attributes"] = attrs
    end
  end

  included_hash
end

#relationship(type, payload) ⇒ Object



68
69
70
71
72
73
74
# File 'lib/railsful/deserializer.rb', line 68

def relationship(type, payload)
  data = payload[:data]

  return has_many_relationship(type, data) if data.is_a?(Array)

  belongs_to_relationship(type, data)
end