StaleOptions
A gem for caching HTTP responses.
The gem was built with an idea to implement a class which will create options for ActionController::ConditionalGet#stale? method. It allows to cache any kind of object, not only record or collection (unlike of #stale?).
Installation
Add this line to your application's Gemfile:
gem 'stale_options'
And then execute:
bundle
Or install it yourself as:
gem install stale_options
Usage
There are three main classes, each class is designed to create options for the corresponding object class:
StaleOptions::ArrayOptions- For caching Arrays.StaleOptions::RelationOptions- For caching relationsActiveRecord::Relation.StaleOptions::ObjectOptions- For caching any other objects.
There is also base class StaleOptions::AbstractOptions. Constructor of these classes looks like:
def initialize(record, = {})
...
end
record- Basically any Ruby object. Arrays and relations are "specials".options-Hash. Caching options (see detailed description in corresponding section).
Here is the very basic example of usage:
[1] pry(main)> = StaleOptions::RelationOptions.new(Item.all)
[2] pry(main)> .to_h
=> {:etag=>"39f08c583b023142dd64b0922dfaefd4", :last_modified=>2018-07-04 18:05:22 UTC}
In order to help create different classes of StaleOptions for different objects there is method StaleOptions.create, so above example can be rewritten like:
[3] pry(main)> StaleOptions.create(Item.all)
=> {:etag=>"39f08c583b023142dd64b0922dfaefd4", :last_modified=>2018-07-04 18:05:22 UTC}
And this is the way how you'll use it in most cases :)
Caching options
There are two options for caching:
:cache_byStringorSymbol. A name of method which returns unique identifier of object for caching.- For arrays and relations if value is
itself, then it will be cached "as it is" (relations will be converted to arrays by calling#to_a), otherwise this method will be called on each element. Hint: To cache arrays of "simple" objects (e.g.StringorNumeric) set it toitself. - Default:
:updated_at.
:last_modifiedStringorSymbol. A name of method which returns an instance ofActiveSupport::TimeWithZone,DateTime,Time.- If
recordis a relation, then an attribute name. - If
recordis anArrayorObject, then a method name. ActiveSupport::TimeWithZone,DateTime,Timeornilto set:last_modified.- Default:
:updated_at.
Examples
[1] pry(main)> StaleOptions.create(Task.all, last_modified: :done_at)
=> {:etag=>"ce8d2fbc9b815937b59e8815d8a85c21", :last_modified=>2018-06-30 18:25:07 UTC}
[2] pry(main)> StaleOptions.create([1, 2, 3], cache_by: :itself, last_modified: nil)
=> {:etag=>"73250e72da5d8950b6bbb16044353d26", :last_modified=>nil}
[3] pry(main)> StaleOptions.create({ a: 'a', b: 'b', c: 'c' }, cache_by: :itself, last_modified: Time.now)
=> {:etag=>"fec76eca1192bc7371e44d517b56c93f", :last_modified=>2018-07-08 07:08:48 UTC}
Controller helpers
In your controller:
# To render a template:
class PostsController < ApplicationController
include StaleOptions::Backend
def index
if_stale?(Post.all) do |posts|
@posts = posts
end
end
end
# Or, to render json:
class PostsController < ApplicationController
include StaleOptions::Backend
def index
if_stale?(Post.all) do |posts|
render json: posts
end
end
end
Here we're using method #if_stale? (there is also #unless_stale? btw) which was added to controller by including StaleOptions::Backend module. The method accepts two arguments record and options (yeah, just like StaleOptions.create).
Under the hood it calls ActionController::ConditionalGet#stale? with options created by StaleOptions.create:
def if_stale?(record, = {})
yield(record) if stale?(StaleOptions.create(record, ))
end
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/digaev/stale_options.
License
The gem is available as open source under the terms of the MIT License.