Project

ar_cache

0.01
No release in over 3 years
Low commit activity in last 3 years
An modern cacheing library for ActiveRecord inspired by cache-money and second_level_cache.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

>= 6.1, < 7
>= 3, < 4
 Project Readme

ArCache (This is outdated, please see 中文文档)

Test Status Gem Version

ArCache is an modern cacheing library for ActiveRecord inspired by cache-money and second_level_cache.
It works automatically by overridden ActiveRecord related CURD code. When executing standard ActiveRecord query, it will first query the cache, and if there is none in the cache, then query the database and write the result to the cache.

! WARNING: Please read these information before using ArCache.

Features

  • Low impact: If your code strictly comply with the activerecord style, you don’t need to modify any code.(see more details)
  • Read cache: Automatically intercept ActiveRecord queries, then try to fetch data from cache.
  • Write cache: If the query is cacheable and the cached data is not exists, it will be automatically written to the cache after the query.
  • Expire cache: Automatically expire cache after updated/modified data.
  • Iterative cache: The cache version will be updated after table fields or ArCache switch changed.
  • Shared cache: The cache is not only used with ActiveRecord, you can easily use it in other places.(see examples)

Installation

Add this line to your application's Gemfile:

gem 'ar_cache'

And then execute:

bundle install

Post Installation

If is an rails application:

rails generate ar_cache:install

Otherwise copy configuration and migration files to your application.

After that review the migrations then migrate:

rake db:migrate

Usage

ArCache works automatically, so you don’t need to care about how to use the cache, just need to know how to skip and delete the cache.

Skip cache:

  • ArCache#skip_cache, eg:
# All queries in the block will not use the cache.
ArCache.skip_cache { User.find(1) }
  • ActiveRecord::Persistence#reload, eg:
User.find(1).reload
  • ActiveRecord::Relation#reload, eg:
# When reload is called after the associated target has been loaded, the cache will be skipped.
User.where(id: 1).load.reload
  • ActiveRecord::Associations::Association#reload, eg:
# When reload is called after the associated target has been loaded, the cache will be skipped.
user.association(:account).load_target.reload

Delete cache:

  • ArCache::Table, eg:
User.ar_cache_table.delete(id...)
User.first.ar_cache_table.delete(id...)

Configuration

For configuration information, please see configuration file.

Cacheable query

If all the following conditions are met, ArCache will try to read the cache:

  • Use hash as #where parameter.
  • Query condition contains unique index.
  • Condition of unique index is only one array or no array.
  • No call #select or select value is table column.
  • No call #order or order value is table column and only one.
  • No call #limit or value of the unique index isn't array.
  • No call #joins, #left_joins, #skip_query_cache!, #explain, #from, #group, #offset, #lock
  • ...

Cacheable example:

User.find(1) # support primary key cache
User.where(id: [1, 2]) # support multi-value unique index cache
User.where(email: 'foobar@gmail.com') # support sigle-column unique index cache
User.where(name: 'foobar', status: :active) # support multi-column unique index cache
User.includes(:account).where(id: [1, 2]) # support association preload cache
User.first.account # support association reader cach

The association cache support belongs_to and has_one, small amount of complex has_one(scope, through:, as:) don't support, then has_many cache support, please watch to future version.

Cache iteration

The following cases will cause cache iteration:

  • Table field changes.
  • Turn on ArCache or turn off ArCache.
  • Call #upsert_all method.

Notice: After iteration, all existing caches of the table will be expired!

How it works(Work in progress)

ArCache works based on the unique index of the table.

Warning

  • Prohibit the use of #execute update/delete operations!
  • Prohibit use ActiveRecord other underlying methods to directly update/delete data! (You is a fake activerecord user if this code appears)
  • Prohibit skip ActiveRecord directly update/delete data!

If you have to do this, please consider turning off ArCache.

Alternatives

There are some other gems implementations for ActiveRecord cache such as:

However, ArCache has some differences:

  • It don’t depend with ActiveRecord callbacks, so don’t need to deal with dirty cache manually.
  • It cache real database data, so can use it's cache at other places.
  • It can automatically handle cache iteration, so don't need to update cache version manually.
  • It proxy standard ActiveRecord query, so don't need to modify the code and remember the additional api.
  • The new data need to perform a query before the cache will take effect.
  • The cache will not be updated after the data is updated, but the cache will be expired directly.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and the created tag, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/OuYangJinTing/ar_cache. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the ArCache project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.