Module: Familia::Horreum::Serialization
- Included in:
- Familia::Horreum
- Defined in:
- lib/familia/horreum/serialization.rb
Overview
Serialization: Where Objects Go to Become Strings (and Vice Versa)!
This module is chock-full of methods that’ll make your head spin (in a good way)! We’ve got loaders, dumpers, and refreshers galore. It’s like a laundromat for your data, but instead of quarters, it runs on Redis commands.
A Note on Our Refreshing Refreshers: In the wild world of Ruby, ‘!’ usually means “Watch out! I’m dangerous!” But here in Familia-land, we march to the beat of a different drummer. Our refresh! method is the real deal, doing all the heavy lifting. The non-bang refresh? Oh, it’s just as rowdy, but it plays nice with method chaining. It’s like the polite twin who still knows how to party.
Remember: In Familia, refreshing isn’t just a chore, it’s a chance to dance with data! Whether you bang(!) or not, you’re still invited to the Redis disco.
(P.S. If you’re reading these docs, lol sorry. I asked Claude 3.5 to write in the style of _why the lucky stiff today and got this uncanny valley response. I hope you enjoy reading it as much as I did writing the prompt for it. - @delano).
(Ahem! What I meant to say was that if you’re reading this, congratulations! You’ve stumbled upon the secret garden of documentation. Feel free to smell the Ruby roses, but watch out for the Redis thorns!)
Instance Attribute Summary collapse
-
#redis ⇒ Redis
Summon the mystical Redis connection from the depths of instance or class.
Instance Method Summary collapse
-
#apply_fields(**fields) ⇒ self
Apply a smattering of fields to this object like fairy dust.
-
#commit_fields ⇒ Array<String>
Commit our precious fields to Redis.
-
#destroy! ⇒ void
Dramatically vanquish this object from the face of Redis! (ed: delete it).
-
#refresh ⇒ self
Refreshes the object’s state and returns self to allow method chaining.
-
#refresh! ⇒ Object
Refreshes the object’s state by querying Redis and overwriting the current field values.
-
#save ⇒ Boolean
Save our precious data to Redis, with a sprinkle of timestamp magic!.
-
#to_a ⇒ Array
Line up all our attributes in a neat little array parade!.
-
#to_h ⇒ Hash
Transform this object into a magical hash of wonders!.
-
#to_redis(val) ⇒ Object
The to_redis method in Familia::Redistype and Familia::Horreum serve similar purposes but have some key differences in their implementation:.
-
#transaction {|conn| ... } ⇒ Object
Perform a sacred Redis transaction ritual.
-
#update_expiration(ttl = nil) ⇒ Boolean
Set an expiration date for our data, like a “best before” sticker for Redis!.
Instance Attribute Details
#redis ⇒ Redis
Summon the mystical Redis connection from the depths of instance or class.
This method is like a magical divining rod, always pointing to the nearest source of Redis goodness. It first checks if we have a personal Redis connection (@redis), and if not, it borrows the class’s connection.
51 52 53 |
# File 'lib/familia/horreum/serialization.rb', line 51 def redis @redis || self.class.redis end |
Instance Method Details
#apply_fields(**fields) ⇒ self
Apply a smattering of fields to this object like fairy dust.
130 131 132 133 134 135 136 |
# File 'lib/familia/horreum/serialization.rb', line 130 def apply_fields(**fields) fields.each do |field, value| # Whisper the new value into the object's ear (if it's listening) send("#{field}=", value) if respond_to?("#{field}=") end self end |
#commit_fields ⇒ Array<String>
Be warned, young programmer! This method dabbles in the arcane art of transactions. Side effects may include data persistence and a slight tingling sensation.
Commit our precious fields to Redis.
This method performs a sacred ritual, sending our cherished attributes on a journey through the ethernet to find their resting place in Redis.
154 155 156 157 158 159 160 |
# File 'lib/familia/horreum/serialization.rb', line 154 def commit_fields Familia.ld "[commit_fields] #{self.class} #{rediskey} #{to_h}" transaction do |conn| hmset update_expiration end end |
#destroy! ⇒ void
If debugging is enabled, this method will leave a trace of its destructive path, like breadcrumbs for future data archaeologists.
This method returns an undefined value.
Dramatically vanquish this object from the face of Redis! (ed: delete it)
This method is the doomsday device of our little data world. It will mercilessly eradicate all traces of our object from Redis, leaving naught but digital dust in its wake. Use with caution, lest you accidentally destroy the wrong data-verse!
181 182 183 184 |
# File 'lib/familia/horreum/serialization.rb', line 181 def destroy! Familia.trace :DESTROY, redis, redisuri, caller(1..1) if Familia.debug? delete! end |
#refresh ⇒ self
While this method allows chaining, it still performs a destructive update like refresh!.
Refreshes the object’s state and returns self to allow method chaining. This method calls refresh! internally, performing the actual Redis query and state update.
209 210 211 212 |
# File 'lib/familia/horreum/serialization.rb', line 209 def refresh refresh! self end |
#refresh! ⇒ Object
This is a destructive operation that will overwrite any unsaved changes.
Refreshes the object’s state by querying Redis and overwriting the current field values. This method performs a destructive update on the object, regardless of unsaved changes.
194 195 196 197 198 199 |
# File 'lib/familia/horreum/serialization.rb', line 194 def refresh! Familia.trace :REFRESH, redis, redisuri, caller(1..1) if Familia.debug? fields = hgetall Familia.ld "[refresh!] #{self.class} #{rediskey} #{fields.keys}" optimistic_refresh(**fields) end |
#save ⇒ Boolean
This method will leave breadcrumbs (traces) if you’re in debug mode. It’s like Hansel and Gretel, but for data operations!
Save our precious data to Redis, with a sprinkle of timestamp magic!
This method is like a conscientious historian, not only recording your object’s current state but also meticulously timestamping when it was created and last updated. It’s the record keeper of your data’s life story!
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/familia/horreum/serialization.rb', line 102 def save Familia.trace :SAVE, redis, redisuri, caller(1..1) if Familia.debug? # Update our object's life story self.key ||= self.identifier self.updated = Familia.now.to_i self.created ||= Familia.now.to_i # Commit our tale to the Redis chronicles ret = commit_fields # e.g. ["OK"] Familia.ld "[save] #{self.class} #{rediskey} #{ret}" # Did Redis accept our offering? ret.uniq.all? { |value| value == "OK" } end |
#to_a ⇒ Array
Each value is carefully disguised in its Redis costume before joining the parade.
Line up all our attributes in a neat little array parade!
This method marshals all our object’s attributes into an orderly procession, ready to march into Redis in perfect formation. It’s like a little data army, but friendlier and less prone to conquering neighboring databases.
252 253 254 255 256 257 258 259 |
# File 'lib/familia/horreum/serialization.rb', line 252 def to_a self.class.fields.map do |field| val = send(field) prepared = to_redis(val) Familia.ld " [to_a] field: #{field} val: #{val.class} prepared: #{prepared.class}" prepared end end |
#to_h ⇒ Hash
Watch in awe as each field is lovingly prepared for its Redis adventure!
Transform this object into a magical hash of wonders!
This method performs an alchemical transmutation, turning our noble object into a more plebeian hash. But fear not, for in this form, it can slip through the cracks of the universe (or at least, into Redis) with ease.
228 229 230 231 232 233 234 235 236 |
# File 'lib/familia/horreum/serialization.rb', line 228 def to_h self.class.fields.inject({}) do |hsh, field| val = send(field) prepared = to_redis(val) Familia.ld " [to_h] field: #{field} val: #{val.class} prepared: #{prepared.class}" hsh[field] = prepared hsh end end |
#to_redis(val) ⇒ Object
The to_redis method in Familia::Redistype and Familia::Horreum serve similar purposes but have some key differences in their implementation:
Similarities:
-
Both methods aim to serialize various data types for Redis storage
-
Both handle basic data types like String, Symbol, and Numeric
-
Both have provisions for custom serialization methods
Differences:
-
Familia::Redistype uses the opts for type hints
-
Familia::Horreum had more explicit type checking and conversion
-
Familia::Redistype includes more extensive debug tracing
The centralized Familia.distinguisher method accommodates both approaches by:
-
Handling a wide range of data types, including those from both implementations
-
Providing a ‘strict_values’ option for flexible type handling
-
Supporting custom serialization through a dump_method
-
Including debug tracing similar to Familia::Redistype
By using Familia.distinguisher, we achieve more consistent behavior across different parts of the library while maintaining the flexibility to handle various data types and custom serialization needs. This centralization also makes it easier to extend or modify serialization behavior in the future.
288 289 290 291 292 293 294 295 296 297 298 299 300 |
# File 'lib/familia/horreum/serialization.rb', line 288 def to_redis(val) prepared = Familia.distinguisher(val, false) if prepared.nil? && val.respond_to?(dump_method) prepared = val.send(dump_method) end if prepared.nil? Familia.ld "[#{self.class}#to_redis] nil returned for #{self.class}##{name}" end prepared end |
#transaction {|conn| ... } ⇒ Object
This method temporarily replaces your Redis connection with a multi connection. Don’t worry, it puts everything back where it found it when it’s done.
Perform a sacred Redis transaction ritual.
This method creates a protective circle around your Redis operations, ensuring they all succeed or fail together. It’s like a group hug for your data operations, but with more ACID properties.
73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/familia/horreum/serialization.rb', line 73 def transaction original_redis = self.redis begin redis.multi do |conn| self.instance_variable_set(:@redis, conn) yield(conn) end ensure self.redis = original_redis end end |
#update_expiration(ttl = nil) ⇒ Boolean
If the TTL is zero, we assume our data wants to live forever. Immortality in Redis! Who wouldn’t want that?
Set an expiration date for our data, like a “best before” sticker for Redis!
This method gives our data a lifespan in Redis. It’s like telling Redis, “Hey, this data is fresh now, but it might get stale after a while!”
319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/familia/horreum/serialization.rb', line 319 def update_expiration(ttl = nil) ttl ||= opts[:ttl] ttl = ttl.to_i return if ttl.zero? Familia.ld "Setting expiration for #{rediskey} to #{ttl} seconds" # EXPIRE command returns 1 if the timeout was set, 0 if key does not # exist or the timeout could not be set. expire(ttl).positive? end |