Module: Familia::Horreum::ManagementMethods
- Includes:
- RelatedFieldsManagement
- Defined in:
- lib/familia/horreum/management_methods.rb
Overview
ManagementMethods: Provides class-level functionality for Horreum records.
This module is extended into classes that include Familia::Horreum, providing methods for Database operations and object management.
Key features:
- Includes RelatedFieldsManagement for DataType field handling
- Provides utility methods for working with Database objects
Instance Method Summary collapse
-
#all(suffix = nil) ⇒ Object
-
#any?(filter = '*') ⇒ Boolean
-
#create ⇒ Object
Creates and persists a new instance of the class.
-
#dbkey(identifier, suffix = self.suffix) ⇒ Object
+identifier+ can be a value or an Array of values used to create the index.
-
#destroy!(identifier, suffix = nil) ⇒ Boolean
Destroys an object in Database with the given identifier.
-
#exists?(identifier, suffix = nil) ⇒ Boolean
Checks if an object with the given identifier exists in Redis.
-
#find_by_id(identifier, suffix = nil) ⇒ Object?
(also: #find, #load, #from_identifier)
Retrieves and instantiates an object from Database using its identifier.
-
#find_by_key(objkey) ⇒ Object?
(also: #from_dbkey)
Retrieves and instantiates an object from Database using the full object key.
-
#find_keys(suffix = '*') ⇒ Array<String>
Finds all keys in Database matching the given suffix pattern.
-
#matching_keys_count(filter = '*') ⇒ Integer
(also: #size)
Returns the number of dbkeys matching the given filter pattern.
-
#multiget(*ids) ⇒ Object
-
#rawmultiget(*ids) ⇒ Object
Methods included from RelatedFieldsManagement
#attach_class_related_field, #attach_instance_related_field
Instance Method Details
#all(suffix = nil) ⇒ Object
245 246 247 248 249 |
# File 'lib/familia/horreum/management_methods.rb', line 245 def all(suffix = nil) suffix ||= self.suffix # objects that could not be parsed will be nil keys(suffix).filter_map { |k| find_by_key(k) } end |
#any?(filter = '*') ⇒ Boolean
251 252 253 |
# File 'lib/familia/horreum/management_methods.rb', line 251 def any?(filter = '*') matching_keys_count(filter) > 0 end |
#create ⇒ Object
The behavior of this method depends on the implementation of #new, #exists?, and #save in the class and its superclasses.
Creates and persists a new instance of the class.
This method serves as a factory method for creating and persisting new instances of the class. It combines object instantiation, existence checking, and persistence in a single operation.
The method is flexible in accepting both positional and keyword arguments: - Positional arguments (*args) are passed directly to the constructor. - Keyword arguments (**kwargs) are passed as a hash to the constructor.
After instantiation, the method checks if an object with the same identifier already exists. If it does, a Familia::Problem exception is raised to prevent overwriting existing data.
Finally, the method saves the new instance returns it.
56 57 58 59 60 61 62 |
# File 'lib/familia/horreum/management_methods.rb', line 56 def create(*, **) fobj = new(*, **) raise Familia::Problem, "#{self} already exists: #{fobj.dbkey}" if fobj.exists? fobj.save fobj end |
#dbkey(identifier, suffix = self.suffix) ⇒ Object
+identifier+ can be a value or an Array of values used to create the index. We don’t enforce a default suffix; that’s left up to the instance. The suffix is used to differentiate between different types of objects.
+suffix+ If a nil value is explicitly passed in, it won’t appear in the redis key that’s returned. If no suffix is passed in, the class’ suffix is used as the default (via the class method self.suffix). It’s an important distinction b/c passing in an explicitly nil is how DataType objects at the class level are created without the global default ‘object’ suffix. See DataType#dbkey “parent_class?” for more details.
237 238 239 240 241 242 243 |
# File 'lib/familia/horreum/management_methods.rb', line 237 def dbkey(identifier, suffix = self.suffix) # Familia.ld "[.dbkey] #{identifier} for #{self} (suffix:#{suffix})" raise NoIdentifier, self if identifier.to_s.empty? identifier &&= identifier.to_s Familia.dbkey(prefix, identifier, suffix) end |
#destroy!(identifier, suffix = nil) ⇒ Boolean
Destroys an object in Database with the given identifier.
This method is part of Familia’s high-level object lifecycle management. While delete!
operates directly on dbkeys, destroy! operates at the object level and is used for
ORM-style operations. Use destroy! when removing complete objects from the system, and
delete! when working directly with dbkeys.
200 201 202 203 204 205 206 207 208 209 |
# File 'lib/familia/horreum/management_methods.rb', line 200 def destroy!(identifier, suffix = nil) suffix ||= self.suffix return false if identifier.to_s.empty? objkey = dbkey identifier, suffix ret = dbclient.del objkey Familia.trace :DESTROY!, dbclient, "#{objkey} #{ret.inspect}", caller(1..1) if Familia.debug? ret.positive? end |
#exists?(identifier, suffix = nil) ⇒ Boolean
Checks if an object with the given identifier exists in Redis.
This method constructs the full dbkey using the provided identifier and suffix, then checks if the key exists in Redis.
174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/familia/horreum/management_methods.rb', line 174 def exists?(identifier, suffix = nil) suffix ||= self.suffix return false if identifier.to_s.empty? objkey = dbkey identifier, suffix ret = dbclient.exists objkey Familia.trace :EXISTS, dbclient, "#{objkey} #{ret.inspect}", caller(1..1) if Familia.debug? ret.positive? # differs from Valkey API but I think it's okay bc `exists?` is a predicate method. end |
#find_by_id(identifier, suffix = nil) ⇒ Object? Also known as: find, load, from_identifier
Retrieves and instantiates an object from Database using its identifier.
This method constructs the full dbkey using the provided identifier
and suffix, then delegates to find_by_key for the actual retrieval and
instantiation.
It’s a higher-level method that abstracts away the key construction, making it easier to retrieve objects when you only have their identifier.
148 149 150 151 152 153 154 155 156 157 |
# File 'lib/familia/horreum/management_methods.rb', line 148 def find_by_id(identifier, suffix = nil) suffix ||= self.suffix return nil if identifier.to_s.empty? objkey = dbkey(identifier, suffix) Familia.ld "[.find_by_id] #{self} from key #{objkey})" Familia.trace :FIND_BY_ID, Familia.dbclient(uri), objkey, caller(1..1).first if Familia.debug? find_by_key objkey end |
#find_by_key(objkey) ⇒ Object? Also known as: from_dbkey
Retrieves and instantiates an object from Database using the full object key.
This method performs a two-step process to safely retrieve and instantiate objects:
- It first checks if the key exists in Redis. This is crucial because:
- It provides a definitive answer about the object’s existence.
- It prevents ambiguity that could arise from
hgetallreturning an empty hash for non-existent keys, which could lead to the creation of “empty” objects.
- If the key exists, it retrieves the object’s data and instantiates it.
This approach ensures that we only attempt to instantiate objects that actually exist in Redis, improving reliability and simplifying debugging.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/familia/horreum/management_methods.rb', line 105 def find_by_key(objkey) raise ArgumentError, 'Empty key' if objkey.to_s.empty? # We use a lower-level method here b/c we're working with the # full key and not just the identifier. does_exist = dbclient.exists(objkey).positive? Familia.ld "[.find_by_key] #{self} from key #{objkey} (exists: #{does_exist})" Familia.trace :FROM_KEY, dbclient, objkey, caller(1..1) if Familia.debug? # This is the reason for calling exists first. We want to definitively # and without any ambiguity know if the object exists in Redis. If it # doesn't, we return nil. If it does, we proceed to load the object. # Otherwise, hgetall will return an empty hash, which will be passed to # the constructor, which will then be annoying to debug. return unless does_exist obj = dbclient.hgetall(objkey) # horreum objects are persisted as database hashes Familia.trace :FROM_KEY2, dbclient, "#{objkey}: #{obj.inspect}", caller(1..1) if Familia.debug? new(**obj) end |
#find_keys(suffix = '*') ⇒ Array<String>
Finds all keys in Database matching the given suffix pattern.
This method searches for all dbkeys that match the given suffix pattern. It uses the class’s dbkey method to construct the search pattern.
223 224 225 |
# File 'lib/familia/horreum/management_methods.rb', line 223 def find_keys(suffix = '*') dbclient.keys(dbkey('*', suffix)) || [] end |
#matching_keys_count(filter = '*') ⇒ Integer Also known as: size
Returns the number of dbkeys matching the given filter pattern
258 259 260 |
# File 'lib/familia/horreum/management_methods.rb', line 258 def matching_keys_count(filter = '*') dbclient.keys(dbkey(filter)).compact.size end |
#multiget(*ids) ⇒ Object
64 65 66 67 |
# File 'lib/familia/horreum/management_methods.rb', line 64 def multiget(*ids) ids = rawmultiget(*ids) ids.filter_map { |json| from_json(json) } end |
#rawmultiget(*ids) ⇒ Object
69 70 71 72 73 74 75 |
# File 'lib/familia/horreum/management_methods.rb', line 69 def rawmultiget(*ids) ids.collect! { |objid| dbkey(objid) } return [] if ids.compact.empty? Familia.trace :MULTIGET, dbclient, "#{ids.size}: #{ids}", caller(1..1) if Familia.debug? dbclient.mget(*ids) end |