Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/igorkasyanchuk/rails_cached_method
Simple way to cache results of methods.
https://github.com/igorkasyanchuk/rails_cached_method
caching rails
Last synced: 17 days ago
JSON representation
Simple way to cache results of methods.
- Host: GitHub
- URL: https://github.com/igorkasyanchuk/rails_cached_method
- Owner: igorkasyanchuk
- License: mit
- Created: 2021-06-22T19:16:34.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2022-05-21T18:02:05.000Z (over 2 years ago)
- Last Synced: 2024-12-31T04:23:53.344Z (28 days ago)
- Topics: caching, rails
- Language: Ruby
- Homepage: https://www.railsjazz.com/
- Size: 426 KB
- Stars: 11
- Watchers: 3
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: MIT-LICENSE
Awesome Lists containing this project
README
# Rails Cached Method
[![RailsJazz](https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/my_other.svg?raw=true)](https://www.railsjazz.com)
[![https://www.patreon.com/igorkasyanchuk](https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/patron.svg?raw=true)](https://www.patreon.com/igorkasyanchuk)Simple way to cache results of methods. Using `Rails.cache` inside with default expiration time of 1 minute.
![Demo](docs/rails_cached_method.png)
## Usage
To get a value and cache it just write a code like:
```ruby
User.cached.admins # get list of admins and automatically put them in cache with 1 minute TTL
post.cached.comments.last # get last comment from the post and cache it
User.cached.where(role: :moderator).count # cache moderators count
Project.cached.first.some_heavey_method # cache result of some_heavey_method for first Project (if first is Project.first)
```So basically just call method `cached` on any object. It will wrap and cache **every** result from the next method call. So every result from method chain is cached.
For example:
```ruby
post.cached.comments.first # A
post.cached.comments.last # B
```Here `post.cached.comments` will return same collection.
You don't need to specify a key, because it's dynamically set based on object, arguments, etc.
Options:
```ruby
cached(key: nil, expires_in: 1.minute, recache: false)
```key - you can set your key.
expires_in - TTL of cached object.
recache - should be key deleted and cached again.## Tips & Tricks
1) use `if page.present?` to check if value is really present. Because every value is wrapped in a class if statement can work incorrectly
```ruby
page = Page.cached.find_by(identifier: identifier)
return page if page # change to return page if page.present?
page = Page.new(identifier: identifier, title: identifier)
page.save(validate: false)
page
```
2) Rails.cache.clear in specs before(:suite) or concrete spec## How it works
After you call `.cached` it will generate a cache key and store value in Rails.cache. Value is class which is wrapps original value and allow you to call methods on the value using `method_missing`. Every result is cached again and again. So on every method call in methods chain every result will be stored in Rails.cache.
To get original value you can call `.__value__`.
Some pieces of code to show you how it works:
```ruby
def cached(key: nil, expires_in: 1.minute, recache: false)
CachedProxy.new(
self,
key: key,
expires_in: expires_in,
recache: recache
)
end
# ---------------------------------------------------------------
class CachedProxyObject.methods.each do |e|
delegate e, to: :@__object__
end
def method_missing(*args)
key = ___compose_key__(args)
if @__recache__
Rails.cache.delete(key)
end
Rails.cache.fetch(key, expires_in: @__expires_in__) do
CachedProxy.new(
@__object__.send(*args),
expires_in: @__expires_in__,
recache: @__recache__,
parent_key: key,
)
end
end
private
def ___compose_key__(args)
result = [@__parent_key__, @__key__]
result += if @__object__.respond_to?(:to_global_id)
[@__object__.to_global_id]
elsif @__object__.is_a?(ActiveRecord::Relation)
[@__object__.class]
else
[@__object__]
end
result += args[0..1]
result.compact.map(&:to_s).join('.').dasherize
end
```## Installation
Add this line to your application's Gemfile:```ruby
gem 'rails_cached_method'
```And then execute:
```bash
$ bundle
```Or install it yourself as:
```bash
$ gem install rails_cached_method
```## TODO
- think if rails dependency could be replaced with something more lightweight
## Contributing
Contribution directions go here.## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).[](https://www.railsjazz.com/?utm_source=github&utm_medium=bottom&utm_campaign=rails_cached_method)