Module: JSONAPI::Realizer::Resource

Extended by:
ActiveSupport::Concern
Includes:
ActiveModel::Model
Defined in:
lib/jsonapi/realizer/resource.rb,
lib/jsonapi/realizer/resource/relation.rb,
lib/jsonapi/realizer/resource/attribute.rb,
lib/jsonapi/realizer/resource/configuration.rb

Defined Under Namespace

Classes: Attribute, Configuration, Relation

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#contextObject



258
259
260
# File 'lib/jsonapi/realizer/resource.rb', line 258

def context
  self.class.const_get("Context").new(**@context || {})
end

#headersObject

Returns the value of attribute headers.



39
40
41
# File 'lib/jsonapi/realizer/resource.rb', line 39

def headers
  @headers
end

#intentObject



226
227
228
# File 'lib/jsonapi/realizer/resource.rb', line 226

def intent
  @intent.to_sym
end

#parametersObject

Returns the value of attribute parameters.



38
39
40
# File 'lib/jsonapi/realizer/resource.rb', line 38

def parameters
  @parameters
end

#scope=(value) ⇒ Object

Sets the attribute scope

Parameters:

  • value

    the value to set the attribute scope to.



41
42
43
# File 'lib/jsonapi/realizer/resource.rb', line 41

def scope=(value)
  @scope = value
end

Instance Method Details

#attributesObject



192
193
194
195
196
197
198
199
# File 'lib/jsonapi/realizer/resource.rb', line 192

def attributes
  return unless data.key?("attributes")

  @attributes ||= data.
    fetch("attributes").
    transform_keys(&:underscore).
    transform_keys{|key| attribute(key).as}
end

#filtering?Boolean

Returns:

  • (Boolean)


116
117
118
# File 'lib/jsonapi/realizer/resource.rb', line 116

def filtering?
  parameters.key?("filter")
end

#filtersObject



120
121
122
123
124
125
126
127
# File 'lib/jsonapi/realizer/resource.rb', line 120

def filters
  @filters ||= parameters.
    # {"filter" => {"full-name" => "Abby Marquardt", "email" => "[email protected]"}}
    fetch("filter").
    # {"full-name" => "Abby Marquardt", "email" => "[email protected]"}
    transform_keys(&:underscore)
    # {"full_name" => "Abby Marquardt", "email" => "[email protected]"}
end

#include?Boolean

Returns:

  • (Boolean)


129
130
131
# File 'lib/jsonapi/realizer/resource.rb', line 129

def include?
  parameters.key?("include")
end

#includesObject



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/jsonapi/realizer/resource.rb', line 133

def includes
  @includes ||= parameters.
    # {"include" => "active-photographer.photographs,comments,comments.author"}
    fetch("include").
    # "active-photographer.photographs,comments,comments.author"
    split(/\s*,\s*/).
    # ["active-photographer.photographs", "comments", "comments.author"]
    map {|chain| chain.split(".")}.
    # [["active-photographer", "photographs"], ["comments"], ["comments", "author"]]
    map {|list| list.map(&:underscore)}.
    # [["active_photographer", "photographs"], ["comments"], ["comments", "author"]]
    map do |relationship_chain|
      # This walks down the path of relationships and normalizes thenm to
      # their defined "as", which lets us expose AccountRealizer#name, but that actually
      # references Account#full_name.
      relationship_chain.reduce([[], self.class]) do |(normalized_relationship_chain, realizer_class), relationship_link|
        [
          [
            *normalized_relationship_chain,
            realizer_class.relation(relationship_link).as
          ],
          realizer_class.relation(relationship_link).realizer_class
        ]
      end.first
    end
    # [["account", "photographs"], ["comments"], ["comments", "account"]]
end

#initialize(**keyword_arguments) ⇒ Object



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
# File 'lib/jsonapi/realizer/resource.rb', line 43

def initialize(**keyword_arguments)
  super(**keyword_arguments)

  context.validate!
  validate!

  if filtering?
    @scope = adapter.filtering(scope, filters)
  end

  if include?
    @scope = adapter.include_relationships(scope, includes)
  end

  if sorting?
    @scope = adapter.sorting(scope, sorts)
  end

  if paginate?
    @scope = adapter.paginate(scope, *pagination)
  end

  if writing? && data?
    adapter.write_attributes(object, attributes)
    adapter.write_relationships(object, relationships)
  end
end

#objectObject



215
216
217
218
219
220
221
222
223
224
# File 'lib/jsonapi/realizer/resource.rb', line 215

def object
  @object ||= case intent
  when :create
    scope.new
  when :show, :update, :destroy
    adapter.find_one(scope, parameters.fetch("id"))
  else
    scope
  end
end

#paginate?Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/jsonapi/realizer/resource.rb', line 84

def paginate?
  parameters.key?("page") && (parameters.fetch("page").key?("limit") || parameters.fetch("page").key?("offset"))
end

#paginationObject



88
89
90
91
92
93
# File 'lib/jsonapi/realizer/resource.rb', line 88

def pagination
  [
    parameters.fetch("page").fetch("limit", nil),
    parameters.fetch("page").fetch("offset", nil)
  ]
end

#relationshipsObject



201
202
203
204
205
206
207
208
209
# File 'lib/jsonapi/realizer/resource.rb', line 201

def relationships
  return unless data.key?("relationships")

  @relationships ||= data.
    fetch("relationships").
    transform_keys(&:underscore).
    map(&method(:as_relationship)).to_h.
    transform_keys{|key| relation(key).as}
end

#selectsObject



165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/jsonapi/realizer/resource.rb', line 165

def selects
  @selects ||= parameters.
    # {"fields" => {"articles" => "title,body,sub-text", "people" => "name"}}
    fetch("fields").
    # {"articles" => "title,body,sub-text", "people" => "name"}
    transform_keys(&:underscore).
    # {"articles" => "title,body,sub-text", "people" => "name"}
    transform_values {|value| value.split(/\s*,\s*/)}.
    # {"articles" => ["title", "body", "sub-text"], "people" => ["name"]}
    transform_values {|value| value.map(&:underscore)}
    # {"articles" => ["title", "body", "sub_text"], "people" => ["name"]}
end

#selects?Boolean

Returns:

  • (Boolean)


161
162
163
# File 'lib/jsonapi/realizer/resource.rb', line 161

def selects?
  parameters.key?("fields")
end

#sorting?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/jsonapi/realizer/resource.rb', line 95

def sorting?
  parameters.key?("sort")
end

#sortsObject



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/jsonapi/realizer/resource.rb', line 99

def sorts
  @sorts ||= parameters.
    # {sort: "name,-age,accounts.created_at,-accounts.updated_at"}
    fetch("sort").
    # "name,-age,accounts.created_at,-accounts.updated_at"
    split(",").
    # ["name", "-age", "accounts.created_at", "-accounts.updated_at"]
    map do |token|
      if token.start_with?("-") then [token.sub(/^-/, "").underscore, "-"] else [token.underscore, "+"] end
    end.
    # [["name", "+"], ["age", "-"], ["accounts.created_at", "+"], ["accounts.updated_at", "-"]]
    map do |(path, direction)|
      [if path.include?(".") then path.split(".") else [self.class.configuration.type, path] end, direction]
    end
    # [[["accounts", "name"], "+"], [["accounts", "age"], "-"], [["accounts", "created_at"], "+"], [["accounts", "updated_at"], "-"]]
end

#to_hashObject



71
72
73
74
75
76
77
78
# File 'lib/jsonapi/realizer/resource.rb', line 71

def to_hash
  @native ||= {
    :pagination => if paginate? then pagination end,
    :selects => if selects? then selects end,
    :includes => if include? then includes end,
    :object => object
  }.compact
end