Skip to content

Commit c495cfc

Browse files
authored
Merge pull request #37 from delano/delano/20240826-fast-attribute
Enhancements for Redis access and instance relations
2 parents 4856214 + 788aaf3 commit c495cfc

File tree

7 files changed

+77
-23
lines changed

7 files changed

+77
-23
lines changed

Gemfile.lock

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
familia (1.0.0.pre.rc6)
4+
familia (1.0.0.pre.rc7)
55
redis (>= 4.8.1, < 6.0)
66
uri-redis (~> 1.3)
77

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Familia - 1.0.0-rc6 (August 2024)
1+
# Familia - 1.0.0-rc7 (August 2024)
22

33
**Organize and store Ruby objects in Redis. A powerful Ruby ORM (of sorts) for Redis.**
44

VERSION.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
:MAJOR: 1
33
:MINOR: 0
44
:PATCH: 0
5-
:PRE: rc6
5+
:PRE: rc7

lib/familia/horreum.rb

+3-1
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,11 @@ def initialize_relatives
142142
#
143143
opts[:parent] = self # unless opts.key(:parent)
144144

145+
suffix_override = opts.fetch(:suffix, name)
146+
145147
# Instantiate the RedisType object and below we store it in
146148
# an instance variable.
147-
redis_type = klass.new name, opts
149+
redis_type = klass.new suffix_override, opts
148150

149151
# Freezes the redis_type, making it immutable.
150152
# This ensures the object's state remains consistent and prevents any modifications,

lib/familia/horreum/class_methods.rb

+68-16
Original file line numberDiff line numberDiff line change
@@ -74,38 +74,90 @@ def field(name)
7474
fields << name
7575
attr_accessor name
7676

77-
# Every field gets a fast writer method for immediately persisting
78-
fast_writer! name
77+
# Every field gets a fast attribute method for immediately persisting
78+
fast_attribute! name
7979
end
8080

81-
# Defines a writer method with a bang (!) suffix for a given attribute name.
81+
# Defines a fast attribute method with a bang (!) suffix for a given
82+
# attribute name. Fast attribute methods are used to immediately read or
83+
# write attribute values from/to Redis. Calling a fast attribute method
84+
# has no effect on any of the object's other attributes and does not
85+
# trigger a call to update the object's expiration time.
8286
#
8387
# The dynamically defined method performs the following:
84-
# - Checks if the correct number of arguments is provided (exactly one).
88+
# - Acts as both a reader and a writer method.
89+
# - When called without arguments, retrieves the current value from Redis.
90+
# - When called with an argument, persists the value to Redis immediately.
91+
# - Checks if the correct number of arguments is provided (zero or one).
8592
# - Converts the provided value to a format suitable for Redis storage.
86-
# - Uses the existing accessor method to set the attribute value.
87-
# - Persists the value to Redis immediately using the hset command.
88-
# - Includes custom error handling to raise an ArgumentError if the wrong number of arguments is given.
89-
# - Raises a custom error message if an exception occurs during the execution of the method.
90-
#
91-
# @param [Symbol, String] name the name of the attribute for which the writer method is defined.
92-
# @raise [ArgumentError] if the wrong number of arguments is provided.
93-
# @raise [RuntimeError] if an exception occurs during the execution of the method.
94-
#
95-
def fast_writer!(name)
93+
# - Uses the existing accessor method to set the attribute value when
94+
# writing.
95+
# - Persists the value to Redis immediately using the hset command when
96+
# writing.
97+
# - Includes custom error handling to raise an ArgumentError if the wrong
98+
# number of arguments is given.
99+
# - Raises a custom error message if an exception occurs during the
100+
# execution of the method.
101+
#
102+
# @param [Symbol, String] name the name of the attribute for which the
103+
# fast method is defined.
104+
# @return [Object] the current value of the attribute when called without
105+
# arguments.
106+
# @raise [ArgumentError] if more than one argument is provided.
107+
# @raise [RuntimeError] if an exception occurs during the execution of the
108+
# method.
109+
#
110+
def fast_attribute!(name = nil)
111+
# Fast attribute accessor method for the '#{name}' attribute.
112+
# This method provides immediate read and write access to the attribute
113+
# in Redis.
114+
#
115+
# When called without arguments, it retrieves the current value of the
116+
# attribute from Redis.
117+
# When called with an argument, it immediately persists the new value to
118+
# Redis.
119+
#
120+
# @overload #{name}!
121+
# Retrieves the current value of the attribute from Redis.
122+
# @return [Object] the current value of the attribute.
123+
#
124+
# @overload #{name}!(value)
125+
# Sets and immediately persists the new value of the attribute to
126+
# Redis.
127+
# @param value [Object] the new value to set for the attribute.
128+
# @return [Object] the newly set value.
129+
#
130+
# @raise [ArgumentError] if more than one argument is provided.
131+
# @raise [RuntimeError] if an exception occurs during the execution of
132+
# the method.
133+
#
134+
# @note This method bypasses any object-level caching and interacts
135+
# directly with Redis. It does not trigger updates to other attributes
136+
# or the object's expiration time.
137+
#
138+
# @example
139+
#
140+
# def #{name}!(*args)
141+
# # Method implementation
142+
# end
143+
#
96144
define_method :"#{name}!" do |*args|
97145
# Check if the correct number of arguments is provided (exactly one).
98-
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 1)" if args.size != 1
146+
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 0 or 1)" if args.size > 1
99147

100148
val = args.first
101149

150+
# If no value is provided to this fast attribute method, make a call
151+
# to redis to return the current stored value of the hash field.
152+
return hget name if val.nil?
153+
102154
begin
103155
# Trace the operation if debugging is enabled.
104156
Familia.trace :FAST_WRITER, redis, "#{name}: #{val.inspect}", caller(1..1) if Familia.debug?
105157

106158
# Convert the provided value to a format suitable for Redis storage.
107159
prepared = to_redis(val)
108-
Familia.ld "[.fast_writer!] #{name} val: #{val.class} prepared: #{prepared.class}"
160+
Familia.ld "[.fast_attribute!] #{name} val: #{val.class} prepared: #{prepared.class}"
109161

110162
# Use the existing accessor method to set the attribute value.
111163
send :"#{name}=", val

lib/familia/redistype.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class RedisType
1616
extend Familia::Features
1717

1818
@registered_types = {}
19-
@valid_options = %i[class parent ttl default db key redis]
19+
@valid_options = %i[class parent ttl default db key redis suffix]
2020
@db = nil
2121

2222
feature :expiration

try/27_redis_horreum_try.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@
4747
@customer.save
4848
#=> true
4949

50-
## Horreum object fields have a fast writer method (1 of 2)
50+
## Horreum object fields have a fast attribute method (1 of 2)
5151
Familia.trace :LOAD, @customer.redis, @customer.redisuri, caller if Familia.debug?
5252
@customer.name! 'Jane Doe'
5353
#=> 0
5454

55-
## Horreum object fields have a fast writer method (2 of 2)
55+
## Horreum object fields have a fast attribute method (2 of 2)
5656
@customer.refresh!
5757
@customer.name
5858
#=> "Jane Doe"

0 commit comments

Comments
 (0)