memorize 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.textile +75 -0
- data/Rakefile +49 -0
- data/lib/memorize/action.rb +75 -0
- data/lib/memorize/keys.rb +52 -0
- data/lib/memorize.rb +21 -0
- metadata +67 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Roger Leite
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
'Software'), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
17
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
18
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
19
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
20
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
h2. Memorize:
|
2
|
+
|
3
|
+
Allows Rails applications to do and control cache of actions.
|
4
|
+
With Memorize, you can expires your actions, calling a method in your model (or a CustomClass).
|
5
|
+
if you've suffered with Rails _caches_action_ and is tired of trying to expire your cache, Memorize is for you !
|
6
|
+
See below my 'code-explanation':
|
7
|
+
|
8
|
+
<pre>
|
9
|
+
<code>
|
10
|
+
|
11
|
+
class Article < ActiveRecord::Base
|
12
|
+
extend Memorize::Keys
|
13
|
+
[...]
|
14
|
+
end
|
15
|
+
|
16
|
+
class TestController < ApplicationController
|
17
|
+
|
18
|
+
#'classic' case of index, with categories, pagination and format support.
|
19
|
+
memorize_action :index, :key_builder => Article, :params => [:category, :page, :format]
|
20
|
+
|
21
|
+
#case of id, slug ... etc. Accessing a resource with identification.
|
22
|
+
memorize_action :show, :key_builder => Article, :key_param => :slug, :params => [:page, :format]
|
23
|
+
|
24
|
+
#case of 'custom' key, if you want to use a 'home made' solution. (here Memorize don't know how expires)
|
25
|
+
memorize_action :custom, :cache_path => lambda { |controller| "my_key" }
|
26
|
+
|
27
|
+
[...]
|
28
|
+
end
|
29
|
+
|
30
|
+
class ArticleSweeper < ActionController::Caching::Sweeper
|
31
|
+
observe Article
|
32
|
+
def after_save(article)
|
33
|
+
Article.cache_entries(:index).each { |key| Rails.cache.delete(key) }
|
34
|
+
Article.cache_entries(:show, :key => article.slug).each { |key| Rails.cache.delete(key) }
|
35
|
+
|
36
|
+
Rails.cache.delete("my_key") #Memorize does not handle custom keys
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
</pre>
|
41
|
+
</code>
|
42
|
+
|
43
|
+
h2. More
|
44
|
+
|
45
|
+
Memorize is designed to be simple and objetive.
|
46
|
+
Used and tested for *Rails 2.3.x*
|
47
|
+
|
48
|
+
h2. Install
|
49
|
+
|
50
|
+
Just execute:
|
51
|
+
<pre><code> sudo gem install memorize</code></pre>
|
52
|
+
|
53
|
+
And add to your environment.
|
54
|
+
|
55
|
+
*Important*: you can configure Memorize cache_store, adding a _memorize.rb_ to your _config/initializers_. Example:
|
56
|
+
|
57
|
+
<pre>
|
58
|
+
<code>
|
59
|
+
#Some examples to set Memorize cache_store:
|
60
|
+
Memorize.cache_store = Rails.cache
|
61
|
+
#Memorize.cache_store = ActiveSupport::Cache.lookup_store(:memory_store)
|
62
|
+
#Memorize.cache_store = ActiveSupport::Cache.lookup_store(:mem_cache_store, '127.0.0.1:11211')
|
63
|
+
|
64
|
+
#Your models can be 'Keys factories'
|
65
|
+
#ActiveRecord::Base.extend Memorize::Keys
|
66
|
+
</code>
|
67
|
+
</pre>
|
68
|
+
|
69
|
+
h2. Bugs and Feedback
|
70
|
+
|
71
|
+
If you find any issues, use Github issues tracker.
|
72
|
+
|
73
|
+
Copyright (c) 2010 Roger Leite
|
74
|
+
"1up4dev":http://1up4dev.org
|
75
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rubygems/specification'
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
|
6
|
+
GEM = "memorize"
|
7
|
+
GEM_VERSION = "0.1.0"
|
8
|
+
SUMMARY = "Allows Rails applications to do and control cache of actions"
|
9
|
+
AUTHOR = "Roger Leite"
|
10
|
+
EMAIL = "roger.barreto@gmail.com"
|
11
|
+
HOMEPAGE = "http://1up4dev.org"
|
12
|
+
|
13
|
+
spec = Gem::Specification.new do |s|
|
14
|
+
s.name = GEM
|
15
|
+
s.version = GEM_VERSION
|
16
|
+
s.platform = Gem::Platform::RUBY
|
17
|
+
s.summary = SUMMARY
|
18
|
+
s.require_paths = ['lib']
|
19
|
+
s.files = FileList['lib/**/*.rb', '[A-Z]*'].to_a
|
20
|
+
|
21
|
+
s.author = AUTHOR
|
22
|
+
s.email = EMAIL
|
23
|
+
s.homepage = HOMEPAGE
|
24
|
+
end
|
25
|
+
|
26
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
27
|
+
pkg.gem_spec = spec
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Install the gem locally"
|
31
|
+
task :install => [:package] do
|
32
|
+
sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Create a gemspec file"
|
36
|
+
task :make_spec do
|
37
|
+
File.open("#{GEM}.gemspec", "w") do |file|
|
38
|
+
file.puts spec.to_ruby
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
require 'rake/testtask'
|
43
|
+
Rake::TestTask.new(:test) do |test|
|
44
|
+
test.test_files = FileList.new('test/**/test_*.rb') do |list|
|
45
|
+
list.exclude 'test/test_helper.rb'
|
46
|
+
end
|
47
|
+
test.libs << 'test'
|
48
|
+
test.verbose = true
|
49
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Memorize
|
2
|
+
|
3
|
+
# Exemplos de uso:
|
4
|
+
#
|
5
|
+
# class TestController < ApplicationController
|
6
|
+
# memorize_action :index, :key_builder => Article, :params => [:category, :page, :format]
|
7
|
+
# memorize_action :show, :key_builder => Article, :key_param => :slug, :params => [:page, :format]
|
8
|
+
# memorize_action :index, :cache_path => lambda { |controller| "my_key_#{controller.params.to_s}" }
|
9
|
+
# end
|
10
|
+
|
11
|
+
module Action
|
12
|
+
|
13
|
+
def memorize_action(*actions)
|
14
|
+
return unless self.perform_caching
|
15
|
+
options = actions.extract_options!
|
16
|
+
filter_options = { :only => actions, :if => options.delete(:if), :unless => options.delete(:unless) }
|
17
|
+
|
18
|
+
memorize_filter = MemorizeFilter.new(options)
|
19
|
+
around_filter(filter_options) do |controller, action|
|
20
|
+
memorize_filter.filter(controller, action)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class MemorizeFilter #:nodoc:
|
25
|
+
|
26
|
+
def initialize(options)
|
27
|
+
@cache_path = options.delete(:cache_path)
|
28
|
+
@key_builder = options.delete(:key_builder)
|
29
|
+
@key_param = options.delete(:key_param)
|
30
|
+
@key_params = options.delete(:params) || []
|
31
|
+
end
|
32
|
+
|
33
|
+
def filter(controller, action)
|
34
|
+
cache_path = eval_cache_path(controller)
|
35
|
+
cached = before(cache_path, controller)
|
36
|
+
unless cached
|
37
|
+
action.call
|
38
|
+
after(cache_path, controller) if caching_allowed?(controller)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def before(cache_path, controller)
|
43
|
+
if (cache = Memorize.cache_store.read(cache_path))
|
44
|
+
options = {:layout => false, :text => cache}
|
45
|
+
controller.__send__(:render, options)
|
46
|
+
end
|
47
|
+
!!cache
|
48
|
+
end
|
49
|
+
|
50
|
+
def after(cache_path, controller)
|
51
|
+
Memorize.cache_store.write cache_path, controller.response.body
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def eval_cache_path(controller)
|
57
|
+
return @cache_path.call(controller) if @cache_path.respond_to?(:call)
|
58
|
+
unless @key_builder.respond_to?(:cache_key)
|
59
|
+
throw "Invalid 'key_builder' parameter. It should respond to 'cache_key' method."
|
60
|
+
end
|
61
|
+
group = controller.action_name.to_sym
|
62
|
+
key = controller.params[@key_param]
|
63
|
+
params = @key_params.collect { |param| controller.params[param] }
|
64
|
+
@key_builder.cache_key(group, :key => key, :params => params)
|
65
|
+
end
|
66
|
+
|
67
|
+
def caching_allowed?(controller)
|
68
|
+
controller.request.get? && controller.response.status.to_i == 200
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Memorize
|
2
|
+
|
3
|
+
# Memorize padroniza e mantém as entradas associadas a um "grupo" e "key".
|
4
|
+
# Ao extender o Memorize::Keys, os seguintes métodos ficarão disponíveis:
|
5
|
+
#
|
6
|
+
# Model.cache_key(:group_id)
|
7
|
+
# Model.cache_key(:group_id, :key => "key")
|
8
|
+
#
|
9
|
+
# Model.cache_entries(:group_id)
|
10
|
+
# Model.cache_entries(:group_id, :key => "key")
|
11
|
+
module Keys
|
12
|
+
|
13
|
+
def cache_key(group, options = {})
|
14
|
+
param_key = options.delete(:key)
|
15
|
+
group_key = build_group_key(group, param_key)
|
16
|
+
cache_key = build_cache_key(group, param_key, options.delete(:params))
|
17
|
+
update_cache_entry(group_key, cache_key)
|
18
|
+
cache_key
|
19
|
+
end
|
20
|
+
|
21
|
+
def cache_entries(group, options = {})
|
22
|
+
group_key = build_group_key(group, options.delete(:key))
|
23
|
+
Memorize.cache_store.read(group_key) || []
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def update_cache_entry(group_key, cache_key)
|
29
|
+
entries = (Memorize.cache_store.read(group_key) || [])
|
30
|
+
unless entries.include?(cache_key)
|
31
|
+
entries = entries.dup if entries.frozen?
|
32
|
+
entries << cache_key
|
33
|
+
Memorize.cache_store.write(group_key, entries)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def build_cache_key(group, key, *params)
|
38
|
+
cache_key = "#{self.to_s}/#{group.to_s}"
|
39
|
+
cache_key << "/#{key}" if key
|
40
|
+
params = params.flatten.compact
|
41
|
+
cache_key << "/#{params.join("/")}" unless params.blank?
|
42
|
+
cache_key
|
43
|
+
end
|
44
|
+
|
45
|
+
def build_group_key(group, key = nil)
|
46
|
+
group_key = "#{self.to_s}/keys/#{group.to_s}"
|
47
|
+
group_key << "/#{key}" if key
|
48
|
+
group_key
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
data/lib/memorize.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Memorize
|
2
|
+
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def cache_store
|
6
|
+
@cache_store || ActiveSupport::Cache.lookup_store(:memory_store)
|
7
|
+
end
|
8
|
+
|
9
|
+
def cache_store=(cs)
|
10
|
+
@cache_store = cs
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'memorize/keys'
|
18
|
+
require 'memorize/action'
|
19
|
+
|
20
|
+
#add memorize_action to controllers
|
21
|
+
ActionController::Base.extend Memorize::Action
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: memorize
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Roger Leite
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-10-16 00:00:00 -03:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description:
|
22
|
+
email: roger.barreto@gmail.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- lib/memorize/action.rb
|
31
|
+
- lib/memorize/keys.rb
|
32
|
+
- lib/memorize.rb
|
33
|
+
- README.textile
|
34
|
+
- MIT-LICENSE
|
35
|
+
- Rakefile
|
36
|
+
has_rdoc: true
|
37
|
+
homepage: http://1up4dev.org
|
38
|
+
licenses: []
|
39
|
+
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
segments:
|
50
|
+
- 0
|
51
|
+
version: "0"
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
version: "0"
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.3.6
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: Allows Rails applications to do and control cache of actions
|
66
|
+
test_files: []
|
67
|
+
|