readme.md in cashier-0.1.0 vs readme.md in cashier-0.2.0

- old
+ new

@@ -4,27 +4,26 @@ ## What Is It? # in your view cache @some_record, :tag => 'some-component' - + # in another view cache @some_releated_record, :tag => 'some-component' # can have multiple tags cache @something, :tag => ['dashboard', 'settings'] # can expire from either tag - # in your sweeper + # in an observer Cashier.expire 'some-component' # don't worry about keys! Much easier to sweep with confidence # in your controller caches_action :tag => 'complicated-action', :cache_path => proc { |c| # huge complicated mess of parameters c.params } - # need to access the controller? caches_action :tag => proc {|c| # c is the controller "users/#{c.current_user.id}/dashboard" } @@ -35,11 +34,11 @@ # what's cached Cashier.tags # sweep all stored keys - Cashier.wipe + Cashier.clear ## How it Came About I work on an application that involves all sorts of caching. I try to use action caching whenever I possible. I had an index action that had maybe ~20 different combination of filters and sorting. If you want to use @@ -47,47 +46,63 @@ to expire the cache. Once you had pagination, then you have even more combinations of possible cache keys. I needed a better solution. I wanted to expire things logically as a viewed them on the page. IE, if a record was added, I wanted to say "expire that page". Problem was that page contained ~1000 different keys. So I needed something to store the keys for me and associate them with tags. That's exactly what cashier does. Cache associate individual cache keys with a tag, then expire them all at once. This took my 7 layer loop -down two one line of code. It's also made managing the cache throught my application much easier. +down to one line of code. It's also made managing the cache throught my application much easier. ## Why Tag Based Caching is Useful - 1. You don't worry about keys. How many times have you created a complicated key for a fragment or action - then messed up when you tried to expire the cache - 2. Associate your cached content into groups of related content. If you have records that are closely associated - or displayed together, then you can tag them and expire them at once. - 3. **Expire cached content from anywhere.** If you've done any serious development, you know that Rails caching - does not work (easily) outside the scope of an HTTP request. If you have background jobs that manipulate data - or potentially invalidate cached data, you know how much of a pain it is to say `expire_fragment` in some random code. - 4. Don't do anything differently! All you have to do is pass `:tag => 'something'` into `cache` (in the view) or `caches_action` - in the controller. +1. You don't worry about keys. How many times have you created a complicated key for a fragment or action +then messed up when you tried to expire the cache +2. Associate your cached content into groups of related content. If you have records that are closely associated +or displayed together, then you can tag them and expire them at once. +3. **Expire cached content from anywhere.** If you've done any serious development, you know that Rails caching +does not work (easily) outside the scope of an HTTP request. If you have background jobs that manipulate data +or potentially invalidate cached data, you know how much of a pain it is to say `expire_fragment` in some random code. +4. Don't do anything differently! All you have to do is pass `:tag => 'something'` into `cache` (in the view) or `caches_action` +in the controller. ## How it Works Cashier hooks into Rails' `expire_fragment` method using `alias_method_chain` to run some code that captures the key -and tag then stores that as a set in redis. Then uses the set members to loop over keys to deleting using `Rails.cache.delete` +and tag then stores that in the rails cache. **No external processes are +needed. All tag/fragment information is stored in the Rails.cache.** ## Configuration -Cashier needs Redis to function correctly. Create a yaml file. You may call it `config/cashier.yml` +**if you're using Rails 3, there is no configuration.** If you're using +Rails 2, include `Cashier::ControllerHelper` into ApplicationController +like so: - development: localhost:6379 - test: localhost:6379/test + require 'cashier' -Then write a simple initializer to configure Cahiser. Drop this file in in `config/initializers/cashier.rb` + class ApplicationController + include Cashier::ControllerHelper + end - resque_config = YAML.load_file(Raisl.root.join 'config', 'cashiser.yml') - Cashier.redis = resque_config[Rails.env] +## Testing -Now in your `application_controller.rb` file just include the module +I've also included some Rspec Matchers and a cucumber helper for testing +caching. The rspec matchers can be used like this: - class ApplicationController < ActionController::Base - include Cashier::ControllerHelper + describe "get index" do + it "should cache the action" do + get :index + 'some-tag'.should be_cached end + end -Now you're good to go! +Testing w/cucumber is more involved. **Make sure you set perform_caching = true in test.rb** +Then require `cashier/cucumber` to use the matchers in your steps. Here +is an example of a possible step + + Then /the dashboard should be cached/ do + "dashboard".should be_cached + end + +Including `cashier/cucumber` will also wipe the cache before every +scenario. ## Contributing to Cashier * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it