Hey all
I''ve released the second version of the CacheFilter plugin.
I''ve made many improvements and fixed at least one serious issue. One
big enhancement is the availability of the controller''s methods when
deciding which cached version to serve the request.
The readme is included below:
CacheFilter
==========
The Cache Filter plugin allows you to keep multiple cached versions of
an action''s template and judge which to serve using a special
''judge''
method in your controller.
== Getting the plugin
ruby script/plugin install svn://rubyforge.org/var/svn/cache-filter
== Usage
First you need to include the CacheFilter mixin in the controllers you
want to use if. Alternatively you can include it in
ApplicationController and make it available across all your controllers
(most common).
class ApplicationController < ActionController::Base
include CacheFilter
#other code
end
The plugin adds the cache_filter method to your controllers. The
cache_filter method takes one or more action names and an optional block
as parameters. The cache_filter method requires that there be a method
called ''judge_cache'' in either your ApplicationController or
the current
controller.
An example follows:
class WelcomeController < ApplicationController
cache_filter :index, :faq
def index
end
def faq
@faqs = Faq.find_for_main_faq
end
private
def judge_cache(cache)
if session[:member_id]
cache.as :logged_in
else
cache.as :not_logged_in
end
end
end
Internally, the cache_filter method is an around_filter which gets
prepended to the list so that action_cache (also an around_filter)
doesn''t execute before the cache_filter block has had a chance to tell
it which version to serve.
Since in the above example the ''index'' and
''faq'' actions are already
included in the cache_filter method, there is no need to further pass
them to caches_action. After all, cache_filter makes internal use of
action_cache and even calls it explicitly on the any actions it gets passed!
Inside the judge_cache method you have full access to your
ApplicationController (and current controller) methods!
(Thanks Chris [http://errtheblog.com])
In the example, we check for a value in the current controller''s
session, which can be read and changed along with the flash and other
controller methods as mentioned above.
I mentioned that cache_filter takes an optional block as parameter. If
this is the case, you don''t need a judge_cache method in that
controller
(it will be ignored by the cache_filter method). The block exposes a
object through which the controller''s methods can be accessed.
For example:
#######in application.rb
include CacheFilter
def method_residing_in_application_dot_rb
false
end
#######
#######in for example welcome_controller.rb
cache_filter :action_one, :action_two do |cache|
if cache.method_residing_in_application_dot_rb
cache.as :foo
elsif cache.method_in_current_controller
cache.as :bar
end
#note that if both are false, it won''t cache the request at all!
end
private
def method_in_current_controller
false
end
#######
Here''s some further examples:
class ApplicationController < ActionController::Base
include CacheFilter
def is_admin?
admin_role = Role.find_by_title("Admin")
Member.find(cache.session[:member_id]).roles.include?(admin_role)
end
end
class WelcomeController < ApplicationController
cache_filter :index, :faq do | cache |
if cache.is_admin?
cache.as :its_me_admin
elsif cache.session[:member_id]
cache.as :logged_in
else
cache.as :not_logged_in
end
end
def index; end
def faq; end
end
The usage of the judge_cache method is preferred as you don''t need to
call controller methods using the ''cache'' object as a proxy
(which can
lead to violations between internal methods belonging to the cache
object and your own methods), and can simply use them as is to be
expected. If however your judging method is very simple, judging in the
cache_filter block is fine!
class ApplicationController < ActionController::Base
include CacheFilter
def is_admin?
admin_role = Role.find_by_title("Admin")
Member.find(cache.session[:member_id]).roles.include?(admin_role)
end
def logged_in?
session[:member_id]
end
end
class WelcomeController < ApplicationController
cache_filter :index, :faq
def index; end
def faq; end
private
def judge_cache(cache)
if is_admin?
cache.as admin_cache_name
elsif logged_in?
cache.as :logged_in
else
cache.as :not_logged_in
end
end
def admin_cache_name
"its_me_admin"
end
end
== Tom Fakes'' action_cache plugin
Tom Fakes developed an excellent plugin that fixes some bugs in Rails''
action_caching as well as provides some great functionality in the way
of using x-sendfile to serve pages (if installed) and a
''cache_action?(action_name)'' method which you can put in your
controllers that specifies whether or not the action should be rendered
normally or whether the cached page should be rendered.
A concern of mine was whether developers would be able to use my plugin
in conjunction with Tom''s. As such I made sure that if installed, my
cache_filter plugin will fully utilize his.
To make them play nicely, you need to add the following three lines to
the bottom of your environment.rb file:
ActionController::Caching::Actions::ActionCacheFilter.fragment_key Proc.new
{|controller|
ActionCachePluginProxy.get_fragment_key(controller)
}
Tom''s plugin let''s you define where the cached file should be
stored(sound familiar? :] ). The above code uses this idea and delegates
generation of the key to the cache_filter plugin through the use of a
little wrapper class I''ve written specifically to make the two play
nicely!
== Acknowledgments
This plugin was inspired by a thread on the mailing list first posted by
Hendrik Jensen. I replied with an ugly hack I''d used on a project,
which
used Javascript to change certain small parts of the page after it loaded.
It made me realize the fact that its pretty crappy that rails doesn''t
let you have multiple cached versions of a template. It is something I
believed should be in the rails core, so I added it...
I''ve extracted it as a plugin in the meantime. You''ll notice
there
aren''t an abundance of tests included, something I''ll have to
remedy
before applying it as a patch! (the rails tests all passed though and I
haven''t has any issues with it to date...haven''t put it
through rigorous
use though...)
== Finally
I''d really appreciate it if you''d drop me e-mails on anything
functionality you''d like added, bugs, etc! I''m really
passionate about
this project and I believe it fills a substantial gap in rails'' caching
functionality!
Also, for those who were wondering, the tests I ran showed no marked
difference in speed between a cache_filter''ed (cache.as :some_action)
serving of the template and a normal action_cache serving.
Thanks for checking this out!
Hope this helps!
Cheery-o!
Gustav Paul
gustav-PUm+PnBUKx7YkQIYctQFYw@public.gmane.org
Copyright (c) 2006 Gustav Paul, released under the GPL license
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---