class LazyHash
A simple hash table which fetches it's values only when required.
Definitions
def initialize(&block)
Initialize a lazily loaded hash.
Implementation
def initialize(&block)
@changed = false
@values = nil
@loader = block
end
def [](key)
Fetch a value by key, loading the hash if necessary.
Signature
-
parameter
keyObject The key.
-
returns
Object | Nil The value.
Implementation
def [] key
load![key]
end
def []=(key, value)
Store a value by key.
Signature
-
parameter
keyObject The key.
-
parameter
valueObject The value.
-
returns
Object The stored value.
Implementation
def []= key, value
values = load!
if values[key] != value
values[key] = value
@changed = true
end
return value
end
def include?(key)
Check whether the hash contains a key.
Signature
-
parameter
keyObject The key.
-
returns
Boolean Whether the key exists.
Implementation
def include?(key)
load!.include?(key)
end
def delete(key)
Delete a value by key.
Signature
-
parameter
keyObject The key.
-
returns
Object | Nil The deleted value.
Implementation
def delete(key)
load!
@changed = true if @values.include? key
@values.delete(key)
end
def changed?
Check whether any value has changed.
Signature
-
returns
Boolean Whether the hash has changed.
Implementation
def changed?
@changed
end
def load!
Load and return the underlying values.
Signature
-
returns
Hash The loaded values.
Implementation
def load!
@values ||= @loader.call
end
def loaded?
Check whether the underlying values have been loaded.
Signature
-
returns
Boolean Whether the values are loaded.
Implementation
def loaded?
!@values.nil?
end
def needs_update?(timeout = nil)
Check whether the values should be persisted.
Signature
-
parameter
timeoutNumeric | Nil The maximum age before an update is required.
-
returns
Boolean Whether an update is required.
Implementation
def needs_update?(timeout = nil)
# If data has changed, we need update:
return true if @changed
# We want to be careful here and not call load! which isn't cheap operation.
if timeout and @values and updated_at = @values[:updated_at]
# If the last update was too long ago, we need update:
return true if updated_at < (Time.now - timeout)
end
return false
end