Module: ActiveModel::SchematizedJson::ClassMethods

Defined in:
activemodel/lib/active_model/schematized_json.rb

Instance Method Summary collapse

Instance Method Details

#has_delegated_json(attr, **schema) ⇒ Object

Like has_json but each schema key also becomes its own set of accessor methods.

class Account < ApplicationRecord
  has_delegated_json :flags, beta: false, staff: :boolean
end

a = Account.new
a.beta? # => false
a.beta = true
a.beta # => true


57
58
59
60
61
62
63
64
65
# File 'activemodel/lib/active_model/schematized_json.rb', line 57

def has_delegated_json(attr, **schema)
  has_json attr, **schema

  schema.keys.each do |schema_key|
    define_method(schema_key)       { public_send(attr).public_send(schema_key) }
    define_method("#{schema_key}?") { public_send(attr).public_send("#{schema_key}?") }
    define_method("#{schema_key}=") { |value| send(attr).public_send("#{schema_key}=", value) }
  end
end

#has_json(attr, **schema) ⇒ Object

Provides a schema-enforced access object for a JSON attribute. This allows you to assign values directly from the UI as strings, and still have them set with the correct JSON type in the database.

Only the three basic JSON types are supported: boolean, integer, and string. No nesting either. These types can either be set by referring to them by their symbol or by setting a default value. Default values are set when a new model is instantiated and on before_save (if defined).

Examples:

class Account < ApplicationRecord
  has_json :settings, restrict_creation_to_admins: true, max_invites: 10, greeting: "Hello!"
  has_json :flags, beta: false, staff: :boolean
end

a = Account.new
a.settings.restrict_creation_to_admins? # => true
a.settings.max_invites = "100" # => Set to integer 100
a.settings = { "restrict_creation_to_admins" => "false", "max_invites" => "500", "greeting" => "goodbye" }
a.settings.greeting # => "goodbye"
a.flags.staff # => nil
a.flags.staff? # => false


32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'activemodel/lib/active_model/schematized_json.rb', line 32

def has_json(attr, **schema)
  define_method(attr) do
    # Ensure the attribute is set if nil, so we can pass the reference to the accessor for defaults.
    _write_attribute(attr.to_s, {}) if attribute(attr.to_s).nil?

    # No memoization used in order to stay compatible with #reload (and because it's such a thin accessor).
    ActiveModel::SchematizedJson::DataAccessor.new(schema, data: attribute(attr.to_s))
  end

  define_method("#{attr}=") { |data| public_send(attr).assign_data_with_type_casting(data) }

  # Ensure default values are set before saving by relying on DataAccessor instantiation to do it.
  before_save -> { send(attr) } if respond_to?(:before_save)
end