Module: T::Props::Serializable::DecoratorMethods

Includes:
HasLazilySpecializedMethods::DecoratorMethods
Defined in:
lib/types/props/serializable.rb

Overview

NB: This must stay in the same file where T::Props::Serializable is defined due to T::Props::Decorator#apply_plugin; see git.corp.stripe.com/stripe-internal/pay-server/blob/fc7f15593b49875f2d0499ffecfd19798bac05b3/chalk/odm/lib/chalk-odm/document_decorator.rb#L716-L717

Instance Method Summary collapse

Methods included from HasLazilySpecializedMethods::DecoratorMethods

#eagerly_define_lazy_methods!, #eagerly_define_lazy_vm_methods!

Methods included from Sig

#sig

Instance Method Details

#add_prop_definition(prop, rules) ⇒ Object



225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/types/props/serializable.rb', line 225

def add_prop_definition(prop, rules)
  serialized_form = rules.fetch(:name, prop.to_s)
  rules[:serialized_form] = serialized_form
  res = super
  prop_by_serialized_forms[serialized_form] = prop
  if T::Configuration.use_vm_prop_serde?
    enqueue_lazy_vm_method_definition!(:__t_props_generated_serialize) {generate_serialize2}
    enqueue_lazy_vm_method_definition!(:__t_props_generated_deserialize) {generate_deserialize2}
  else
    enqueue_lazy_method_definition!(:__t_props_generated_serialize) {generate_serialize_source}
    enqueue_lazy_method_definition!(:__t_props_generated_deserialize) {generate_deserialize_source}
  end
  res
end

#extra_props(instance) ⇒ Object



334
335
336
337
338
339
340
# File 'lib/types/props/serializable.rb', line 334

def extra_props(instance)
  if instance.instance_variable_defined?(:@_extra_props)
    instance.instance_variable_get(:@_extra_props) || EMPTY_EXTRA_PROPS
  else
    EMPTY_EXTRA_PROPS
  end
end

#from_hash(hash, strict = false) ⇒ Object

Raises:

  • (ArgumentError)


208
209
210
211
212
213
214
215
# File 'lib/types/props/serializable.rb', line 208

def from_hash(hash, strict=false)
  raise ArgumentError.new("#{hash.inspect} provided to from_hash") if !(hash && hash.is_a?(Hash))

  i = @class.allocate
  i.deserialize(hash, strict)

  i
end

#get_id(instance) ⇒ Object



322
323
324
325
326
327
328
329
# File 'lib/types/props/serializable.rb', line 322

def get_id(instance)
  prop = prop_by_serialized_forms['_id']
  if prop
    get(instance, prop)
  else
    nil
  end
end

#message_with_generated_source_context(error, generated_method, generate_source_method) ⇒ Object



263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/types/props/serializable.rb', line 263

def message_with_generated_source_context(error, generated_method, generate_source_method)
  line_label = error.backtrace.find {|l| l.end_with?("in `#{generated_method}'")}
  return unless line_label

  line_num = line_label.split(':')[1]&.to_i
  return unless line_num

  source_lines = self.send(generate_source_method).split("\n")
  previous_blank = source_lines[0...line_num].rindex(&:empty?) || 0
  next_blank = line_num + (source_lines[line_num..-1]&.find_index(&:empty?) || 0)
  context = "  #{source_lines[(previous_blank + 1)...next_blank].join("\n  ")}"
  <<~MSG
    Error in #{decorated_class.name}##{generated_method}: #{error.message}
    at line #{line_num - previous_blank - 1} in:
    #{context}
  MSG
end

#pretty_print_extra(instance, pp) ⇒ Object

adds to the default result of T::Props::PrettyPrintable



343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
# File 'lib/types/props/serializable.rb', line 343

def pretty_print_extra(instance, pp)
  # This is to maintain backwards compatibility with Stripe's codebase, where only the single line (through `inspect`)
  # version is expected to add anything extra
  return if !pp.is_a?(PP::SingleLine)
  if (extra_props = extra_props(instance)) && !extra_props.empty?
    pp.breakable
    pp.text("@_extra_props=")
    pp.group(1, "<", ">") do
      extra_props.each_with_index do |(prop, value), i|
        pp.breakable unless i.zero?
        pp.text("#{prop}=")
        value.pretty_print(pp)
      end
    end
  end
end

#prop_by_serialized_formsObject



204
205
206
# File 'lib/types/props/serializable.rb', line 204

def prop_by_serialized_forms
  @class.prop_by_serialized_forms
end

#prop_dont_store?(prop) ⇒ Boolean

Returns:



201
202
203
# File 'lib/types/props/serializable.rb', line 201

def prop_dont_store?(prop)
  prop_rules(prop)[:dont_store]
end

#prop_serialized_form(prop) ⇒ Object



217
218
219
# File 'lib/types/props/serializable.rb', line 217

def prop_serialized_form(prop)
  prop_rules(prop)[:serialized_form]
end

#prop_validate_definition!(name, cls, rules, type) ⇒ Object



304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/types/props/serializable.rb', line 304

def prop_validate_definition!(name, cls, rules, type)
  result = super

  if (rules_name = rules[:name])
    unless rules_name.is_a?(String)
      raise ArgumentError.new("Invalid name in prop #{@class.name}.#{name}: #{rules_name.inspect}")
    end

    validate_prop_name(rules_name)
  end

  if !rules[:raise_on_nil_write].nil? && rules[:raise_on_nil_write] != true
    raise ArgumentError.new("The value of `raise_on_nil_write` if specified must be `true` (given: #{rules[:raise_on_nil_write]}).")
  end

  result
end

#raise_nil_deserialize_error(hkey) ⇒ Object



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
# File 'lib/types/props/serializable.rb', line 281

def raise_nil_deserialize_error(hkey)
  msg = "Tried to deserialize a required prop from a nil value. It's "\
    "possible that a nil value exists in the database, so you should "\
    "provide a `default: or factory:` for this prop (see go/optional "\
    "for more details). If this is already the case, you probably "\
    "omitted a required prop from the `fields:` option when doing a "\
    "partial load."
  storytime = {prop: hkey, klass: decorated_class.name}

  # Notify the model owner if it exists, and always notify the API owner.
  begin
    if T::Configuration.class_owner_finder && (owner = T::Configuration.class_owner_finder.call(decorated_class))
      T::Configuration.hard_assert_handler(
        msg,
        storytime: storytime,
        project: owner
      )
    end
  ensure
    T::Configuration.hard_assert_handler(msg, storytime: storytime)
  end
end

#required_propsObject



197
198
199
# File 'lib/types/props/serializable.rb', line 197

def required_props
  @class.props.select {|_, v| T::Props::Utils.required_prop?(v)}.keys
end

#serialized_form_prop(serialized_form) ⇒ Object



221
222
223
# File 'lib/types/props/serializable.rb', line 221

def serialized_form_prop(serialized_form)
  prop_by_serialized_forms[serialized_form.to_s] || raise("No such serialized form: #{serialized_form.inspect}")
end

#valid_rule_key?(key) ⇒ Boolean

Returns:



193
194
195
# File 'lib/types/props/serializable.rb', line 193

def valid_rule_key?(key)
  super || VALID_RULE_KEYS[key]
end