Module: Alba::Resource::InstanceMethods

Included in:
Alba::Resource
Defined in:
lib/alba/resource.rb,
sig/alba/resource.rbs

Overview

Instance methods

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#objectObject (readonly)

Returns the value of attribute object.

Returns:

  • (Object)


47
48
49
# File 'lib/alba/resource.rb', line 47

def object
  @object
end

#paramsgeneric_hash (readonly)

Returns the value of attribute params.

Returns:

  • (generic_hash)


47
48
49
# File 'lib/alba/resource.rb', line 47

def params
  @params
end

Instance Method Details

#__send__Object

Parameters:

  • (Symbol)
  • (Object)

Returns:

  • (Object)


62
# File 'sig/alba/resource.rbs', line 62

def __send__: (Symbol, *untyped) -> untyped

#_fetch_attribute_from_object_first(obj, attribute) ⇒ Object

Parameters:

  • (Object)
  • (Symbol)

Returns:

  • (Object)


309
310
311
312
313
314
315
# File 'lib/alba/resource.rb', line 309

def _fetch_attribute_from_object_first(obj, attribute)
  return obj.fetch(attribute) if obj.is_a?(Hash)

  obj.__send__(attribute)
rescue NoMethodError, KeyError
  __send__(attribute, obj)
end

#_fetch_attribute_from_resource_first(obj, attribute) ⇒ Object

Parameters:

  • (Object)
  • (Symbol)

Returns:

  • (Object)


317
318
319
320
321
322
323
324
325
326
327
# File 'lib/alba/resource.rb', line 317

def _fetch_attribute_from_resource_first(obj, attribute)
  return obj.fetch(attribute) if obj.is_a?(Hash)

  if @_resource_methods.include?(attribute)
    __send__(attribute, obj)
  else
    obj.__send__(attribute)
  end
rescue KeyError
  __send__(attribute, obj)
end

#_keyroot_key_type

Returns:

  • (root_key_type)


193
194
195
196
# File 'lib/alba/resource.rb', line 193

def _key
  k = @_key == true ? resource_name(pluralized: false) : @_key
  Alba.regularize_key(k)
end

#_key_for_collectionroot_key_type

Returns:

  • (root_key_type)


188
189
190
191
# File 'lib/alba/resource.rb', line 188

def _key_for_collection
  k = @_key_for_collection == true ? resource_name(pluralized: true) : @_key_for_collection
  Alba.regularize_key(k)
end

#_metadata(block, meta) ⇒ generic_hash

Parameters:

  • (Object)
  • (generic_hash)

Returns:

  • (generic_hash)


154
155
156
# File 'lib/alba/resource.rb', line 154

def (block, meta)
  block ? instance_eval(&block).merge(meta) : meta
end

#_setupvoid

This method returns an undefined value.



55
# File 'sig/alba/resource.rbs', line 55

def _setup: () -> void

#as_json(_options = EMPTY_HASH, root_key: nil, meta: EMPTY_HASH) ⇒ Hash

Returns a Hash corresponding #serialize

Parameters:

  • _options (Hash) (defaults to: EMPTY_HASH)

    dummy parameter for Rails compatibility

  • root_key (Symbol, nil) (defaults to: nil)
  • meta (Hash) (defaults to: EMPTY_HASH)

    metadata for this serialization

  • (generic_hash)
  • root_key: (root_key_type) (defaults to: nil)
  • meta: (generic_hash) (defaults to: EMPTY_HASH)

Returns:

  • (Hash)


96
97
98
99
100
101
102
103
104
105
# File 'lib/alba/resource.rb', line 96

def as_json(_options = EMPTY_HASH, root_key: nil, meta: EMPTY_HASH)
  key = root_key.nil? ? fetch_key : root_key
  key = Alba.regularize_key(key)
  if key && !key.empty?
    h = {key => serializable_hash}
    (h, meta)
  else
    serializable_hash
  end
end

#attributesHash[Symbol | String, attribute]

Deprecated.

in favor of select

This is default behavior for getting attributes for serialization Override this method to filter certain attributes

Returns:



243
244
245
# File 'lib/alba/resource.rb', line 243

def attributes
  @_attributes
end

#attributes_to_hash(obj, hash) ⇒ generic_hash

Parameters:

  • (Object)
  • (generic_hash)

Returns:

  • (generic_hash)


228
229
230
231
232
233
234
235
236
237
# File 'lib/alba/resource.rb', line 228

def attributes_to_hash(obj, hash)
  attributes.each do |key, attribute|
    set_key_and_attribute_body_from(obj, key, attribute, hash)
  rescue ::Alba::Error, FrozenError, TypeError
    raise
  rescue StandardError => e
    handle_error(e, obj, key, attribute, hash)
  end
  @with_traits.nil? ? hash : hash.merge!(hash_from_traits(obj))
end

#bindingBinding

Returns:

  • (Binding)


63
# File 'sig/alba/resource.rbs', line 63

def binding: () -> Binding

#check_within(association_name) ⇒ Object

Parameters:

  • (Symbol)

Returns:

  • (Object)


338
339
340
341
342
343
344
345
346
347
348
# File 'lib/alba/resource.rb', line 338

def check_within(association_name)
  case @within
  when WITHIN_DEFAULT then WITHIN_DEFAULT # Default value, doesn't check within tree
  when Hash then @within.fetch(association_name, nil) # Traverse within tree
  when Array then @within.find { |item| item.to_sym == association_name }
  when Symbol then @within == association_name
  when nil, true, false then false # Stop here
  else
    raise Alba::Error, "Unknown type for within option: #{@within.class}"
  end
end

#classClass

These methods are available on the eventual resource instance. Declaring them here models the module's inclusion context for Steep.

Returns:



59
# File 'sig/alba/resource.rbs', line 59

def class: () -> Class

#collection_converterProc

Returns:

  • (Proc)


219
220
221
222
223
224
225
226
# File 'lib/alba/resource.rb', line 219

def collection_converter
  lambda do |obj, a|
    a << {}
    h = a.last
    attributes_to_hash(obj, h)
    a
  end
end

#converterProc

Returns:

  • (Proc)


213
214
215
216
217
# File 'lib/alba/resource.rb', line 213

def converter
  lambda do |obj|
    attributes_to_hash(obj, {})
  end
end

#deprecated_serializable_hashObject

Returns:

  • (Object)


130
131
132
# File 'lib/alba/resource.rb', line 130

def deprecated_serializable_hash
  Alba.collection?(@object) ? serializable_hash_for_collection : converter.call(@object)
end

#deprecated_serializable_hash_for_collectionObject

Returns:

  • (Object)


170
171
172
173
174
175
176
177
178
179
180
# File 'lib/alba/resource.rb', line 170

def deprecated_serializable_hash_for_collection
  if @_collection_key
    @object.to_h do |item|
      k = item.public_send(@_collection_key)
      key = Alba.regularize_key(k)
      [key, converter.call(item)]
    end
  else
    @object.each_with_object([], &collection_converter)
  end
end

#do_select(key, value, attribute) ⇒ Boolean

Parameters:

  • (Object)
  • (Object)
  • (Object)

Returns:

  • (Boolean)


262
263
264
265
266
267
# File 'lib/alba/resource.rb', line 262

def do_select(key, value, attribute)
  # `select` can be overridden with both 2 and 3 parameters
  # Here we check the arity and build arguments accordingly
  args = @_select_arity == 3 ? [key, value, attribute] : [key, value]
  select(*args)
end

#encodeString

Parameters:

  • (Object)

Returns:

  • (String)


64
# File 'sig/alba/resource.rbs', line 64

def encode: (untyped) -> String

#fetch_attribute(obj, key, attribute) ⇒ Object

rubocop:disable Metrics

Parameters:

Returns:

  • (Object)


290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/alba/resource.rb', line 290

def fetch_attribute(obj, key, attribute) # rubocop:disable Metrics
  value = case attribute
          when Symbol then fetch_attribute_from_object_and_resource(obj, attribute)
          when Proc then instance_exec(obj, &attribute)
          when Alba::Association then yield_if_within(attribute.name.to_sym) { |within| attribute.to_h(obj, params: params, within: within) }
          when TypedAttribute then attribute.value(object: obj) { |attr| fetch_attribute(obj, key, attr) }
          when NestedAttribute then attribute.value(object: obj, params: params, within: @within)
          when ConditionalAttribute then attribute.with_passing_condition(resource: self, object: obj) { |attr| fetch_attribute(obj, key, attr) }
            # :nocov:
          else raise ::Alba::Error, "Unsupported type of attribute: #{attribute.class}"
            # :nocov:
          end
  value.nil? && nil_handler ? instance_exec(obj, key, attribute, &nil_handler) : value
end

#fetch_attribute_from_object_and_resource(obj, attribute) ⇒ Object

Parameters:

  • (Object)
  • (Symbol)

Returns:

  • (Object)


305
306
307
# File 'lib/alba/resource.rb', line 305

def fetch_attribute_from_object_and_resource(obj, attribute)
  _fetch_attribute_from_resource_first(obj, attribute)
end

#fetch_keyString

Returns:

  • (String)


183
184
185
186
# File 'lib/alba/resource.rb', line 183

def fetch_key
  k = Alba.collection?(@object) ? _key_for_collection : _key
  transforming_root_key? ? transform_key(k) : k
end

#handle_error(error, obj, key, attribute, hash) ⇒ Object

Parameters:

  • (StandardError)
  • (Object)
  • (Symbol, String)
  • (attribute)
  • (generic_hash)

Returns:

  • (Object)


269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/alba/resource.rb', line 269

def handle_error(error, obj, key, attribute, hash)
  case (on_error = @_on_error || :raise)
  when :raise, nil then raise(error)
  when :nullify then hash[key] = nil
  when :ignore then nil
  when Proc
    key, value = on_error.call(error, obj, key, attribute, self.class)
    hash[key] = value unless Alba::REMOVE_KEY == key # rubocop:disable Style/YodaCondition
  else
    # :nocov:
    raise Alba::Error, 'Impossible path'
    # :nocov:
  end
end

#hash_from_traits(obj) ⇒ Object

Parameters:

  • (Object)

Returns:

  • (Object)


117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/alba/resource.rb', line 117

def hash_from_traits(obj)
  return {} if @with_traits.nil?

  Array(@with_traits).each_with_object({}) do |trait, hash|
    body = @_traits.fetch(trait) { raise Alba::Error, "Trait not found: #{trait}" }
    resource_class = Class.new(self.class)
    resource_class.instance_variable_set(:@_attributes, {})
    resource_class.class_eval(&body)
    resource_class.transform_keys(@_transform_type) unless @_transform_type == :none
    hash.merge!(resource_class.new(obj, params: params, within: @within).serializable_hash)
  end
end

#hash_with_metadata(hash, meta) ⇒ Object

Parameters:

  • (Object)
  • (generic_hash)

Returns:

  • (Object)


141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/alba/resource.rb', line 141

def (hash, meta)
  return hash if meta.empty? && @_meta&.last.nil?

  key, block = @_meta || :meta

  if key
    hash[key] = (block, meta)
  else
    (block, meta).each { |k, v| hash[k] = v }
  end
  hash
end

#initialize(object, params: EMPTY_HASH, within: WITHIN_DEFAULT, with_traits: nil, select: nil) ⇒ InstanceMethods

Returns a new instance of InstanceMethods.

Parameters:

  • object (Object)

    the object to be serialized

  • params (Hash) (defaults to: EMPTY_HASH)

    user-given Hash for arbitrary data

  • within (Alba::WITHIN_DEFAULT, Hash, Array, nil, false, true) (defaults to: WITHIN_DEFAULT)

    determines what associations to be serialized. If not set, it serializes all associations.

  • with_traits (Symbol, Array<Symbol>, nil) (defaults to: nil)

    specified traits

  • select (Method) (defaults to: nil)

    DEPRECATED noop

  • (Object)
  • params: (generic_hash) (defaults to: EMPTY_HASH)
  • within: (Object) (defaults to: WITHIN_DEFAULT)
  • with_traits: (Symbol, Array[Symbol], nil) (defaults to: nil)
  • select: (Method, nil) (defaults to: nil)

Returns:



55
56
57
58
59
60
61
62
# File 'lib/alba/resource.rb', line 55

def initialize(object, params: EMPTY_HASH, within: WITHIN_DEFAULT, with_traits: nil, select: nil)
  @object = object
  @params = params
  @within = within
  @with_traits = with_traits
  warn '`select` keyword for Alba::Resource is deprecated', category: :deprecated, uplevel: 1 if select
  _setup
end

#instance_evalvoid

This method returns an undefined value.



60
# File 'sig/alba/resource.rbs', line 60

def instance_eval: [A] () { () [self: self] -> A } -> A

#instance_execvoid

This method returns an undefined value.



61
# File 'sig/alba/resource.rbs', line 61

def instance_exec: [A] (*untyped) { (*untyped) [self: self] -> A } -> A

#nil_handlerObject

Returns:

  • (Object)


329
330
331
# File 'lib/alba/resource.rb', line 329

def nil_handler
  @_on_nil
end

#resource_name(pluralized: false) ⇒ String

Parameters:

  • pluralized: (Boolean) (defaults to: false)

Returns:

  • (String)

Raises:



198
199
200
201
202
203
204
205
206
207
# File 'lib/alba/resource.rb', line 198

def resource_name(pluralized: false)
  inflector = Alba.inflector
  raise Alba::Error, 'You must set inflector when setting root key as true.' unless inflector

  class_name = self.class.name
  suffix = class_name.end_with?('Resource') ? 'Resource' : 'Serializer'
  name = inflector.demodulize(class_name).delete_suffix(suffix)
  underscore_name = inflector.underscore(name)
  pluralized ? inflector.pluralize(underscore_name) : underscore_name
end

#select(_key, _value, _attribute) ⇒ Boolean

Default implementation for selecting attributes Override this method to filter attributes based on key and value

Parameters:

  • (Object)
  • (Object)
  • (Object)

Returns:

  • (Boolean)


249
250
251
# File 'lib/alba/resource.rb', line 249

def select(_key, _value, _attribute)
  true
end

#serializable_hashHash Also known as: to_h

A Hash for serialization

Returns:

  • (Hash)


110
111
112
# File 'lib/alba/resource.rb', line 110

def serializable_hash
  Alba.collection?(@object) ? serializable_hash_for_collection : attributes_to_hash(@object, {})
end

#serializable_hash_for_collectionObject

Returns:

  • (Object)


158
159
160
161
162
163
164
165
166
167
168
# File 'lib/alba/resource.rb', line 158

def serializable_hash_for_collection
  if @_collection_key
    @object.to_h do |item|
      k = item.public_send(@_collection_key)
      key = Alba.regularize_key(k)
      [key, attributes_to_hash(item, {})]
    end
  else
    @object.map { |obj| attributes_to_hash(obj, {}) }
  end
end

#serialize(root_key: nil, meta: EMPTY_HASH) ⇒ String

Serialize object into JSON string

Parameters:

  • root_key (Symbol, nil) (defaults to: nil)
  • meta (Hash) (defaults to: EMPTY_HASH)

    metadata for this serialization

  • root_key: (root_key_type) (defaults to: nil)
  • meta: (generic_hash) (defaults to: EMPTY_HASH)

Returns:

  • (String)

    serialized JSON string



69
70
71
# File 'lib/alba/resource.rb', line 69

def serialize(root_key: nil, meta: EMPTY_HASH)
  serialize_with(as_json(root_key: root_key, meta: meta))
end

#serialize_with(hash) ⇒ String

Parameters:

  • (Object)

Returns:

  • (String)


134
135
136
137
138
139
# File 'lib/alba/resource.rb', line 134

def serialize_with(hash)
  serialized_json = encode(hash)
  return serialized_json unless @_layout

  @_layout.serialize(resource: self, serialized_json: serialized_json, binding: binding)
end

#set_key_and_attribute_body_from(obj, key, attribute, hash) ⇒ Object

Parameters:

  • (Object)
  • (Object)
  • (attribute)
  • (generic_hash)

Returns:

  • (Object)


253
254
255
256
257
258
259
260
# File 'lib/alba/resource.rb', line 253

def set_key_and_attribute_body_from(obj, key, attribute, hash)
  key = transform_key(key)
  value = fetch_attribute(obj, key, attribute)
  # When `select` is not overridden, skip calling it for better performance
  return if !@_select_arity.nil? && !do_select(key, value, attribute)

  hash[key] = value unless Alba::REMOVE_KEY == value # rubocop:disable Style/YodaCondition
end

#to_json(options = EMPTY_HASH, root_key: nil, meta: EMPTY_HASH) ⇒ String

For Rails compatibility The first options is a dummy parameter

Parameters:

  • (generic_hash)
  • root_key: (root_key_type) (defaults to: nil)
  • meta: (generic_hash) (defaults to: EMPTY_HASH)

Returns:

  • (String)

See Also:



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/alba/resource.rb', line 78

def to_json(options = EMPTY_HASH, root_key: nil, meta: EMPTY_HASH)
  confusing_keys = [:only, :except]
  confusing_options = options.keys.select { |k| confusing_keys.include?(k.to_sym) }
  unless confusing_options.empty?
    confusing_options.sort!
    confusing_options.map! { |s| "\"#{s}\"" }
    message = "You passed #{confusing_options.join(' and ')} options but ignored. Please refer to the document: https://github.com/okuramasafumi/alba/blob/main/docs/rails.md"
    Kernel.warn(message)
  end
  serialize(root_key: root_key, meta: meta)
end

#transform_key(key) ⇒ Object

Parameters:

  • (Object)

Returns:

  • (Object)


284
285
286
287
288
# File 'lib/alba/resource.rb', line 284

def transform_key(key)
  return Alba.regularize_key(key) if @_transform_type == :none || key.nil? || key.empty? # We can skip transformation

  Alba.transform_key(key, transform_type: @_transform_type)
end

#transforming_root_key?Boolean

Returns:

  • (Boolean)


209
210
211
# File 'lib/alba/resource.rb', line 209

def transforming_root_key?
  @_transforming_root_key
end

#yield_if_within(association_name) {|arg0| ... } ⇒ Object

Parameters:

  • (Symbol)

Yields:

Yield Parameters:

  • arg0 (Object)

Yield Returns:

  • (Object)

Returns:

  • (Object)


333
334
335
336
# File 'lib/alba/resource.rb', line 333

def yield_if_within(association_name)
  within = check_within(association_name)
  within ? yield(within) : Alba::REMOVE_KEY
end