Module: Familia::Horreum::DefinitionMethods
- Includes:
- RelatedFieldsManagement, Settings
- Defined in:
- lib/familia/horreum/subclass/definition.rb
Overview
DefinitionMethods - Class-level DSL methods for defining Horreum model structure
This module is extended into classes that include Familia::Horreum, providing class methods for defining model structure and configuration (e.g., Customer.field :name, Customer.identifier_field :custid).
Key features:
- Defines DSL methods for field definitions (field, identifier_field)
- Includes RelatedFieldsManagement for DataType field DSL (list, set, zset, etc.)
- Provides class-level configuration (prefix, suffix, logical_database)
- Manages field metadata and inheritance
Instance Attribute Summary
Attributes included from Settings
#current_key_version, #default_expiration, #delim, #encryption_keys, #encryption_personalization, #transaction_mode
Instance Method Summary collapse
-
#add_feature_options(feature_name, **options) ⇒ Hash
Add feature options for a specific feature.
- #class_related_fields ⇒ Object
- #dump_method ⇒ Object
-
#feature_options(feature_name = nil) ⇒ Hash
Retrieves feature options for the current class.
-
#field(name, as: name, fast_method: :"#{name}!", on_conflict: :raise, category: nil) ⇒ Object
Defines a field for the class and creates accessor methods.
-
#field_method_map ⇒ Object
Returns a hash mapping field names to method names for backward compatibility.
-
#field_types ⇒ Object
Storage for field type instances.
-
#fields ⇒ Object
Returns the list of field names defined for the class in the order that they were defined.
-
#identifier_field(val = nil) ⇒ Object
Sets or retrieves the unique identifier field for the class.
- #load_method ⇒ Object
- #logical_database(v = nil) ⇒ Object
-
#persistent_fields ⇒ Object
Get fields for serialization (excludes transients).
-
#prefix(a = nil) ⇒ String, Symbol
Sets or retrieves the prefix for generating Valkey/Redis keys.
-
#register_field_type(field_type) ⇒ Object
Register a field type instance with this class.
- #related_fields ⇒ Object
- #relations? ⇒ Boolean
-
#suffix(a = nil, &blk) ⇒ String, Symbol
Sets or retrieves the suffix for generating Valkey/Redis keys.
-
#transient_field(name) ⇒ Object
Create and register a transient field type.
-
#transient_fields ⇒ Object
Get fields that are not persisted to the database (transients).
Methods included from RelatedFieldsManagement
#attach_class_related_field, #attach_instance_related_field
Methods included from Settings
#configure, #default_suffix, #pipeline_mode, #pipeline_mode=
Instance Method Details
#add_feature_options(feature_name, **options) ⇒ Hash
This method only sets defaults for options that don't already exist, using the ||= operator to prevent overwrites.
Add feature options for a specific feature
This method provides a clean way for features to set their default options without worrying about initialization state. Similar to register_field_type for field types.
Feature options are stored at the class level using instance variables, ensuring complete isolation between different Familia::Horreum subclasses. Each class maintains its own @feature_options hash.
294 295 296 297 298 299 300 301 302 303 304 |
# File 'lib/familia/horreum/subclass/definition.rb', line 294 def (feature_name, **) @feature_options ||= {} @feature_options[feature_name.to_sym] ||= {} # Only set defaults for options that don't already exist .each do |key, value| @feature_options[feature_name.to_sym][key] ||= value end @feature_options[feature_name.to_sym] end |
#class_related_fields ⇒ Object
164 165 166 167 |
# File 'lib/familia/horreum/subclass/definition.rb', line 164 def @class_related_fields ||= {} @class_related_fields end |
#dump_method ⇒ Object
178 179 180 |
# File 'lib/familia/horreum/subclass/definition.rb', line 178 def dump_method @dump_method || :to_json # Familia.dump_method end |
#feature_options(feature_name = nil) ⇒ Hash
Retrieves feature options for the current class.
Feature options are stored per-class in instance variables, ensuring complete isolation between different Familia::Horreum subclasses. Each class maintains its own @feature_options hash that does not interfere with other classes' configurations.
259 260 261 262 263 264 |
# File 'lib/familia/horreum/subclass/definition.rb', line 259 def (feature_name = nil) @feature_options ||= {} return @feature_options if feature_name.nil? @feature_options[feature_name.to_sym] || {} end |
#field(name, as: name, fast_method: :"#{name}!", on_conflict: :raise, category: nil) ⇒ Object
Defines a field for the class and creates accessor methods.
This method defines a new field for the class, creating getter and setter
instance methods similar to attr_accessor. It also generates a fast
writer method for immediate persistence to the database.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/familia/horreum/subclass/definition.rb', line 99 def field(name, as: name, fast_method: :"#{name}!", on_conflict: :raise, category: nil) # Use field type system for consistency require_relative '../../field_type' # Create appropriate field type based on category field_type = if category == :transient require_relative '../../features/transient_fields/transient_field_type' TransientFieldType.new(name, as: as, fast_method: false, on_conflict: on_conflict) else # For regular fields and other categories, create custom field type with category override custom_field_type = Class.new(FieldType) do define_method :category do category || :field end end custom_field_type.new(name, as: as, fast_method: fast_method, on_conflict: on_conflict) end register_field_type(field_type) end |
#field_method_map ⇒ Object
Returns a hash mapping field names to method names for backward compatibility
192 193 194 |
# File 'lib/familia/horreum/subclass/definition.rb', line 192 def field_method_map field_types.transform_values(&:method_name) end |
#field_types ⇒ Object
Storage for field type instances
187 188 189 |
# File 'lib/familia/horreum/subclass/definition.rb', line 187 def field_types @field_types ||= {} end |
#fields ⇒ Object
Returns the list of field names defined for the class in the order
that they were defined. i.e. field :a; field :b; fields => [:a, :b].
159 160 161 162 |
# File 'lib/familia/horreum/subclass/definition.rb', line 159 def fields @fields ||= [] @fields end |
#identifier_field(val = nil) ⇒ Object
Sets or retrieves the unique identifier field for the class.
This method defines or returns the field or method that contains the unique identifier used to generate the dbkey for the object. If a value is provided, it sets the identifier field; otherwise, it returns the current identifier field.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/familia/horreum/subclass/definition.rb', line 60 def identifier_field(val = nil) if val # Validate identifier field definition at class definition time case val when Symbol, String, Proc @identifier_field = val else raise Problem, <<~ERROR Invalid identifier field definition: #{val.inspect}. Use a field name (Symbol/String) or Proc. ERROR end end @identifier_field end |
#load_method ⇒ Object
182 183 184 |
# File 'lib/familia/horreum/subclass/definition.rb', line 182 def load_method @load_method || :from_json # Familia.load_method end |
#logical_database(v = nil) ⇒ Object
151 152 153 154 155 |
# File 'lib/familia/horreum/subclass/definition.rb', line 151 def logical_database(v = nil) Familia.trace :LOGICAL_DATABASE_DEF, "instvar:#{@logical_database}", v if Familia.debug? @logical_database = v unless v.nil? @logical_database || parent&.logical_database end |
#persistent_fields ⇒ Object
Get fields for serialization (excludes transients)
197 198 199 200 201 |
# File 'lib/familia/horreum/subclass/definition.rb', line 197 def persistent_fields fields.select do |field| field_types[field]&.persistent? end end |
#prefix(a = nil) ⇒ String, Symbol
Sets or retrieves the prefix for generating Valkey/Redis keys.
The exception is only raised when both @prefix is nil/falsy AND name is nil, which typically occurs with anonymous classes that haven't had their prefix explicitly set.
140 141 142 143 144 145 146 147 148 149 |
# File 'lib/familia/horreum/subclass/definition.rb', line 140 def prefix(a = nil) @prefix = a if a @prefix || begin if name.nil? raise Problem, 'Cannot generate prefix for anonymous class. ' \ 'Use `prefix` method to set explicitly.' end config_name.to_sym end end |
#register_field_type(field_type) ⇒ Object
Register a field type instance with this class
This method installs the field type's methods and registers it for later reference. It maintains backward compatibility by creating FieldDefinition objects.
218 219 220 221 222 223 224 225 226 |
# File 'lib/familia/horreum/subclass/definition.rb', line 218 def register_field_type(field_type) fields << field_type.name field_type.install(self) # Complete the registration after installation. If we do this beforehand # we can run into issues where it looks like it's already installed. field_types[field_type.name] = field_type # Freeze the field_type to ensure immutability (maintains Data class heritage) field_type.freeze end |
#related_fields ⇒ Object
169 170 171 172 |
# File 'lib/familia/horreum/subclass/definition.rb', line 169 def @related_fields ||= {} @related_fields end |
#relations? ⇒ Boolean
174 175 176 |
# File 'lib/familia/horreum/subclass/definition.rb', line 174 def relations? @has_related_fields ||= false end |
#suffix(a = nil, &blk) ⇒ String, Symbol
Sets or retrieves the suffix for generating Valkey/Redis keys.
126 127 128 129 |
# File 'lib/familia/horreum/subclass/definition.rb', line 126 def suffix(a = nil, &blk) @suffix = a || blk if a || !blk.nil? @suffix || Familia.default_suffix end |
#transient_field(name) ⇒ Object
Create and register a transient field type
310 311 312 313 314 |
# File 'lib/familia/horreum/subclass/definition.rb', line 310 def transient_field(name, **) require_relative '../../features/transient_fields/transient_field_type' field_type = TransientFieldType.new(name, **, fast_method: false) register_field_type(field_type) end |
#transient_fields ⇒ Object
Get fields that are not persisted to the database (transients)
204 205 206 207 208 |
# File 'lib/familia/horreum/subclass/definition.rb', line 204 def transient_fields fields.select do |field| field_types[field]&.transient? end end |