Skip to content

Commit 09bdfce

Browse files
committed
Add collection methods to NamespacedEnvCache
1 parent 00a8551 commit 09bdfce

1 file changed

Lines changed: 50 additions & 0 deletions

File tree

lib/namespaced_env_cache.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,56 @@ def persistent(name, **opts, &block)
7272
end
7373
end
7474

75+
##
76+
# Cache an ActiveRecord collection. Supports only a basic collection of one type of object. Column selections or
77+
# joins etc. will NOT be respected when the collection is read back out.
78+
# @param name [String] cache key name
79+
# @param value [ActiveRecord::Relation] collection to cache
80+
# @param opts [Hash] options hash - any unlisted options will be passed to the underlying cache
81+
# @option opts [Boolean] :include_community whether to include the community ID in the cache key
82+
def write_collection(name, value, **opts)
83+
types = value.map(&:class).uniq
84+
if types.size > 1
85+
raise TypeError, "Can't cache more than one type of object via write_collection"
86+
end
87+
88+
data = [types[0], ...value.map(&:id)]
89+
namespaced = construct_ns_key(name, include_community: include_community(opts))
90+
@underlying.write(namespaced, data, **opts)
91+
end
92+
93+
##
94+
# Read an ActiveRecord collection from cache. Returns a basic collection of the records that were cached, with
95+
# no selects or joins applied.
96+
# @param name [String] cache key name
97+
# @param opts [Hash] options hash - any unlisted options will be passed to the underlying cache
98+
# @options opts [Boolean] :include_community whether to include the community ID in the cache key
99+
def read_collection(name, **opts)
100+
namespaced = construct_ns_key(name, include_community: include_community(opts))
101+
data = @underlying.read(namespaced, **opts)
102+
type = data.slice!(0)
103+
type.constantize.where(id: data)
104+
end
105+
106+
##
107+
# Fetch an ActiveRecord collection from cache if it is present, otherwise cache the value returned by +block+.
108+
# @param name [String] cache key name
109+
# @param opts [Hash] options hash - any unlisted options will be passed to the underlying cache
110+
# @option opts [Boolean] :include_community whether to include the community ID in the cache key
111+
# @yieldreturn [ActiveRecord::Relation]
112+
def fetch_collection(name, **opts, &block)
113+
if @underlying.exist?(name)
114+
read_collection(name, **opts)
115+
else
116+
unless block_given?
117+
raise ArgumentError, "Can't fetch collection without a block given"
118+
end
119+
data = block.call
120+
write_collection(name, data, **opts)
121+
data
122+
end
123+
end
124+
75125
# We have to statically report that we support cache versioning even though this depends on the underlying class.
76126
# However, this is not really a problem since all cache stores provided by activesupport support the feature and
77127
# we only use the redis cache (by activesupport) for QPixel.

0 commit comments

Comments
 (0)