Class: Familia::TransientFieldType

Inherits:
FieldType
  • Object
show all
Defined in:
lib/familia/features/transient_fields/transient_field_type.rb

Overview

TransientFieldType - Fields that are not persisted to database

Transient fields automatically wrap values in RedactedString for security and are excluded from serialization operations. They are ideal for storing sensitive data like API keys, passwords, and tokens that should not be persisted to the database.

Examples:

Using transient fields

class SecretService < Familia::Horreum
  field :name                    # Regular field
  transient_field :api_key       # Wrapped in RedactedString
  transient_field :password      # Not persisted to database
end

service = SecretService.new
service.api_key = "sk-1234567890"
service.api_key.class           #=> RedactedString
service.to_h                    #=> {:name => nil} (no api_key)

Instance Attribute Summary

Attributes inherited from FieldType

#fast_method_name, #loggable, #method_name, #name, #on_conflict, #options

Instance Method Summary collapse

Methods inherited from FieldType

#generated_methods, #initialize, #inspect, #install

Constructor Details

This class inherits a constructor from Familia::FieldType

Instance Method Details

#categorySymbol

Category for transient fields

Returns:

  • (Symbol)

    :transient



105
106
107
# File 'lib/familia/features/transient_fields/transient_field_type.rb', line 105

def category
  :transient
end

#define_fast_writer(_klass) ⇒ Object

Override fast writer to disable it for transient fields

Transient fields should not have fast writers since they’re not persisted to the database.

Parameters:

  • klass (Class)

    The class to define the method on



81
82
83
84
85
# File 'lib/familia/features/transient_fields/transient_field_type.rb', line 81

def define_fast_writer(_klass)
  # No fast writer for transient fields since they're not persisted
  Familia.ld "[TransientFieldType] Skipping fast writer for transient field: #{@name}"
  nil
end

#define_getter(klass) ⇒ Object

Override getter to unwrap RedactedString values

Returns the actual value from the RedactedString wrapper for convenient access, or nil if the value is nil or cleared.

Parameters:

  • klass (Class)

    The class to define the method on



60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/familia/features/transient_fields/transient_field_type.rb', line 60

def define_getter(klass)
  field_name = @name
  method_name = @method_name

  handle_method_conflict(klass, method_name) do
    klass.define_method method_name do
      wrapped = instance_variable_get(:"@#{field_name}")
      return nil if wrapped.nil? || wrapped.cleared?

      wrapped
    end
  end
end

#define_setter(klass) ⇒ Object

Override setter to wrap values in RedactedString

Values are automatically wrapped in RedactedString objects for security. Nil values and existing RedactedString objects are handled appropriately.

Parameters:

  • klass (Class)

    The class to define the method on



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/familia/features/transient_fields/transient_field_type.rb', line 35

def define_setter(klass)
  field_name = @name
  method_name = @method_name

  handle_method_conflict(klass, :"#{method_name}=") do
    klass.define_method :"#{method_name}=" do |value|
      wrapped = if value.nil?
                  nil
                elsif value.is_a?(RedactedString)
                  value
                else
                  RedactedString.new(value)
                end
      instance_variable_set(:"@#{field_name}", wrapped)
    end
  end
end

#deserialize(_value, _record = nil) ⇒ nil

Transient fields are not deserialized from database

This method should not be called since transient fields are not persisted, but we provide it for completeness.

Parameters:

  • value (Object)

    The value to deserialize

  • record (Object)

    The record instance

Returns:

  • (nil)

    Always nil since transient fields are not stored



133
134
135
136
137
# File 'lib/familia/features/transient_fields/transient_field_type.rb', line 133

def deserialize(_value, _record = nil)
  # Transient fields should never be deserialized
  Familia.ld "[TransientFieldType] WARNING: deserialize called on transient field #{@name}"
  nil
end

#persistent?Boolean

Transient fields are not persisted to database

Returns:

  • (Boolean)

    false - transient fields are never persisted



91
92
93
# File 'lib/familia/features/transient_fields/transient_field_type.rb', line 91

def persistent?
  false
end

#serialize(_value, _record = nil) ⇒ nil

Transient fields are not serialized to database

This method should not be called since transient fields are not persisted, but we provide it for completeness.

Parameters:

  • value (Object)

    The value to serialize

  • record (Object)

    The record instance

Returns:

  • (nil)

    Always nil since transient fields are not serialized



118
119
120
121
122
# File 'lib/familia/features/transient_fields/transient_field_type.rb', line 118

def serialize(_value, _record = nil)
  # Transient fields should never be serialized
  Familia.ld "[TransientFieldType] WARNING: serialize called on transient field #{@name}"
  nil
end

#transient?Boolean

A convenience method that wraps persistent?

Returns:

  • (Boolean)


97
98
99
# File 'lib/familia/features/transient_fields/transient_field_type.rb', line 97

def transient?
  !persistent?
end