cashier 0.2.0 → 0.4.0
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.
- data/.gitignore +3 -42
- data/README.md +183 -0
- data/Rakefile +1 -5
- data/cashier.gemspec +8 -11
- data/lib/cashier.rb +93 -35
- data/lib/cashier/adapters/cache_store.rb +45 -0
- data/lib/cashier/adapters/redis_store.rb +46 -0
- data/lib/cashier/application_controller.rb +28 -0
- data/lib/cashier/matchers.rb +0 -1
- data/lib/cashier/railtie.rb +4 -3
- data/lib/cashier/version.rb +1 -1
- data/spec/{application_controller_spec.rb → controllers/application_controller_spec.rb} +0 -8
- data/spec/{test_app → dummy}/.gitignore +0 -0
- data/spec/{test_app → dummy}/Gemfile +0 -0
- data/spec/{test_app → dummy}/README +0 -0
- data/spec/{test_app → dummy}/Rakefile +0 -0
- data/spec/{test_app → dummy}/app/controllers/application_controller.rb +0 -0
- data/spec/{test_app → dummy}/app/controllers/home_controller.rb +0 -0
- data/spec/{test_app → dummy}/app/helpers/application_helper.rb +0 -0
- data/spec/{test_app → dummy}/app/helpers/home_helper.rb +0 -0
- data/spec/{test_app → dummy}/app/views/home/index.html.erb +0 -0
- data/spec/{test_app → dummy}/app/views/layouts/application.html.erb +0 -0
- data/spec/{test_app → dummy}/config.ru +0 -0
- data/spec/{test_app → dummy}/config/application.rb +0 -4
- data/spec/{test_app → dummy}/config/boot.rb +0 -0
- data/spec/{test_app → dummy}/config/environment.rb +0 -0
- data/spec/{test_app → dummy}/config/environments/development.rb +0 -3
- data/spec/{test_app → dummy}/config/environments/production.rb +0 -3
- data/spec/{test_app → dummy}/config/environments/test.rb +1 -6
- data/spec/{test_app → dummy}/config/initializers/backtrace_silencers.rb +0 -0
- data/spec/{test_app → dummy}/config/initializers/inflections.rb +0 -0
- data/spec/{test_app → dummy}/config/initializers/mime_types.rb +0 -0
- data/spec/{test_app → dummy}/config/initializers/secret_token.rb +0 -0
- data/spec/{test_app → dummy}/config/initializers/session_store.rb +0 -0
- data/spec/{test_app → dummy}/config/locales/en.yml +0 -0
- data/spec/{test_app → dummy}/config/routes.rb +0 -0
- data/spec/{test_app → dummy}/db/seeds.rb +0 -0
- data/spec/{test_app → dummy}/lib/tasks/.gitkeep +0 -0
- data/spec/{test_app → dummy}/public/404.html +0 -0
- data/spec/{test_app → dummy}/public/422.html +0 -0
- data/spec/{test_app → dummy}/public/500.html +0 -0
- data/spec/{test_app → dummy}/public/favicon.ico +0 -0
- data/spec/{test_app → dummy}/public/images/rails.png +0 -0
- data/spec/{test_app → dummy}/public/javascripts/application.js +0 -0
- data/spec/{test_app → dummy}/public/javascripts/controls.js +0 -0
- data/spec/{test_app → dummy}/public/javascripts/dragdrop.js +0 -0
- data/spec/{test_app → dummy}/public/javascripts/effects.js +0 -0
- data/spec/{test_app → dummy}/public/javascripts/prototype.js +0 -0
- data/spec/{test_app → dummy}/public/javascripts/rails.js +0 -0
- data/spec/{test_app → dummy}/public/robots.txt +0 -0
- data/spec/{test_app → dummy}/public/stylesheets/.gitkeep +0 -0
- data/spec/{test_app → dummy}/script/rails +0 -0
- data/spec/{test_app → dummy}/test/performance/browsing_test.rb +0 -0
- data/spec/{test_app → dummy}/test/test_helper.rb +0 -0
- data/spec/{test_app → dummy}/vendor/plugins/.gitkeep +0 -0
- data/spec/lib/adapters/cache_store_spec.rb +75 -0
- data/spec/lib/adapters/redis_store_spec.rb +89 -0
- data/spec/lib/cashier_spec.rb +112 -0
- data/spec/spec_helper.rb +34 -8
- metadata +179 -214
- data/..gemspec +0 -21
- data/.infinity_test +0 -19
- data/.rvmrc +0 -1
- data/Gemfile.lock +0 -118
- data/lib/cashier/controller_helper.rb +0 -34
- data/readme.md +0 -120
- data/spec/cashier_spec.rb +0 -89
- data/spec/test_app/Gemfile.lock +0 -73
- data/spec/test_app/config/database.yml +0 -22
@@ -0,0 +1,45 @@
|
|
1
|
+
module Cashier
|
2
|
+
module Adapters
|
3
|
+
class CacheStore
|
4
|
+
def self.store_fragment_in_tag(fragment, tag)
|
5
|
+
fragments = Rails.cache.fetch(tag) || []
|
6
|
+
new_fragments = fragments + [fragment]
|
7
|
+
Rails.cache.write(tag, new_fragments)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.store_tags(tags)
|
11
|
+
cashier_tags = Rails.cache.fetch(Cashier::CACHE_KEY) || []
|
12
|
+
cashier_tags = (cashier_tags + tags).uniq
|
13
|
+
|
14
|
+
Rails.cache.write(Cashier::CACHE_KEY, cashier_tags)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.remove_tags(tags)
|
18
|
+
cashier_tags = Rails.cache.fetch(Cashier::CACHE_KEY) || []
|
19
|
+
cashier_tags = (cashier_tags - tags).uniq
|
20
|
+
Rails.cache.write(Cashier::CACHE_KEY, cashier_tags)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.tags
|
24
|
+
Rails.cache.read(Cashier::CACHE_KEY) || []
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.get_fragments_for_tag(tag)
|
28
|
+
Rails.cache.read(tag) || []
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.delete_tag(tag)
|
32
|
+
Rails.cache.delete(tag)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.clear
|
36
|
+
remove_tags(tags)
|
37
|
+
Rails.cache.delete(Cashier::CACHE_KEY)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.keys
|
41
|
+
tags.inject([]) { |arry, tag| arry += Rails.cache.fetch(tag) }.compact
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Cashier
|
2
|
+
module Adapters
|
3
|
+
class RedisStore
|
4
|
+
def self.redis
|
5
|
+
@@redis
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.redis=(redis_instance)
|
9
|
+
@@redis = redis_instance
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.store_fragment_in_tag(fragment, tag)
|
13
|
+
redis.sadd(tag, fragment)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.store_tags(tags)
|
17
|
+
tags.each { |tag| redis.sadd(Cashier::CACHE_KEY, tag) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.remove_tags(tags)
|
21
|
+
tags.each { |tag| redis.srem(Cashier::CACHE_KEY, tag) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.tags
|
25
|
+
redis.smembers(Cashier::CACHE_KEY) || []
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.get_fragments_for_tag(tag)
|
29
|
+
redis.smembers(tag) || []
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.delete_tag(tag)
|
33
|
+
redis.del(tag)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.clear
|
37
|
+
remove_tags(tags)
|
38
|
+
redis.del(Cashier::CACHE_KEY)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.keys
|
42
|
+
tags.inject([]) { |arry, tag| arry += get_fragments_for_tag(tag) }.compact
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Hooks into ApplicationController's write_fragment method.
|
2
|
+
# write_fragment is used for action and fragment caching.
|
3
|
+
# Create an alias method chain to call our customer method
|
4
|
+
# which stores the associated key with the tag in a
|
5
|
+
# Redis Set. Then we can expire all those keys from anywhere
|
6
|
+
# in the code using Rails.cache.delete
|
7
|
+
#
|
8
|
+
# I use alias_method_chain instead of calling 'super'
|
9
|
+
# because there is a very rare case where someone
|
10
|
+
# may have redfined 'write_fragment' in their own
|
11
|
+
# controllers. Using an alias method chain
|
12
|
+
# keeps those methods intact.
|
13
|
+
|
14
|
+
class ApplicationController < ActionController::Base
|
15
|
+
def write_fragment_with_tagged_key(key, content, options = nil)
|
16
|
+
if options && options[:tag] && Cashier.perform_caching?
|
17
|
+
tags = case options[:tag].class.to_s
|
18
|
+
when 'Proc', 'Lambda'
|
19
|
+
options[:tag].call(self)
|
20
|
+
else
|
21
|
+
options[:tag]
|
22
|
+
end
|
23
|
+
Cashier.store_fragment fragment_cache_key(key), *tags
|
24
|
+
end
|
25
|
+
write_fragment_without_tagged_key(key, content, options)
|
26
|
+
end
|
27
|
+
alias_method_chain :write_fragment, :tagged_key
|
28
|
+
end
|
data/lib/cashier/matchers.rb
CHANGED
data/lib/cashier/railtie.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
module Cashier
|
2
2
|
class Railtie < Rails::Railtie
|
3
3
|
initializer 'cashier.initialize' do
|
4
|
-
|
4
|
+
ActiveSupport.on_load(:action_controller) do
|
5
|
+
require 'cashier/application_controller'
|
6
|
+
end
|
5
7
|
end
|
6
8
|
end
|
7
|
-
end
|
8
|
-
|
9
|
+
end
|
data/lib/cashier/version.rb
CHANGED
@@ -1,14 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
require 'rspec/rails'
|
4
|
-
|
5
|
-
class ApplicationController
|
6
|
-
include Cashier::ControllerHelper
|
7
|
-
end
|
8
|
-
|
9
3
|
describe ApplicationController do
|
10
|
-
include Rspec::Rails::ControllerExampleGroup
|
11
|
-
|
12
4
|
it "should be able to tag framgents" do
|
13
5
|
Cashier.should_receive(:store_fragment).with('views/key', 'tag')
|
14
6
|
controller.write_fragment('key', 'content', :tag => 'tag')
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -1,10 +1,6 @@
|
|
1
1
|
require File.expand_path('../boot', __FILE__)
|
2
2
|
|
3
|
-
require "active_model/railtie"
|
4
|
-
require "active_record/railtie"
|
5
3
|
require "action_controller/railtie"
|
6
|
-
require "action_view/railtie"
|
7
|
-
require "action_mailer/railtie"
|
8
4
|
|
9
5
|
# If you have a Gemfile, require the gems listed there, including any gems
|
10
6
|
# you've limited to :test, :development, or :production.
|
File without changes
|
File without changes
|
@@ -14,9 +14,6 @@ TestApp::Application.configure do
|
|
14
14
|
config.action_view.debug_rjs = true
|
15
15
|
config.action_controller.perform_caching = true
|
16
16
|
|
17
|
-
# Don't care if the mailer can't send
|
18
|
-
config.action_mailer.raise_delivery_errors = false
|
19
|
-
|
20
17
|
# Print deprecation notices to the Rails logger
|
21
18
|
config.active_support.deprecation = :log
|
22
19
|
|
@@ -34,9 +34,6 @@ TestApp::Application.configure do
|
|
34
34
|
# Enable serving of images, stylesheets, and javascripts from an asset server
|
35
35
|
# config.action_controller.asset_host = "http://assets.example.com"
|
36
36
|
|
37
|
-
# Disable delivery errors, bad email addresses will be ignored
|
38
|
-
# config.action_mailer.raise_delivery_errors = false
|
39
|
-
|
40
37
|
# Enable threaded mode
|
41
38
|
# config.threadsafe!
|
42
39
|
|
@@ -13,7 +13,7 @@ TestApp::Application.configure do
|
|
13
13
|
# Show full error reports and disable caching
|
14
14
|
config.consider_all_requests_local = true
|
15
15
|
config.action_controller.perform_caching = true
|
16
|
-
config.cache_store = :
|
16
|
+
config.cache_store = :dalli_store
|
17
17
|
|
18
18
|
# Raise exceptions instead of rendering exception templates
|
19
19
|
config.action_dispatch.show_exceptions = false
|
@@ -21,11 +21,6 @@ TestApp::Application.configure do
|
|
21
21
|
# Disable request forgery protection in test environment
|
22
22
|
config.action_controller.allow_forgery_protection = false
|
23
23
|
|
24
|
-
# Tell Action Mailer not to deliver emails to the real world.
|
25
|
-
# The :test delivery method accumulates sent emails in the
|
26
|
-
# ActionMailer::Base.deliveries array.
|
27
|
-
config.action_mailer.delivery_method = :test
|
28
|
-
|
29
24
|
# Use SQL instead of Active Record's schema dumper when creating the test database.
|
30
25
|
# This is necessary if your schema can't be completely dumped by the schema dumper,
|
31
26
|
# like if you have constraints or database-specific column types
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cashier::Adapters::CacheStore do
|
4
|
+
subject { Cashier::Adapters::CacheStore }
|
5
|
+
let(:cache) { Rails.cache }
|
6
|
+
|
7
|
+
it "should store the fragment in a tag" do
|
8
|
+
subject.store_fragment_in_tag('fragment-key', 'dashboard')
|
9
|
+
cache.fetch('dashboard').should eql(['fragment-key'])
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should store the tag in the tags array" do
|
13
|
+
subject.store_tags(["dashboard"])
|
14
|
+
cache.fetch(Cashier::CACHE_KEY).should eql(['dashboard'])
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return all of the fragments for a given tag" do
|
18
|
+
subject.store_fragment_in_tag('fragment-key', 'dashboard')
|
19
|
+
subject.store_fragment_in_tag('fragment-key-2', 'dashboard')
|
20
|
+
subject.store_fragment_in_tag('fragment-key-3', 'dashboard')
|
21
|
+
|
22
|
+
subject.get_fragments_for_tag('dashboard').length.should == 3
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should delete a tag from the cache" do
|
26
|
+
subject.store_fragment_in_tag('fragment-key', 'dashboard')
|
27
|
+
Rails.cache.read('dashboard').should_not be_nil
|
28
|
+
|
29
|
+
subject.delete_tag('dashboard')
|
30
|
+
Rails.cache.read('dashboard').should be_nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return the list of tags" do
|
34
|
+
(1..5).each {|i| subject.store_tags(["tag-#{i}"])}
|
35
|
+
subject.tags.length.should == 5
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return the tags correctly" do
|
39
|
+
subject.store_tags(["tag-1", "tag-2", "tag-3"])
|
40
|
+
subject.tags.include?("tag-1").should be_true
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should remove tags from the tags list" do
|
44
|
+
(1..5).each {|i| subject.store_tags(["tag-#{i}"])}
|
45
|
+
subject.remove_tags(["tag-1", "tag-2", "tag-3", "tag-4", "tag-5"])
|
46
|
+
subject.tags.length.should == 0
|
47
|
+
end
|
48
|
+
|
49
|
+
context "clear" do
|
50
|
+
before(:each) do
|
51
|
+
subject.store_tags(['dashboard'])
|
52
|
+
subject.store_tags(['settings'])
|
53
|
+
subject.store_tags(['email'])
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should clear the cache and remove all of the tags" do
|
57
|
+
subject.should_receive(:remove_tags).with(['dashboard','settings','email'])
|
58
|
+
subject.clear
|
59
|
+
Rails.cache.read(Cashier::CACHE_KEY).should be_nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "keys" do
|
64
|
+
it "should return the list of keys" do
|
65
|
+
|
66
|
+
subject.store_tags(['dashboard', 'settings', 'email'])
|
67
|
+
|
68
|
+
subject.store_fragment_in_tag('key1', 'dashboard')
|
69
|
+
subject.store_fragment_in_tag('key2', 'settings')
|
70
|
+
subject.store_fragment_in_tag('key3', 'email')
|
71
|
+
|
72
|
+
subject.keys.should eql(%w(key1 key2 key3))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cashier::Adapters::RedisStore do
|
4
|
+
subject { Cashier::Adapters::RedisStore }
|
5
|
+
let(:cache) { Rails.cache }
|
6
|
+
let(:redis) { subject.redis }
|
7
|
+
|
8
|
+
context "setting and getting the redis instance" do
|
9
|
+
it "should allow to set the redis instance" do
|
10
|
+
subject.respond_to?(:redis=).should be_true
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should allow to get the redis instance" do
|
14
|
+
subject.respond_to?(:redis).should be_true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should return the redis instance you set" do
|
19
|
+
subject.redis = redis
|
20
|
+
subject.redis.should == redis
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should store the fragment in a tag" do
|
24
|
+
subject.store_fragment_in_tag('fragment-key', 'dashboard')
|
25
|
+
redis.smembers('dashboard').should eql(['fragment-key'])
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should store the tag in the tags array" do
|
29
|
+
subject.store_tags(["dashboard"])
|
30
|
+
redis.smembers(Cashier::CACHE_KEY).should eql(['dashboard'])
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return all of the fragments for a given tag" do
|
34
|
+
subject.store_fragment_in_tag('fragment-key', 'dashboard')
|
35
|
+
subject.store_fragment_in_tag('fragment-key-2', 'dashboard')
|
36
|
+
subject.store_fragment_in_tag('fragment-key-3', 'dashboard')
|
37
|
+
|
38
|
+
subject.get_fragments_for_tag('dashboard').length.should == 3
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should delete a tag from the cache" do
|
42
|
+
subject.store_fragment_in_tag('fragment-key', 'dashboard')
|
43
|
+
redis.smembers('dashboard').should_not be_nil
|
44
|
+
|
45
|
+
subject.delete_tag('dashboard')
|
46
|
+
redis.exists('dashboard').should be_false
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should return the list of tags" do
|
50
|
+
(1..5).each {|i| subject.store_tags(["tag-#{i}"])}
|
51
|
+
subject.tags.length.should == 5
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should return the tags correctly" do
|
55
|
+
subject.store_tags(["tag-1", "tag-2", "tag-3"])
|
56
|
+
subject.tags.include?("tag-1").should be_true
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should remove tags from the tags list" do
|
60
|
+
(1..5).each {|i| subject.store_tags(["tag-#{i}"])}
|
61
|
+
subject.remove_tags(["tag-1", "tag-2", "tag-3", "tag-4", "tag-5"])
|
62
|
+
subject.tags.length.should == 0
|
63
|
+
end
|
64
|
+
|
65
|
+
context "clear" do
|
66
|
+
before(:each) do
|
67
|
+
subject.store_tags(['dashboard'])
|
68
|
+
subject.store_tags(['settings'])
|
69
|
+
subject.store_tags(['email'])
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should clear the cache and remove all of the tags" do
|
73
|
+
subject.clear
|
74
|
+
redis.smembers(Cashier::CACHE_KEY).should eql([])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "keys" do
|
79
|
+
it "should return the list of keys" do
|
80
|
+
subject.store_tags(['dashboard', 'settings', 'email'])
|
81
|
+
|
82
|
+
subject.store_fragment_in_tag('key1', 'dashboard')
|
83
|
+
subject.store_fragment_in_tag('key2', 'settings')
|
84
|
+
subject.store_fragment_in_tag('key3', 'email')
|
85
|
+
|
86
|
+
subject.keys.sort.should eql(%w(key1 key2 key3))
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|