cache_keeper 0.3.0 → 0.4.1
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/.github/workflows/ci.yml +10 -3
- data/.gitignore +2 -0
- data/.rubocop.yml +122 -0
- data/Gemfile +17 -3
- data/README.md +33 -5
- data/app/models/cache_keeper/cached_method/refreshable.rb +1 -1
- data/app/models/cache_keeper/cached_method.rb +16 -8
- data/bin/rails +6 -6
- data/lib/cache_keeper/configuration.rb +1 -1
- data/lib/cache_keeper/engine.rb +2 -2
- data/lib/cache_keeper/version.rb +1 -1
- data/test/jobs/refresh_job_test.rb +3 -2
- data/test/models/cached_method/refreshable_test.rb +1 -1
- data/test/models/cached_method_test.rb +37 -2
- metadata +3 -3
- data/Gemfile.lock +0 -199
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc9efe0608912e0c97f6f89659ad73e64588e33eb384701afe0c52afb981c568
|
4
|
+
data.tar.gz: 22b645e8a15de837f4d72de70bc64a1d966c9ce96f9ada07a6fb2f7ba6a0d32f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e60f463b994d17a08f047cd00cd7ef7114940cf5458a6c42d25efacf1968d93a01b2b9cbd6c1bad23252a9b357f88cae5909b291b24756a566ebe95efb0cf578
|
7
|
+
data.tar.gz: 25e87146ea75af98f0112aa8ba6acb730d6314962357589e4b8c0a540a728e9e59c2ebecb4764612f1eba375a6ad45069686ad5e3934bec05cbe31781522eee6
|
data/.github/workflows/ci.yml
CHANGED
@@ -4,13 +4,20 @@ jobs:
|
|
4
4
|
tests:
|
5
5
|
strategy:
|
6
6
|
matrix:
|
7
|
-
ruby-version:
|
8
|
-
- "2.7"
|
9
|
-
- "3.0"
|
10
7
|
rails-version:
|
11
8
|
- "6.1"
|
12
9
|
- "7.0"
|
10
|
+
- "7.1"
|
13
11
|
- "main"
|
12
|
+
include:
|
13
|
+
- rails-version: "6.1"
|
14
|
+
ruby-version: "2.5"
|
15
|
+
- rails-version: "7.0"
|
16
|
+
ruby-version: "2.7"
|
17
|
+
- rails-version: "7.1"
|
18
|
+
ruby-version: "2.7"
|
19
|
+
- rails-version: "main"
|
20
|
+
ruby-version: "3.2"
|
14
21
|
|
15
22
|
env:
|
16
23
|
RAILS_VERSION: "${{ matrix.rails-version }}"
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
require:
|
2
|
+
- rubocop-rails
|
3
|
+
- rubocop-performance
|
4
|
+
|
5
|
+
AllCops:
|
6
|
+
Exclude:
|
7
|
+
- '**/db/**/*'
|
8
|
+
- '**/config/**/*'
|
9
|
+
- '**/tmp/**/*'
|
10
|
+
- '**/templates/**/*'
|
11
|
+
- '**/vendor/**/*'
|
12
|
+
- '**/node_modules/**/*'
|
13
|
+
TargetRubyVersion: 3.2.2
|
14
|
+
|
15
|
+
# Relaxed Ruby Style
|
16
|
+
Style/Alias:
|
17
|
+
Enabled: false
|
18
|
+
StyleGuide: https://relaxed.ruby.style/#stylealias
|
19
|
+
|
20
|
+
Style/AsciiComments:
|
21
|
+
Enabled: false
|
22
|
+
StyleGuide: https://relaxed.ruby.style/#styleasciicomments
|
23
|
+
|
24
|
+
Style/BeginBlock:
|
25
|
+
Enabled: false
|
26
|
+
StyleGuide: https://relaxed.ruby.style/#stylebeginblock
|
27
|
+
|
28
|
+
Style/BlockDelimiters:
|
29
|
+
Enabled: false
|
30
|
+
StyleGuide: https://relaxed.ruby.style/#styleblockdelimiters
|
31
|
+
|
32
|
+
Style/Documentation:
|
33
|
+
Enabled: false
|
34
|
+
StyleGuide: https://relaxed.ruby.style/#styledocumentation
|
35
|
+
|
36
|
+
Style/EndBlock:
|
37
|
+
Enabled: false
|
38
|
+
StyleGuide: https://relaxed.ruby.style/#styleendblock
|
39
|
+
|
40
|
+
Style/GuardClause:
|
41
|
+
Enabled: false
|
42
|
+
|
43
|
+
Style/IfUnlessModifier:
|
44
|
+
Enabled: false
|
45
|
+
StyleGuide: https://relaxed.ruby.style/#styleifunlessmodifier
|
46
|
+
|
47
|
+
Style/ModuleFunction:
|
48
|
+
Enabled: false
|
49
|
+
StyleGuide: https://relaxed.ruby.style/#stylemodulefunction
|
50
|
+
|
51
|
+
Style/MultilineBlockChain:
|
52
|
+
Enabled: false
|
53
|
+
StyleGuide: https://relaxed.ruby.style/#stylemultilineblockchain
|
54
|
+
|
55
|
+
Style/NegatedIf:
|
56
|
+
Enabled: false
|
57
|
+
StyleGuide: https://relaxed.ruby.style/#stylenegatedif
|
58
|
+
|
59
|
+
Style/NegatedWhile:
|
60
|
+
Enabled: false
|
61
|
+
StyleGuide: https://relaxed.ruby.style/#stylenegatedwhile
|
62
|
+
|
63
|
+
Style/NumericPredicate:
|
64
|
+
Enabled: false
|
65
|
+
StyleGuide: https://relaxed.ruby.style/#stylenumericpredicate
|
66
|
+
|
67
|
+
Style/PercentLiteralDelimiters:
|
68
|
+
Enabled: false
|
69
|
+
StyleGuide: https://relaxed.ruby.style/#stylepercentliteraldelimiters
|
70
|
+
|
71
|
+
Style/WhileUntilModifier:
|
72
|
+
Enabled: false
|
73
|
+
StyleGuide: https://relaxed.ruby.style/#stylewhileuntilmodifier
|
74
|
+
|
75
|
+
Style/WordArray:
|
76
|
+
Enabled: false
|
77
|
+
StyleGuide: https://relaxed.ruby.style/#stylewordarray
|
78
|
+
|
79
|
+
Lint/AmbiguousRegexpLiteral:
|
80
|
+
Enabled: false
|
81
|
+
StyleGuide: https://relaxed.ruby.style/#lintambiguousregexpliteral
|
82
|
+
|
83
|
+
Lint/AssignmentInCondition:
|
84
|
+
Enabled: false
|
85
|
+
StyleGuide: https://relaxed.ruby.style/#lintassignmentincondition
|
86
|
+
|
87
|
+
Layout/LineLength:
|
88
|
+
Enabled: false
|
89
|
+
|
90
|
+
Metrics:
|
91
|
+
Enabled: false
|
92
|
+
|
93
|
+
# Custom
|
94
|
+
Performance:
|
95
|
+
Exclude:
|
96
|
+
- '**/spec/**/*'
|
97
|
+
|
98
|
+
Style/FrozenStringLiteralComment:
|
99
|
+
Enabled: false
|
100
|
+
|
101
|
+
Style/AndOr:
|
102
|
+
Enabled: true
|
103
|
+
EnforcedStyle: conditionals
|
104
|
+
|
105
|
+
Style/ClassAndModuleChildren:
|
106
|
+
Enabled: false
|
107
|
+
|
108
|
+
Style/HashSyntax:
|
109
|
+
Enabled: false
|
110
|
+
|
111
|
+
Style/MixinGrouping:
|
112
|
+
Enabled: false
|
113
|
+
|
114
|
+
Style/RegexpLiteral:
|
115
|
+
Enabled: false
|
116
|
+
|
117
|
+
Style/StringConcatenation:
|
118
|
+
Enabled: false
|
119
|
+
|
120
|
+
Style/StringLiterals:
|
121
|
+
Enabled: true
|
122
|
+
EnforcedStyle: double_quotes
|
data/Gemfile
CHANGED
@@ -2,8 +2,22 @@ source "https://rubygems.org"
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
|
6
|
-
gem "byebug"
|
5
|
+
rails_version = ENV.fetch("RAILS_VERSION", "7.1")
|
7
6
|
|
8
|
-
|
7
|
+
rails_constraint =
|
8
|
+
if rails_version == "main"
|
9
|
+
{ github: "rails/rails" }
|
10
|
+
else
|
11
|
+
"~> #{rails_version}.0"
|
12
|
+
end
|
13
|
+
|
14
|
+
gem "rails", rails_constraint
|
9
15
|
gem "sqlite3"
|
16
|
+
|
17
|
+
group :debug do
|
18
|
+
gem "byebug"
|
19
|
+
|
20
|
+
gem "rubocop"
|
21
|
+
gem "rubocop-performance"
|
22
|
+
gem "rubocop-rails"
|
23
|
+
end
|
data/README.md
CHANGED
@@ -29,8 +29,22 @@ bundle add cache_keeper
|
|
29
29
|
CacheKeeper provides a `caches` method that will cache the result of the methods you give it:
|
30
30
|
|
31
31
|
```ruby
|
32
|
-
|
33
|
-
caches :
|
32
|
+
class Recording < ApplicationRecord
|
33
|
+
caches :slow_method, :really_slow_method, expires_in: 1.hour
|
34
|
+
caches :incredibly_slow_method, expires_in: 2.hours, must_revalidate: true
|
35
|
+
|
36
|
+
def slow_method
|
37
|
+
...
|
38
|
+
end
|
39
|
+
|
40
|
+
def really_slow_method
|
41
|
+
...
|
42
|
+
end
|
43
|
+
|
44
|
+
def incredibly_slow_method
|
45
|
+
...
|
46
|
+
end
|
47
|
+
end
|
34
48
|
```
|
35
49
|
|
36
50
|
It's automatically available in your ActiveRecord models and in your controllers. You can also use it in any other class by including `CacheKeeper::Caching`.
|
@@ -39,13 +53,27 @@ By default, it will immediately run the method call if it hasn't been cached bef
|
|
39
53
|
|
40
54
|
It's important to note that it will only work with methods that don't take any arguments.
|
41
55
|
|
56
|
+
### Cache key
|
57
|
+
|
58
|
+
CacheKeeper will compose cache keys from the name of the method and the instance's `cache_key` if it's defined or the name of the class otherwise. You can pass a `key` option to customize the cache key if you need it. It accepts [the same values](https://guides.rubyonrails.org/caching_with_rails.html#cache-keys) as `Rails.cache.fetch`, as well as procs or lambdas in case you need access to the instance:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
class NebulaNoodleTwister
|
62
|
+
caches :twist_noodles, :dish_of_the_day, key: ->(method_name) { [:recoding, id, method_name] }
|
63
|
+
caches :synchronize_taste_buds, key: -> { [:recoding, id, :synchronize_taste_buds] }
|
64
|
+
caches :space_soup_simulation, key: :space_soup_simulation
|
65
|
+
|
66
|
+
...
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
42
70
|
### Serialization
|
43
71
|
|
44
72
|
CacheKeeper needs to pass the instance on which the cached method is called along to the refresh job. As any other job argument, ActiveJob requires it to be serializable. ActiveRecord instances are serializable by default, but controllers, POROs and other classes are not. CacheKeeper provides a `serializer` option that will work in most cases:
|
45
73
|
|
46
74
|
```ruby
|
47
|
-
class
|
48
|
-
# Generate a new instance using an empty initializer (
|
75
|
+
class QuantumQuackerator
|
76
|
+
# Generate a new instance using an empty initializer (QuantumQuackerator.new)
|
49
77
|
# Useful for controllers and for POROs with no arguments
|
50
78
|
caches :slow_method, serializer: :new_instance
|
51
79
|
|
@@ -55,7 +83,7 @@ class Example
|
|
55
83
|
end
|
56
84
|
```
|
57
85
|
|
58
|
-
If those options don't work for you, you can always [write custom
|
86
|
+
If those options don't work for you, you can always [write custom serializers](https://guides.rubyonrails.org/active_job_basics.html#serializers) for your classes.
|
59
87
|
|
60
88
|
|
61
89
|
## Configuration
|
@@ -14,11 +14,9 @@ class CacheKeeper::CachedMethod
|
|
14
14
|
:"__#{method_name}__hooked__"
|
15
15
|
end
|
16
16
|
|
17
|
-
def stale?
|
18
|
-
cache_entry.blank? || cache_entry.expired?
|
19
|
-
end
|
20
|
-
|
21
17
|
def call(target)
|
18
|
+
cache_entry = cache_entry(target)
|
19
|
+
|
22
20
|
if cache_entry.blank?
|
23
21
|
refresh target
|
24
22
|
elsif cache_entry.expired?
|
@@ -36,12 +34,22 @@ class CacheKeeper::CachedMethod
|
|
36
34
|
|
37
35
|
private
|
38
36
|
|
39
|
-
def cache_entry
|
40
|
-
Rails.cache.send :read_entry, Rails.cache.send(:normalize_key, cache_key, {})
|
37
|
+
def cache_entry(target)
|
38
|
+
Rails.cache.send :read_entry, Rails.cache.send(:normalize_key, cache_key(target), {})
|
41
39
|
end
|
42
40
|
|
43
|
-
def cache_key
|
44
|
-
[
|
41
|
+
def cache_key(target)
|
42
|
+
if options[:key].is_a?(Proc)
|
43
|
+
if options[:key].arity == 1
|
44
|
+
target.instance_exec(method_name, &options[:key])
|
45
|
+
else
|
46
|
+
target.instance_exec(&options[:key])
|
47
|
+
end
|
48
|
+
elsif options[:key].present?
|
49
|
+
options[:key]
|
50
|
+
else
|
51
|
+
target.respond_to?(:cache_key) ? ["CacheKeeper", target, method_name] : ["CacheKeeper", klass, method_name]
|
52
|
+
end
|
45
53
|
end
|
46
54
|
|
47
55
|
def expires_in
|
data/bin/rails
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
# This command will automatically be run when you run "rails" with Rails gems
|
3
3
|
# installed from the root of your application.
|
4
4
|
|
5
|
-
ENGINE_ROOT = File.expand_path(
|
6
|
-
APP_PATH = File.expand_path(
|
5
|
+
ENGINE_ROOT = File.expand_path("..", __dir__)
|
6
|
+
APP_PATH = File.expand_path("../test/dummy/config/application", __dir__)
|
7
7
|
|
8
8
|
# Set up gems listed in the Gemfile.
|
9
|
-
ENV[
|
10
|
-
require
|
9
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
10
|
+
require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
|
11
11
|
|
12
|
-
require
|
13
|
-
require
|
12
|
+
require "rails/all"
|
13
|
+
require "rails/engine/commands"
|
data/lib/cache_keeper/engine.rb
CHANGED
@@ -7,13 +7,13 @@ module CacheKeeper
|
|
7
7
|
config.cache_keeper = ActiveSupport::OrderedOptions.new
|
8
8
|
config.cache_keeper.queues = ActiveSupport::OrderedOptions.new
|
9
9
|
|
10
|
-
initializer "cache_keeper.active_job_serializer" do
|
10
|
+
initializer "cache_keeper.active_job_serializer" do
|
11
11
|
config.to_prepare do
|
12
12
|
Rails.application.config.active_job.custom_serializers << CacheKeeper::CachedMethodSerializer
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
initializer "cache_keeper.caching_methods" do
|
16
|
+
initializer "cache_keeper.caching_methods" do
|
17
17
|
ActiveSupport.on_load :action_controller do
|
18
18
|
ActionController::Base.send :include, CacheKeeper::Caching
|
19
19
|
end
|
data/lib/cache_keeper/version.rb
CHANGED
@@ -3,11 +3,12 @@ require "test_helper"
|
|
3
3
|
class CacheKeeper::RefreshJobTest < ActiveSupport::TestCase
|
4
4
|
include ActiveJob::TestHelper
|
5
5
|
|
6
|
-
test "
|
6
|
+
test "uses the correct queue" do
|
7
|
+
CacheKeeper.configuration.queues[:refresh] = "refresh"
|
7
8
|
recording = Recording.create(number: 5)
|
8
9
|
cached_method = CacheKeeper.manager.cached_methods.first
|
9
10
|
|
10
|
-
assert_performed_with(queue:
|
11
|
+
assert_performed_with(queue: "refresh") do
|
11
12
|
CacheKeeper::RefreshJob.perform_later cached_method, recording
|
12
13
|
end
|
13
14
|
end
|
@@ -7,7 +7,7 @@ class CacheKeeper::CachedMethod::RefreshableTest < ActiveSupport::TestCase
|
|
7
7
|
recording = Recording.create(number: 5)
|
8
8
|
cached_method = CacheKeeper.manager.cached_methods.first
|
9
9
|
|
10
|
-
assert_enqueued_with(job: CacheKeeper::RefreshJob
|
10
|
+
assert_enqueued_with(job: CacheKeeper::RefreshJob) do
|
11
11
|
cached_method.refresh_later recording
|
12
12
|
end
|
13
13
|
end
|
@@ -2,14 +2,49 @@ require "test_helper"
|
|
2
2
|
|
3
3
|
class CacheKeeper::CachedMethodTest < ActiveSupport::TestCase
|
4
4
|
test "#call caches the result of the original method" do
|
5
|
-
recording = Recording.
|
5
|
+
recording = Recording.create(number: 5)
|
6
6
|
cached_method = manager.handle(Recording, :another_method, expires_in: 1.hour)
|
7
7
|
manager.activate_if_handling(Recording, :another_method)
|
8
8
|
|
9
9
|
result = cached_method.call(recording)
|
10
10
|
|
11
11
|
assert_equal 5, result
|
12
|
-
assert cache_has_key? "CacheKeeper/
|
12
|
+
assert cache_has_key? "CacheKeeper/recordings/#{recording.id}/another_method"
|
13
|
+
end
|
14
|
+
|
15
|
+
test ":key option accepts arrays" do
|
16
|
+
cached_method = manager.handle(Recording, :another_method, key: ["QuantumQuackerator", "dimensional_duckling"])
|
17
|
+
cache_key = cached_method.send :cache_key, Recording.new
|
18
|
+
|
19
|
+
assert_equal ["QuantumQuackerator", "dimensional_duckling"], cache_key
|
20
|
+
end
|
21
|
+
|
22
|
+
test ":key option accepts procs with no arguments" do
|
23
|
+
cached_method = manager.handle(Recording, :another_method, key: proc { 123 })
|
24
|
+
cache_key = cached_method.send :cache_key, Recording.new
|
25
|
+
|
26
|
+
assert_equal 123, cache_key
|
27
|
+
end
|
28
|
+
|
29
|
+
test ":key option accepts procs with an argument" do
|
30
|
+
cached_method = manager.handle(Recording, :another_method, key: proc { |method_name| [method_name, 123] })
|
31
|
+
cache_key = cached_method.send :cache_key, Recording.new
|
32
|
+
|
33
|
+
assert_equal [:another_method, 123], cache_key
|
34
|
+
end
|
35
|
+
|
36
|
+
test ":key option accepts lambdas with no arguments" do
|
37
|
+
cached_method = manager.handle(Recording, :another_method, key: -> { 123 })
|
38
|
+
cache_key = cached_method.send :cache_key, Recording.new
|
39
|
+
|
40
|
+
assert_equal 123, cache_key
|
41
|
+
end
|
42
|
+
|
43
|
+
test ":key option accepts lambdas with an argument" do
|
44
|
+
cached_method = manager.handle(Recording, :another_method, key: ->(method_name) { [method_name, 123] })
|
45
|
+
cache_key = cached_method.send :cache_key, Recording.new
|
46
|
+
|
47
|
+
assert_equal [:another_method, 123], cache_key
|
13
48
|
end
|
14
49
|
|
15
50
|
private
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cache_keeper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Zamuner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-10-
|
11
|
+
date: 2023-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -32,8 +32,8 @@ extra_rdoc_files: []
|
|
32
32
|
files:
|
33
33
|
- ".github/workflows/ci.yml"
|
34
34
|
- ".gitignore"
|
35
|
+
- ".rubocop.yml"
|
35
36
|
- Gemfile
|
36
|
-
- Gemfile.lock
|
37
37
|
- MIT-LICENSE
|
38
38
|
- README.md
|
39
39
|
- app/jobs/cache_keeper/base_job.rb
|
data/Gemfile.lock
DELETED
@@ -1,199 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
cache_keeper (0.3.0)
|
5
|
-
rails (>= 6.1.0)
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
actioncable (7.1.1)
|
11
|
-
actionpack (= 7.1.1)
|
12
|
-
activesupport (= 7.1.1)
|
13
|
-
nio4r (~> 2.0)
|
14
|
-
websocket-driver (>= 0.6.1)
|
15
|
-
zeitwerk (~> 2.6)
|
16
|
-
actionmailbox (7.1.1)
|
17
|
-
actionpack (= 7.1.1)
|
18
|
-
activejob (= 7.1.1)
|
19
|
-
activerecord (= 7.1.1)
|
20
|
-
activestorage (= 7.1.1)
|
21
|
-
activesupport (= 7.1.1)
|
22
|
-
mail (>= 2.7.1)
|
23
|
-
net-imap
|
24
|
-
net-pop
|
25
|
-
net-smtp
|
26
|
-
actionmailer (7.1.1)
|
27
|
-
actionpack (= 7.1.1)
|
28
|
-
actionview (= 7.1.1)
|
29
|
-
activejob (= 7.1.1)
|
30
|
-
activesupport (= 7.1.1)
|
31
|
-
mail (~> 2.5, >= 2.5.4)
|
32
|
-
net-imap
|
33
|
-
net-pop
|
34
|
-
net-smtp
|
35
|
-
rails-dom-testing (~> 2.2)
|
36
|
-
actionpack (7.1.1)
|
37
|
-
actionview (= 7.1.1)
|
38
|
-
activesupport (= 7.1.1)
|
39
|
-
nokogiri (>= 1.8.5)
|
40
|
-
rack (>= 2.2.4)
|
41
|
-
rack-session (>= 1.0.1)
|
42
|
-
rack-test (>= 0.6.3)
|
43
|
-
rails-dom-testing (~> 2.2)
|
44
|
-
rails-html-sanitizer (~> 1.6)
|
45
|
-
actiontext (7.1.1)
|
46
|
-
actionpack (= 7.1.1)
|
47
|
-
activerecord (= 7.1.1)
|
48
|
-
activestorage (= 7.1.1)
|
49
|
-
activesupport (= 7.1.1)
|
50
|
-
globalid (>= 0.6.0)
|
51
|
-
nokogiri (>= 1.8.5)
|
52
|
-
actionview (7.1.1)
|
53
|
-
activesupport (= 7.1.1)
|
54
|
-
builder (~> 3.1)
|
55
|
-
erubi (~> 1.11)
|
56
|
-
rails-dom-testing (~> 2.2)
|
57
|
-
rails-html-sanitizer (~> 1.6)
|
58
|
-
activejob (7.1.1)
|
59
|
-
activesupport (= 7.1.1)
|
60
|
-
globalid (>= 0.3.6)
|
61
|
-
activemodel (7.1.1)
|
62
|
-
activesupport (= 7.1.1)
|
63
|
-
activerecord (7.1.1)
|
64
|
-
activemodel (= 7.1.1)
|
65
|
-
activesupport (= 7.1.1)
|
66
|
-
timeout (>= 0.4.0)
|
67
|
-
activestorage (7.1.1)
|
68
|
-
actionpack (= 7.1.1)
|
69
|
-
activejob (= 7.1.1)
|
70
|
-
activerecord (= 7.1.1)
|
71
|
-
activesupport (= 7.1.1)
|
72
|
-
marcel (~> 1.0)
|
73
|
-
activesupport (7.1.1)
|
74
|
-
base64
|
75
|
-
bigdecimal
|
76
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
77
|
-
connection_pool (>= 2.2.5)
|
78
|
-
drb
|
79
|
-
i18n (>= 1.6, < 2)
|
80
|
-
minitest (>= 5.1)
|
81
|
-
mutex_m
|
82
|
-
tzinfo (~> 2.0)
|
83
|
-
base64 (0.1.1)
|
84
|
-
bigdecimal (3.1.4)
|
85
|
-
builder (3.2.4)
|
86
|
-
byebug (11.1.3)
|
87
|
-
concurrent-ruby (1.2.2)
|
88
|
-
connection_pool (2.4.1)
|
89
|
-
crass (1.0.6)
|
90
|
-
date (3.3.3)
|
91
|
-
drb (2.1.1)
|
92
|
-
ruby2_keywords
|
93
|
-
erubi (1.12.0)
|
94
|
-
globalid (1.2.1)
|
95
|
-
activesupport (>= 6.1)
|
96
|
-
i18n (1.14.1)
|
97
|
-
concurrent-ruby (~> 1.0)
|
98
|
-
io-console (0.6.0)
|
99
|
-
irb (1.8.3)
|
100
|
-
rdoc
|
101
|
-
reline (>= 0.3.8)
|
102
|
-
loofah (2.21.4)
|
103
|
-
crass (~> 1.0.2)
|
104
|
-
nokogiri (>= 1.12.0)
|
105
|
-
mail (2.8.1)
|
106
|
-
mini_mime (>= 0.1.1)
|
107
|
-
net-imap
|
108
|
-
net-pop
|
109
|
-
net-smtp
|
110
|
-
marcel (1.0.2)
|
111
|
-
mini_mime (1.1.5)
|
112
|
-
minitest (5.20.0)
|
113
|
-
mutex_m (0.1.2)
|
114
|
-
net-imap (0.4.2)
|
115
|
-
date
|
116
|
-
net-protocol
|
117
|
-
net-pop (0.1.2)
|
118
|
-
net-protocol
|
119
|
-
net-protocol (0.2.1)
|
120
|
-
timeout
|
121
|
-
net-smtp (0.4.0)
|
122
|
-
net-protocol
|
123
|
-
nio4r (2.5.9)
|
124
|
-
nokogiri (1.15.4-arm64-darwin)
|
125
|
-
racc (~> 1.4)
|
126
|
-
nokogiri (1.15.4-x86_64-linux)
|
127
|
-
racc (~> 1.4)
|
128
|
-
psych (5.1.1.1)
|
129
|
-
stringio
|
130
|
-
racc (1.7.1)
|
131
|
-
rack (3.0.8)
|
132
|
-
rack-session (2.0.0)
|
133
|
-
rack (>= 3.0.0)
|
134
|
-
rack-test (2.1.0)
|
135
|
-
rack (>= 1.3)
|
136
|
-
rackup (2.1.0)
|
137
|
-
rack (>= 3)
|
138
|
-
webrick (~> 1.8)
|
139
|
-
rails (7.1.1)
|
140
|
-
actioncable (= 7.1.1)
|
141
|
-
actionmailbox (= 7.1.1)
|
142
|
-
actionmailer (= 7.1.1)
|
143
|
-
actionpack (= 7.1.1)
|
144
|
-
actiontext (= 7.1.1)
|
145
|
-
actionview (= 7.1.1)
|
146
|
-
activejob (= 7.1.1)
|
147
|
-
activemodel (= 7.1.1)
|
148
|
-
activerecord (= 7.1.1)
|
149
|
-
activestorage (= 7.1.1)
|
150
|
-
activesupport (= 7.1.1)
|
151
|
-
bundler (>= 1.15.0)
|
152
|
-
railties (= 7.1.1)
|
153
|
-
rails-dom-testing (2.2.0)
|
154
|
-
activesupport (>= 5.0.0)
|
155
|
-
minitest
|
156
|
-
nokogiri (>= 1.6)
|
157
|
-
rails-html-sanitizer (1.6.0)
|
158
|
-
loofah (~> 2.21)
|
159
|
-
nokogiri (~> 1.14)
|
160
|
-
railties (7.1.1)
|
161
|
-
actionpack (= 7.1.1)
|
162
|
-
activesupport (= 7.1.1)
|
163
|
-
irb
|
164
|
-
rackup (>= 1.0.0)
|
165
|
-
rake (>= 12.2)
|
166
|
-
thor (~> 1.0, >= 1.2.2)
|
167
|
-
zeitwerk (~> 2.6)
|
168
|
-
rake (13.0.6)
|
169
|
-
rdoc (6.5.0)
|
170
|
-
psych (>= 4.0.0)
|
171
|
-
reline (0.3.9)
|
172
|
-
io-console (~> 0.5)
|
173
|
-
ruby2_keywords (0.0.5)
|
174
|
-
sqlite3 (1.6.7-arm64-darwin)
|
175
|
-
sqlite3 (1.6.7-x86_64-linux)
|
176
|
-
stringio (3.0.8)
|
177
|
-
thor (1.3.0)
|
178
|
-
timeout (0.4.0)
|
179
|
-
tzinfo (2.0.6)
|
180
|
-
concurrent-ruby (~> 1.0)
|
181
|
-
webrick (1.8.1)
|
182
|
-
websocket-driver (0.7.6)
|
183
|
-
websocket-extensions (>= 0.1.0)
|
184
|
-
websocket-extensions (0.1.5)
|
185
|
-
zeitwerk (2.6.12)
|
186
|
-
|
187
|
-
PLATFORMS
|
188
|
-
arm64-darwin-22
|
189
|
-
x86_64-linux
|
190
|
-
|
191
|
-
DEPENDENCIES
|
192
|
-
byebug
|
193
|
-
cache_keeper!
|
194
|
-
rails (>= 6.1)
|
195
|
-
rake
|
196
|
-
sqlite3
|
197
|
-
|
198
|
-
BUNDLED WITH
|
199
|
-
2.4.19
|