Module: Parse::Cache::MonetaSurface
- Included in:
- KeyspacedStore, Redis, ScopedView
- Defined in:
- lib/parse/cache/moneta_surface.rb
Overview
The derived half of Moneta's store interface.
Moneta gets these from Moneta::Defaults, which the SDK's own store
wrappers do not include. That gap was invisible for a long time because
the Faraday caching middleware only ever calls the primitives. It is not
invisible to applications: the README has documented
Parse.cache["key"] = value and Parse.cache.fetch(...) for years, and
neither existed on Redis. Anyone following the
documentation got NoMethodError.
Required primitives. An including class must implement load,
store, delete, and key?, each taking Moneta's options argument.
load is the read primitive, NOT []: an earlier version of this
module derived load from [] and consulted a moneta_backing_store
that defaulted to self, so load(key, expires: 60) asked whether self
responded to the method it was already executing and recursed until
SystemStackError. Every option-carrying read went the same way, since
fetch, values_at, slice, and fetch_values all route through it.
A wrapper knows how to reach its own backing store; this module does
not, and should not guess.
Optional capabilities that cannot be derived (create, increment,
decrement, expire) are deliberately absent: they need backend
support, and claiming them unconditionally would turn a feature check
into a runtime error. Feature-detect those with respond_to?.
Instance Method Summary collapse
- #[](key) ⇒ Object?
-
#[]=(key, value) ⇒ Object
The stored value, so assignment chains as Ruby expects.
-
#fetch(key, default = nil, options = nil) ⇒ Object
Copied from
Moneta::Defaults#fetch, deliberately line for line. -
#fetch_values(*keys, **options) ⇒ Array<Object>
Values in the order requested, with the block result substituted for misses.
-
#merge!(pairs, options = {}) ⇒ self
(also: #update)
Matching Moneta, which returns the store.
-
#slice(*keys, **options) ⇒ Array<Array(String, Object)>
[key, value]pairs for the present keys only. -
#values_at(*keys, **options) ⇒ Array<Object, nil>
Values in the order requested, nil for misses.
Instance Method Details
#[](key) ⇒ Object?
34 35 36 |
# File 'lib/parse/cache/moneta_surface.rb', line 34 def [](key) load(key, {}) end |
#[]=(key, value) ⇒ Object
Returns the stored value, so assignment chains as Ruby expects.
42 43 44 45 |
# File 'lib/parse/cache/moneta_surface.rb', line 42 def []=(key, value) store(key, value, {}) value end |
#fetch(key, default = nil, options = nil) ⇒ Object
Copied from Moneta::Defaults#fetch, deliberately line for line.
Its two shapes read the second positional differently: without a block it is the default value, with one it is the OPTIONS hash and the block supplies the fallback. Passing both a block and a third argument is an error, not something to silently absorb.
This has now been wrong twice from interpretation: first treating the second argument as a default in both shapes, which dropped the options, then accepting a block alongside a third argument and ignoring one of the two hashes. Reproducing the upstream method is cheaper than continuing to infer it.
66 67 68 69 70 71 72 73 74 75 |
# File 'lib/parse/cache/moneta_surface.rb', line 66 def fetch(key, default = nil, = nil) if block_given? raise ArgumentError, "Only one argument accepted if block is given" if result = load(key, default || {}) result == nil ? yield(key) : result else result = load(key, || {}) result == nil ? default : result end end |
#fetch_values(*keys, **options) ⇒ Array<Object>
Returns values in the order requested, with the block result substituted for misses.
87 88 89 90 91 92 93 |
# File 'lib/parse/cache/moneta_surface.rb', line 87 def fetch_values(*keys, **) values = values_at(*keys, **) return values unless block_given? keys.zip(values).map do |key, value| value == nil ? yield(key) : value end end |
#merge!(pairs, options = {}) ⇒ self Also known as: update
Returns matching Moneta, which returns the store.
109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/parse/cache/moneta_surface.rb', line 109 def merge!(pairs, = {}) pairs.each do |key, value| if block_given? # The existing value is read with the SAME options the write will # use, so a conflict block never decides against a value fetched # under different terms than the one being stored. existing = load(key, ) value = yield(key, existing, value) unless existing.nil? end store(key, value, ) end self end |
#slice(*keys, **options) ⇒ Array<Array(String, Object)>
Returns [key, value] pairs for the
present keys only. Pairs rather than a Hash because that is what
Moneta returns, and the point of this module is to behave the way a
Moneta store does, not the way a Hash does.
100 101 102 103 104 105 |
# File 'lib/parse/cache/moneta_surface.rb', line 100 def slice(*keys, **) keys.each_with_object([]) do |key, out| value = load(key, ) out << [key, value] unless value.nil? end end |