Class: Dinie::Internal::Model

Inherits:
Object
  • Object
show all
Defined in:
lib/dinie/runtime/model.rb

Overview

Base class for every generated model (architecture §5.1, RB3/RB18).

Gives POROs value-semantics without ‘Data.define`, so the floor stays at Ruby 3.1 (Block 0). A subclass declares its fields with Model.attribute in alphabetical order (R-ORDER); the source-emission order is the single source of truth for `to_h` and `inspect`, so the runtime never sorts at call time. Instances are frozen after construction, mirroring the read-only character of the `sdk-js` models.

Examples:

class Customer < Dinie::Internal::Model
  attribute :cpf, :id, :name, :status
end

c = Customer.new(cpf: "***", id: "cust_1", name: "Ana", status: "active")
c.id                       # => "cust_1"
c.to_h                     # => {cpf: "***", id: "cust_1", name: "Ana", status: "active"}
c == Customer.new(...)     # value-equality by attributes
case c; in {status:}; end  # pattern matching via deconstruct_keys

Constant Summary collapse

REDACTED_ATTRIBUTES =

PII attribute names redacted by #inspect. Kept in sync with the logger’s body redaction list (architecture §9 / story 005, which owns the canonical set).

%i[
  access_token account client_secret cnpj cpf cvv password phone secret
].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**attrs) ⇒ Model

Build a frozen instance from keyword arguments — one per declared attribute.

Every declared attribute is required (hydration always passes a value, ‘nil` included), and unknown keywords are rejected, so a contract drift surfaces loudly instead of silently dropping data.

Parameters:

  • attrs (Hash{Symbol => Object})

    one value per declared attribute

Raises:

  • (ArgumentError)

    when a declared attribute is missing or an unknown one is given



103
104
105
106
107
108
# File 'lib/dinie/runtime/model.rb', line 103

def initialize(**attrs)
  expected = self.class.attributes
  validate_keys!(expected, attrs)
  expected.each { |name| instance_variable_set(:"@#{name}", attrs[name]) }
  freeze
end

Class Method Details

.attribute(*names) ⇒ void

This method returns an undefined value.

Declare one or more attributes: defines an ‘attr_reader` for each and appends it to attributes in declaration order. Idempotent per name.

Parameters:

  • names (Array<Symbol, String>)

    attribute names, alphabetical (R-ORDER)



75
76
77
78
79
80
81
82
83
# File 'lib/dinie/runtime/model.rb', line 75

def attribute(*names)
  names.each do |name|
    sym = name.to_sym
    next if attributes.include?(sym)

    attributes << sym
    attr_reader(sym)
  end
end

.attributesArray<Symbol>

The declared attribute names, in declaration (R-ORDER) order. Subclasses inherit and may extend their parent’s list.

Returns:

  • (Array<Symbol>)


66
67
68
# File 'lib/dinie/runtime/model.rb', line 66

def attributes
  @attributes ||= []
end

.inherited(subclass) ⇒ void

This method returns an undefined value.

Carry the parent’s attribute list into each subclass.

Parameters:

  • subclass (Class)


89
90
91
92
# File 'lib/dinie/runtime/model.rb', line 89

def inherited(subclass)
  super
  subclass.instance_variable_set(:@attributes, attributes.dup)
end

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?

Value-equality: same class and same attribute values.

Parameters:

  • other (Object)

Returns:

  • (Boolean)


126
127
128
# File 'lib/dinie/runtime/model.rb', line 126

def ==(other)
  other.class == self.class && other.to_h == to_h
end

#deconstruct_keys(_keys) ⇒ Hash{Symbol => Object}

Enable pattern matching (‘case model; in “active”`).

Parameters:

  • _keys (Array<Symbol>, nil)

    requested keys (ignored — the full hash matches)

Returns:

  • (Hash{Symbol => Object})


120
# File 'lib/dinie/runtime/model.rb', line 120

def deconstruct_keys(_keys) = to_h

#hashInteger

Returns consistent with #eql? so instances work as Hash keys.

Returns:

  • (Integer)

    consistent with #eql? so instances work as Hash keys



132
133
134
# File 'lib/dinie/runtime/model.rb', line 132

def hash
  [self.class, to_h].hash
end

#inspectString

Like #to_h, but with PII redacted — safe for logs and the console.

Returns:

  • (String)


139
140
141
142
143
144
145
# File 'lib/dinie/runtime/model.rb', line 139

def inspect
  pairs = self.class.attributes.map do |name|
    rendered = REDACTED_ATTRIBUTES.include?(name) ? "[REDACTED]" : public_send(name).inspect
    "#{name}=#{rendered}"
  end
  "#<#{self.class.name} #{pairs.join(", ")}>"
end

#to_hHash{Symbol => Object} Also known as: to_hash

Returns attributes in declaration (R-ORDER) order — deterministic.

Returns:

  • (Hash{Symbol => Object})

    attributes in declaration (R-ORDER) order — deterministic



111
112
113
# File 'lib/dinie/runtime/model.rb', line 111

def to_h
  self.class.attributes.to_h { |name| [name, public_send(name)] }
end