Module: Graphiti::SerializableHash

Included in:
Serializer
Defined in:
lib/graphiti/hash_renderer.rb

Instance Method Summary collapse

Instance Method Details

#polymorphic_subclass?Boolean

Returns:

  • (Boolean)


121
122
123
124
125
# File 'lib/graphiti/hash_renderer.rb', line 121

def polymorphic_subclass?
  !remote_resource? &&
    @resource.polymorphic? &&
    @resource.type != jsonapi_type
end

#remote_resource?Boolean

See hack in util/remote_serializer.rb

Returns:

  • (Boolean)


128
129
130
# File 'lib/graphiti/hash_renderer.rb', line 128

def remote_resource?
  @resource == 1
end

#to_hash(fields: nil, include: {}, name_chain: [], graphql: false) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/graphiti/hash_renderer.rb', line 3

def to_hash(fields: nil, include: {}, name_chain: [], graphql: false)
  {}.tap do |hash|
    if fields
      fields_list = nil

      # Dot syntax wins over jsonapi type
      if name_chain.length > 0
        fields_list = fields[name_chain.join(".").to_sym]
      end

      if fields_list.nil?
        fields_list = fields[jsonapi_type]
      end
    end

    # polymorphic resources - merge the PARENT type
    if polymorphic_subclass?
      if fields[@resource.type]
        fields_list ||= []
        fields_list |= fields[@resource.type]
      end

      if fields[jsonapi_type]
        fields_list ||= []
        fields_list |= fields[jsonapi_type]
      end
    end

    attrs = requested_attributes(fields_list).each_with_object({}) { |(k, v), h|
      name = graphql ? k.to_s.camelize(:lower).to_sym : k
      h[name] = instance_eval(&v)
    }

    # The main logic here is just !!include[k]
    # But we also have special on__<type>--<name> includes
    # Where we only include when matching the polymorphic type
    rels = @_relationships.select { |k, v|
      if include[k]
        true
      else
        included = false
        include.keys.each do |key|
          split = key.to_s.split(/^on__/)
          if split.length > 1
            requested_type, key = split[1].split("--")
            if requested_type.to_sym == jsonapi_type
              included = k == key.to_sym
              break
            end
          end
        end
        included
      end
    }

    rels.each_with_object({}) do |(k, v), h|
      nested_include = include[k]

      # This logic only fires if it's a special on__<type>--<name> include
      unless include.has_key?(k)
        include.keys.each do |include_key|
          if k == include_key.to_s.split("--")[1].to_sym
            nested_include = include[include_key]
            break
          end
        end
      end

      serializers = v.send(:resources)
      name = graphql ? k.to_s.camelize(:lower) : k
      name_chain = name_chain.dup
      name_chain << k unless name_chain.last == k

      unless remote_resource? && serializers.nil?
        payload = if serializers.is_a?(Array)
          data = serializers.map { |rr|
            rr.to_hash(fields: fields, include: nested_include, graphql: graphql, name_chain: name_chain)
          }
          graphql ? {nodes: data} : data
        elsif serializers.nil?
          if @resource.class.respond_to?(:sideload)
            if @resource.class.sideload(k).type.to_s.include?("_many")
              graphql ? {nodes: []} : []
            end
          end
        else
          serializers.to_hash(fields: fields, include: nested_include, graphql: graphql, name_chain: name_chain)
        end

        attrs[name.to_sym] = payload
      end
    end

    if !graphql || (fields_list || []).include?(:id)
      hash[:id] = jsonapi_id
    end

    if (fields_list || []).include?(:_type)
      hash[:_type] = jsonapi_type.to_s
    end

    if (fields_list || []).include?(:_cursor)
      hash[:_cursor] = cursor
    end

    if (fields_list || []).include?(:__typename)
      resource_class = @resource.class
      if polymorphic_subclass?
        resource_class = @resource.class.resource_for_type(jsonapi_type)
      end
      hash[:__typename] = ::Graphiti::Util::Class
        .graphql_type_name(resource_class.name)
    end

    hash.merge!(attrs) if attrs.any?
  end
end