active_cached_resource 0.1.10 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: afcd141833ea0ddb9bd49c2c6d8381647070bb826908af33a0a4bdb9af9b0baa
4
- data.tar.gz: cf5579fb46a2076f86c635e048cf8dcfeb0ae18aae932e59eca73d82576c8c0e
3
+ metadata.gz: ff5568ae59b708a8797b4a76940222c5b6e6203ae6914fcefcccae0b6fd4702e
4
+ data.tar.gz: 810e8446382d26728299806a427f865de4fbda34de6704ceb3a231163b471c0a
5
5
  SHA512:
6
- metadata.gz: dd2750852a436d259d3e7574ec0719b23e6ddf7c24813d3d641abc89931e48396940113a19d61ff963d8fe3c414fc3a4de987a9189c4d40762a7e69d42e1c981
7
- data.tar.gz: c7776d28e660fd88807412f8b48a500ead60865b713387974ac94441152d9fdbe16ee3616441a37e42eac7c3cb864ce97ad716bf8863191c18f491d081a1eb81
6
+ metadata.gz: 9c4e5b58ec0e1e9151c51e62e6760dd408098b68a01c634ca0ef62e2f999a6bb5c2d2a4961db0563a3d3a3490f9dcd6934c76a12e940233fd212a78fa6d34df4
7
+ data.tar.gz: b5d37c1863e51ef8aec7db5afebabe35a25d0aae60453a48ba61212f9348aea1dda4a1c43f0c00a5d80008d30170988bbf826eecc4e7fc74b7a5d978b63be67f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [0.2.0] - 2024-04-24
2
+ - Allow virtual attributes to be persisted into cache with introduction of `ActiveCachedResource::Collection.persisted_attribute`.
3
+ - Optimized cache key generation by switching from `SHA-256` to `MD5`, improving hashing performance while maintaining uniqueness.
4
+
5
+ ## [0.1.10] - 2024-03-05
6
+ - Patch Collection#reload to return correct type
7
+
1
8
  ## [0.1.9] - 2024-02-05
2
9
  - Fixed bug not allowing reloading collection cache
3
10
  - Change debug to info for cache hits
@@ -40,9 +40,10 @@ module ActiveCachedResource
40
40
  # @option options [Hash] :params
41
41
  # Query and prefix (nested URL) parameters.
42
42
  #
43
- # @return [Object, Array<Object>, nil]
43
+ # @return [ActiveCachedResource::Collection, ActiveCachedResource::Resource, nil]
44
+ # Returns the requested resource(s) based on the scope:
44
45
  # * Returns a single resource object if `:one`, `:first`, `:last`, or an ID is given.
45
- # * Returns an array of resources if `:all` is given.
46
+ # * Returns an ActiveCachedResource::Collection containing the resources if `:all` is given.
46
47
  # * Returns `nil` if no data is found for `:one`, `:first`, `:last`, or `:all` queries.
47
48
  #
48
49
  # @raise [ResourceNotFound]
@@ -148,7 +149,7 @@ module ActiveCachedResource
148
149
  #
149
150
  # @return [void]
150
151
  def clear_cache
151
- cached_resource.logger.info("Clearing cache for #{name} cache with prefix: #{cache_key_prefix}")
152
+ cached_resource.logger.debug("Clearing cache for #{name} cache with prefix: #{cache_key_prefix}")
152
153
  cached_resource.cache.clear(cache_key_prefix)
153
154
  end
154
155
 
@@ -166,7 +167,7 @@ module ActiveCachedResource
166
167
 
167
168
  return nil if json_string.nil?
168
169
 
169
- cached_resource.logger.info("[KEY:#{key}] Cache hit")
170
+ cached_resource.logger.debug("[KEY:#{key}] Cache hit")
170
171
  json_to_object(json_string)
171
172
  end
172
173
 
@@ -242,11 +243,17 @@ module ActiveCachedResource
242
243
 
243
244
  case resource
244
245
  when Array
245
- resource.map do |attrs|
246
+ elements = resource.map do |attrs|
246
247
  new(attrs["object"], attrs["persistence"]).tap do |r|
247
248
  r.prefix_options = object["prefix_options"]
248
249
  end
249
250
  end
251
+ object["collection_parser"].constantize.new(elements, object["from"]).tap do |parser|
252
+ parser.resource_class = self
253
+ parser.query_params = object["query_params"] || {}
254
+ parser.prefix_options = object["prefix_options"] || {}
255
+ parser.path_params = object["path_params"] || {}
256
+ end
250
257
  else
251
258
  new(resource["object"], resource["persistence"]).tap do |r|
252
259
  r.prefix_options = object["prefix_options"]
@@ -258,13 +265,16 @@ module ActiveCachedResource
258
265
  options = extract_options(*)
259
266
  params = options.fetch(:params, {})
260
267
  prefix_options, query_options = split_options(params)
261
- json_object = if object.is_a? Enumerable
262
- {
268
+ json_object = case object
269
+ when ActiveCachedResource::Collection
270
+ object.virtual_persistable_attributes.merge({
263
271
  resource: object.map { |o| {object: o, persistence: o.persisted?} },
264
- prefix_options: prefix_options,
272
+ collection_parser: object.class.name,
273
+ from: object.from,
265
274
  path_params: params,
275
+ prefix_options: prefix_options,
266
276
  query_params: query_options
267
- }
277
+ })
268
278
  else
269
279
  {
270
280
  resource: {object: object, persistence: object.persisted?},
@@ -120,7 +120,7 @@ module ActiveCachedResource
120
120
  if prefix.nil? || k.nil?
121
121
  raise ArgumentError, "Key must have a prefix and a key separated by a dash"
122
122
  end
123
- "#{prefix}#{ActiveCachedResource::Constants::PREFIX_SEPARATOR}#{Digest::SHA256.hexdigest(k)}"
123
+ "#{prefix}#{ActiveCachedResource::Constants::PREFIX_SEPARATOR}#{Digest::MD5.hexdigest(k)}"
124
124
  end
125
125
 
126
126
  def compress(value)
@@ -1,10 +1,27 @@
1
1
  module ActiveCachedResource
2
2
  class Collection < ActiveResource::Collection
3
- # Reload the collection by re-fetching the resources from the API.
3
+ class_attribute :virtual_persisted_attributes, default: []
4
+
5
+ # This method dynamically creates accessor methods for the specified attributes
6
+ # and adds them to a list of virtual persisted attributes to keep track of
7
+ # attributes that should be persisted to cache.
4
8
  #
5
- # ==== Returns
9
+ # @param args [Array<Symbol>] A list of attribute names to be persisted.
10
+ # @return [void]
11
+ def self.persisted_attribute(*args)
12
+ attr_accessor(*args)
13
+ self.virtual_persisted_attributes += args
14
+ end
15
+
16
+ def virtual_persistable_attributes
17
+ self.class.virtual_persisted_attributes.each_with_object({}) do |attribute, hash|
18
+ hash[attribute] = public_send(attribute)
19
+ end
20
+ end
21
+
22
+ # Reload the collection by re-fetching the resources from the API.
6
23
  #
7
- # [Array<Object>] The collection of resources retrieved from the API.
24
+ # @return Returns [Array<Object>] The collection of resources retrieved from the API.
8
25
  def reload
9
26
  query_params[Constants::RELOAD_PARAM] = true
10
27
  super
@@ -20,19 +37,34 @@ module ActiveCachedResource
20
37
  should_reload = query_params.delete(Constants::RELOAD_PARAM)
21
38
  if !should_reload
22
39
  from_cache = resource_class.send(:cache_read, from, path_params, query_params, prefix_options)
23
- @elements = from_cache
24
- return @elements if @elements
40
+ if from_cache
41
+ update_self!(from_cache)
42
+ return @elements if @elements
43
+ end
25
44
  end
26
45
 
27
46
  super # This sets @elements
28
47
 
29
48
  if resource_class.send(:should_cache?, @elements)
30
- resource_class.send(:cache_write, @elements, from, path_params, query_params, prefix_options)
49
+ resource_class.send(:cache_write, self, from, path_params, query_params, prefix_options)
31
50
  end
32
51
 
33
52
  @elements
34
53
  ensure
35
54
  @requested = true
36
55
  end
56
+
57
+ def update_self!(other_collection)
58
+ # Ensure that the virtual persisted attributes are also updated
59
+ self.class.virtual_persisted_attributes.each do |attribute|
60
+ public_send(:"#{attribute}=", other_collection.public_send(attribute))
61
+ end
62
+
63
+ @elements = other_collection.instance_variable_get(:@elements)
64
+ @from = other_collection.instance_variable_get(:@from)
65
+ @query_params = other_collection.query_params
66
+ @path_params = other_collection.path_params
67
+ @prefix_options = other_collection.prefix_options
68
+ end
37
69
  end
38
70
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveCachedResource
4
- VERSION = "0.1.10"
4
+ VERSION = "0.2.2"
5
5
  end
@@ -4,7 +4,7 @@ module ActiveResource::Associations::Builder
4
4
  class Association # :nodoc:
5
5
  # providing a Class-Variable, which will have a different store of subclasses
6
6
  class_attribute :valid_options
7
- self.valid_options = [:class_name]
7
+ self.valid_options = [:class_name, :foreign_key]
8
8
 
9
9
  # would identify subclasses of association
10
10
  class_attribute :macro
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pry-byebug" # IGNORE: This line is for debugging purposes and should be removed in production code.
3
4
  module ActiveResource::Associations
4
5
  module Builder
5
- autoload :Association, "active_resource/associations/builder/association"
6
- autoload :HasMany, "active_resource/associations/builder/has_many"
7
- autoload :HasOne, "active_resource/associations/builder/has_one"
8
- autoload :BelongsTo, "active_resource/associations/builder/belongs_to"
6
+ autoload :Association, "activeresource/lib/active_resource/associations/builder/association"
7
+ autoload :HasMany, "activeresource/lib/active_resource/associations/builder/has_many"
8
+ autoload :HasOne, "activeresource/lib/active_resource/associations/builder/has_one"
9
+ autoload :BelongsTo, "activeresource/lib/active_resource/associations/builder/belongs_to"
9
10
  end
10
11
 
11
12
 
@@ -148,9 +149,11 @@ module ActiveResource::Associations
148
149
  elsif attributes.include?(method_name)
149
150
  attributes[method_name]
150
151
  elsif !new_record?
151
- instance_variable_set(ivar_name, reflection.klass.find(:all, params: { "#{self.class.element_name}_id": self.id }))
152
+ # Association would be set on custom primary key if explicitly defined, otherwise use convention _id
153
+ assoc_key = self.class.custom_primary_key || "#{self.class.element_name}_id"
154
+ instance_variable_set(ivar_name, reflection.klass.find(:all, params: { assoc_key => self.id }))
152
155
  else
153
- instance_variable_set(ivar_name, reflection.klass.find(:all))
156
+ instance_variable_set(ivar_name, reflection.klass.none)
154
157
  end
155
158
  end
156
159
  end
@@ -672,6 +672,10 @@ module ActiveResource
672
672
  end
673
673
  end
674
674
 
675
+ def none
676
+ collection_parser.none
677
+ end
678
+
675
679
  # An instance of ActiveResource::Connection that is the base \connection to the remote service.
676
680
  # The +refresh+ parameter toggles whether or not the \connection is refreshed at every request
677
681
  # or not (defaults to <tt>false</tt>).
@@ -717,6 +721,10 @@ module ActiveResource
717
721
 
718
722
  attr_writer :primary_key
719
723
 
724
+ def custom_primary_key
725
+ @primary_key
726
+ end
727
+
720
728
  def primary_key
721
729
  if defined?(@primary_key)
722
730
  @primary_key
@@ -1226,6 +1234,10 @@ module ActiveResource
1226
1234
  load(attributes, false, persisted)
1227
1235
  end
1228
1236
 
1237
+ def [](key)
1238
+ public_send(key)
1239
+ end
1240
+
1229
1241
  # Returns a \clone of the resource that hasn't been assigned an +id+ yet and
1230
1242
  # is treated as a \new resource.
1231
1243
  #
@@ -6,12 +6,12 @@ require "active_support/inflector"
6
6
  module ActiveResource # :nodoc:
7
7
  class Collection # :nodoc:
8
8
  include Enumerable
9
- delegate :==, :[], :&, :*, :+, :-, :<=>, :all?, :any?, :as_json, :at, :assoc, :blank?, :bsearch, :bsearch_index,
10
- :collect, :combination, :compact, :count, :cycle, :deconstruct, :deep_dup, :dig, :difference, :drop,
9
+ delegate :==, :[], :&, :*, :+, :-, :<=>, :<<, :all?, :any?, :as_json, :at, :assoc, :blank?, :bsearch, :bsearch_index,
10
+ :collect, :combination, :compact, :concat, :count, :cycle, :deconstruct, :deep_dup, :dig, :difference, :drop,
11
11
  :drop_while, :each, :each_index, :empty?, :eql?, :excluding, :filter, :fifth, :find_index, :first,
12
- :flatten, :forty_two, :fourth, :from, :hash, :include?, :including, :index, :inspect, :intersect?,
12
+ :flatten, :fourth, :hash, :include?, :including, :index, :inspect, :intersect?,
13
13
  :intersection, :join, :last, :length, :map, :max, :min, :minmax, :none?, :one?, :pack, :permutation,
14
- :pretty_print_cycle, :present?, :product, :reject, :repeated_combination, :repeated_permutation,
14
+ :pretty_print_cycle, :present?, :product, :push, :reject, :repeated_combination, :repeated_permutation,
15
15
  :rassoc, :reverse, :reverse_each, :rindex, :rotate, :sample, :second, :second_to_last, :select,
16
16
  :shelljoin, :shuffle, :size, :slice, :sort, :sum, :take, :take_while, :third, :third_to_last, :to,
17
17
  :to_a, :to_ary, :to_fs, :to_formatted_s, :to_h, :to_param, :to_query, :to_s, :to_sentence, :to_xml,
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_cached_resource
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.10
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean Luis Urena
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-03-05 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: activemodel-serializers-xml
@@ -136,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
136
  - !ruby/object:Gem::Version
137
137
  version: '0'
138
138
  requirements: []
139
- rubygems_version: 3.6.5
139
+ rubygems_version: 3.7.0
140
140
  specification_version: 4
141
141
  summary: ActiveResource, but with a caching layer.
142
142
  test_files: []