activerecord-cached_at 5.2.1.0 → 6.0.0
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 +4 -4
- data/README.md +89 -6
- data/lib/cached_at/base.rb +26 -4
- data/lib/cached_at/connection_adapters/abstract/schema_definitions.rb +2 -4
- data/lib/cached_at/connection_adapters/abstract/schema_statements.rb +1 -1
- data/lib/cached_at/helpers.rb +31 -7
- data/lib/cached_at/timestamp.rb +1 -1
- data/lib/cached_at/version.rb +1 -1
- metadata +8 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0d9e3d63dbd18d8baab8017ad304e44f55b73ebe42060e0723438b252dc4cfe
|
4
|
+
data.tar.gz: 1c6cbb926a39f8c2cabe19a44d918e063df2f6278d443ea3d13ffae37b28e608
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bfafa9a17b95d329a28b0b7b3cc2c570b5cb206b9e9ab51a653f263b971fa59e5d56b4ecc87db02c1a0a526e98ff2ef3012ccc49b31b73da3f7c65cec9d7fc5b
|
7
|
+
data.tar.gz: 1311efa1ca1b808d636739c417ceb5561976e9d6565096ba871a51bed9e2faa40110de75a000c48d93e51e63e3022f523cdfd7fb05e956e9a82e734c81c704fa
|
data/README.md
CHANGED
@@ -1,15 +1,16 @@
|
|
1
|
-
# ActiveRecord - CachedAt
|
1
|
+
# ActiveRecord - CachedAt [](https://travis-ci.org/malomalo/activerecord-cached_at)
|
2
2
|
|
3
3
|
This gem causes ActiveRecord to update a `cached_at` column if present, like the
|
4
4
|
`updated_at` column.
|
5
5
|
|
6
6
|
When calculating a `cache_key` for a model it will also consider the `cached_at`
|
7
|
-
column to
|
7
|
+
column to determine the key of a model.
|
8
8
|
|
9
9
|
Any `ActiveRecord::Migration` that calls `timestamps` will include a `cached_at`
|
10
10
|
column.
|
11
11
|
|
12
|
-
|
12
|
+
Call to [`ActiveRecord::Persistence::touch`](https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-touch)
|
13
|
+
will also touch the `cached_at` column.
|
13
14
|
|
14
15
|
## Installation
|
15
16
|
|
@@ -22,12 +23,94 @@ aren't updating the models you can just require the helpers:
|
|
22
23
|
|
23
24
|
gem 'activerecord-cached_at', require: 'cached_at/helpers'
|
24
25
|
|
26
|
+
## Configuration
|
25
27
|
|
28
|
+
By default updates to the `cached_at`, `updated_at`, and `created_at` columns
|
29
|
+
will not trigger and update to the `cached_at` column. You can add aditional
|
30
|
+
fields to ignore:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
class User
|
34
|
+
cached_at ignore: :my_column
|
35
|
+
end
|
36
|
+
|
37
|
+
class Photo
|
38
|
+
cached_at ignore: :column_a, :column_b
|
39
|
+
end
|
40
|
+
```
|
41
|
+
## Relationship Cache Keys
|
42
|
+
|
43
|
+
CachedAt also allows you to keep cache keys for relationships. This allows you
|
44
|
+
to use the record to determine if a cache is valid for a relationship instead
|
45
|
+
of doing another database query.
|
46
|
+
|
47
|
+
For example:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
class User < ActiveRecord::Base
|
51
|
+
has_many :photos
|
52
|
+
end
|
53
|
+
|
54
|
+
class Photo
|
55
|
+
belongs_to :user, cached_at: true
|
56
|
+
end
|
57
|
+
|
58
|
+
bob_ross = User.create(name: 'Bob Ross')
|
59
|
+
# => INSERT INTO "users"
|
60
|
+
# ("name", "cached_at", "updated_at_", "created_at")
|
61
|
+
# VALUES
|
62
|
+
# ("Bob Ross", "2020-07-19 20:22:03", "2020-07-19 20:22:03", "2020-07-19 20:22:03")
|
63
|
+
|
64
|
+
photo = Photo.create(user: bob_ross, file: ...)
|
65
|
+
# =>INSERT INTO "photos" ("user_id", "cached_at", "updated_at_", "created_at") VALUES (1, "Bob Ross", "2020-07-19 20:22:04", "2020-07-19 20:22:04", "2020-07-19 20:22:04")
|
66
|
+
# => UPDATE "users" SET "photos_cached_at" = "2020-07-19 20:22:04" WHERE "users"."id" = 1
|
67
|
+
|
68
|
+
photo.update(file: ...)
|
69
|
+
# =>UPDATE "photos" (..., "cached_at", "updated_at_") VALUES (..., "2020-07-19 20:22:05", "2020-07-19 20:22:05", "2020-07-19 20:22:05")
|
70
|
+
# => UPDATE "users" SET "photos_cached_at" = "2020-07-19 20:22:05" WHERE "users"."id" = 1
|
71
|
+
|
72
|
+
photo.update(user: not_bob_ross)
|
73
|
+
# =>UPDATE "photos" ("user_id", "cached_at", "updated_at_") VALUES (2, "2020-07-19 20:22:06", "2020-07-19 20:22:06", "2020-07-19 20:22:06")
|
74
|
+
# => UPDATE "users" SET "photos_cached_at" = "2020-07-19 20:22:06" WHERE "users"."id" IN (1, 2)
|
75
|
+
|
76
|
+
photo.destroy
|
77
|
+
# => UPDATE "users" SET "photos_cached_at" = "2020-07-19 20:22:07" WHERE "users"."id" = 2
|
78
|
+
# => DELETE FROM "users" WHERE WHERE "users"."id" = 2
|
79
|
+
```
|
80
|
+
|
81
|
+
# Usage
|
82
|
+
|
83
|
+
`cached_at` will automatically be used for determining the cache key in Rails.
|
84
|
+
|
85
|
+
However if you need to calculate the cache key based on relationship cache keys
|
86
|
+
you will need to manually compute the cache key. Examples are below:
|
87
|
+
|
88
|
+
The cache key here is the maxium of the following keys: `cached_at`,
|
89
|
+
`listings_cached_at`, and `photos_cached_at`
|
90
|
+
|
91
|
+
```erb
|
92
|
+
<%= render partial: 'row', collection: @properties, as: :property, cached: Proc.new { |item|
|
93
|
+
[item.cache_key_with_version(:listings, :photos), current_account.id ]
|
94
|
+
} %>
|
95
|
+
|
96
|
+
<% cache @property.cache_key_with_version(:listings, :photos) do %>
|
97
|
+
<b>All the info on this property</b>
|
98
|
+
<%= @property.name %>
|
99
|
+
<% @property.listings.each do |listing| %>
|
100
|
+
<%= listing.info %>
|
101
|
+
<% end %>
|
102
|
+
<% @property.photos.each do |photo| %>
|
103
|
+
<%= image_tag(photo.url) %>
|
104
|
+
<% end %>
|
105
|
+
<% end %>
|
106
|
+
|
107
|
+
```
|
26
108
|
## TODO:
|
27
109
|
|
28
|
-
|
110
|
+
* Document going more than one level with cached_at keys
|
29
111
|
|
112
|
+
* Add a `cache_key` method to the Model class that gets `MAX(cached_at)`
|
30
113
|
|
114
|
+
* change option to cache: true
|
31
115
|
|
32
|
-
|
33
|
-
add cache_association helper
|
116
|
+
* add cache_association helper
|
data/lib/cached_at/base.rb
CHANGED
@@ -13,20 +13,34 @@ module CachedAt
|
|
13
13
|
extend ActiveSupport::Concern
|
14
14
|
|
15
15
|
included do
|
16
|
+
class_attribute :cached_at_settings, default: {ignore: ['cached_at', 'updated_at', 'created_at']}
|
17
|
+
before_save :set_cached_at
|
16
18
|
before_save :update_belongs_to_cached_at_keys
|
17
19
|
before_destroy { update_relations_cached_at(method: :destroy) }
|
18
20
|
|
19
21
|
after_touch { update_relations_cached_at_from_cached_at(method: :touch) }
|
20
|
-
after_save
|
22
|
+
after_save :update_relations_cached_at_from_cached_at
|
23
|
+
end
|
24
|
+
|
25
|
+
class_methods do
|
26
|
+
def cached_at(ignore: [])
|
27
|
+
ignore = [ignore] if !ignore.is_a?(Array)
|
28
|
+
self.cached_at_settings[:ignore].push(*ignore.map(&:to_s))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def touch(*names, time: nil)
|
33
|
+
names.push('cached_at')
|
34
|
+
super(*names, time: time)
|
21
35
|
end
|
22
36
|
|
23
37
|
private
|
24
38
|
|
25
39
|
def update_relations_cached_at_from_cached_at(method: nil)
|
26
|
-
update_relations_cached_at(
|
40
|
+
update_relations_cached_at(
|
27
41
|
timestamp: (self.class.column_names.include?('cached_at') ? cached_at : nil),
|
28
42
|
method: method
|
29
|
-
|
43
|
+
)
|
30
44
|
end
|
31
45
|
|
32
46
|
def update_relations_cached_at(timestamp: nil, method: nil)
|
@@ -49,6 +63,14 @@ module CachedAt
|
|
49
63
|
end
|
50
64
|
end
|
51
65
|
|
66
|
+
def set_cached_at
|
67
|
+
return if !self.class.column_names.include?('cached_at')
|
68
|
+
diff = changes.transform_values(&:first)
|
69
|
+
return if diff.keys.all? { |k| cached_at_settings[:ignore].include?(k) }
|
70
|
+
|
71
|
+
self.cached_at = current_time_from_proper_timezone
|
72
|
+
end
|
73
|
+
|
52
74
|
def update_belongs_to_cached_at_keys
|
53
75
|
self.class.reflect_on_all_associations.each do |reflection|
|
54
76
|
next unless reflection.is_a?(ActiveRecord::Reflection::BelongsToReflection)
|
@@ -64,7 +86,7 @@ module CachedAt
|
|
64
86
|
|
65
87
|
end
|
66
88
|
end
|
67
|
-
|
89
|
+
|
68
90
|
end
|
69
91
|
end
|
70
92
|
|
@@ -2,14 +2,12 @@ module ActiveRecord
|
|
2
2
|
module ConnectionAdapters #:nodoc:
|
3
3
|
|
4
4
|
class TableDefinition
|
5
|
-
def timestamps(
|
6
|
-
options = args.extract_options!
|
7
|
-
|
5
|
+
def timestamps(**options)
|
8
6
|
options[:null] = false if options[:null].nil?
|
9
7
|
|
10
8
|
column(:created_at, :datetime, options)
|
11
9
|
column(:updated_at, :datetime, options)
|
12
|
-
column(:cached_at,
|
10
|
+
column(:cached_at, :datetime, options)
|
13
11
|
end
|
14
12
|
end
|
15
13
|
|
@@ -7,7 +7,7 @@ module ActiveRecord
|
|
7
7
|
|
8
8
|
add_column table_name, :created_at, :datetime, options
|
9
9
|
add_column table_name, :updated_at, :datetime, options
|
10
|
-
add_column table_name, :cached_at,
|
10
|
+
add_column table_name, :cached_at, :datetime, options
|
11
11
|
end
|
12
12
|
|
13
13
|
def remove_timestamps(table_name, options = {})
|
data/lib/cached_at/helpers.rb
CHANGED
@@ -29,16 +29,40 @@ module CachedAt
|
|
29
29
|
|
30
30
|
end
|
31
31
|
|
32
|
-
def cache_key(includes
|
32
|
+
def cache_key(*includes)
|
33
33
|
if includes.nil? || includes.empty?
|
34
|
-
|
34
|
+
if cache_versioning
|
35
|
+
"#{model_name.cache_key}/#{id}"
|
36
|
+
else
|
37
|
+
"#{model_name.cache_key}/#{id}@#{cache_version}"
|
38
|
+
end
|
39
|
+
else
|
40
|
+
digest = Digest::MD5.hexdigest(paramaterize_cache_includes(includes))
|
41
|
+
if cache_versioning
|
42
|
+
"#{model_name.cache_key}/#{id}+#{digest}"
|
43
|
+
else
|
44
|
+
"#{model_name.cache_key}/#{id}+#{digest}@#{cache_version(includes)}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def cache_key_with_version(*includes)
|
50
|
+
if version = cache_version(*includes)
|
51
|
+
"#{cache_key(*includes)}-#{version}"
|
52
|
+
else
|
53
|
+
cache_key(*includes)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def cache_version(*includes)
|
58
|
+
timestamp = if includes.empty?
|
59
|
+
try(:cached_at) || try(:cached_at)
|
35
60
|
else
|
36
61
|
timestamp_keys = ['cached_at'] + self.class.cached_at_columns_for_includes(includes)
|
37
|
-
timestamp =
|
38
|
-
digest ||= Digest::MD5.new()
|
39
|
-
digest << paramaterize_cache_includes(includes)
|
40
|
-
"#{model_name.cache_key}/#{id}+#{digest.hexdigest}@#{timestamp}"
|
62
|
+
timestamp = timestamp_keys.map { |attr| self[attr]&.to_time }.compact.max
|
41
63
|
end
|
64
|
+
|
65
|
+
timestamp.utc.to_s(:usec)
|
42
66
|
end
|
43
67
|
|
44
68
|
# TODO
|
@@ -84,4 +108,4 @@ module CachedAt
|
|
84
108
|
end
|
85
109
|
end
|
86
110
|
|
87
|
-
ActiveRecord::Base.include(CachedAt::Base::Helpers)
|
111
|
+
ActiveRecord::Base.include(CachedAt::Base::Helpers)
|
data/lib/cached_at/timestamp.rb
CHANGED
data/lib/cached_at/version.rb
CHANGED
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-cached_at
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Bracy
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-07-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 5.2.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 5.2.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -153,7 +153,7 @@ homepage: https://github.com/malomalo/activerecord-cached_at
|
|
153
153
|
licenses:
|
154
154
|
- MIT
|
155
155
|
metadata: {}
|
156
|
-
post_install_message:
|
156
|
+
post_install_message:
|
157
157
|
rdoc_options:
|
158
158
|
- "--main"
|
159
159
|
- README.md
|
@@ -170,9 +170,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
170
|
- !ruby/object:Gem::Version
|
171
171
|
version: '0'
|
172
172
|
requirements: []
|
173
|
-
|
174
|
-
|
175
|
-
signing_key:
|
173
|
+
rubygems_version: 3.1.2
|
174
|
+
signing_key:
|
176
175
|
specification_version: 4
|
177
176
|
summary: Allows ActiveRecord and Rails to use a `cached_at` column for the `cache_key`
|
178
177
|
if available
|