The document discusses various caching techniques in Rails including page caching, action caching, and fragment caching. Page caching allows entire pages to be served from cache without processing by the Rails app. Action caching caches specific actions. Fragment caching caches fragments of views for dynamic parts of pages. The document also covers Memcached for distributed caching across multiple app instances.
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Caching/Expiring in Rails
1. Caching
With
Rails
By
Carmen
Diaz
Echauri
–
cdechauri@gmail.com
For
www.blazingcloud.net
Rails
version
2.3.8
2. Caching
with
Rails
Scaling
your
ApplicaFons
• Rails
provides
by
default
three
techniques:
–
Page
Caching
–
AcFon
Caching
– Fragment
Caching
3. Page
Caching
• Allows
the
request
for
a
generated
page
to
be
fulfilled
by
the
webserver,
without
ever
having
to
go
through
your
Rails
applicaFon.
Client
Apache
Mongrel
Public/users.html
hOp://localhost:3000/users
4. Page
Caching
Next
Fme
we
request
the
same
page,
apache
will
load
the
page
from
the
filesystem
and
send
it
back
to
the
client.
Client
Apache
Mongrel
Public/users.html
hOp://localhost:3000/users
5. When
we
might
want
to
page
cached?
• When
every
user
always
sees
exactly
the
same
content
on
a
page,
even
if
they
are
login
to
the
admin
interface
or
not.
But
It's
always
the
same.
• It
doesn't
change
so
oWen.
Maybe
once
per
day,
week
or
month.
6. Get
started
with
caching….
• Make
sure
config.acFon_controller.perform_caching
is
set
to
true
for
your
environment.
(config/
environments/development.rb)
config.acFon_controller.perform_caching
=
true
10. Page
caching
• Page
caching
ignores
all
parameters
– hOp://localhost:3000/users?page=1
Will
be
wriOen
out
so
if
someone
request
hOp://localhost:3000/users?page=3
it
will
be
gegng
users.html.
11. AcFon
Caching
• Caching
stored
– Page
Caching
• Stored
on
Disk
– AcFon
&
Fragment
Caching
• Use
the
configured
cache
that
we
configure
in
our
rails
instance.
12. When
to
do
AcFon
Caching?
• When
we
need
filters
to
run
– Like
authenFcaFon
Client
Apache
Mongrel
Public/posts.html
hOp://localhost:3000/posts
Run
Filters
(authenFcate)
14. AcFon
Caching
Didn’t
call
the
acFon.
It
loaded
straight
out
of
the
cache
It
executed
the
acFon
15. AcFon
Caching
OpFons
/config/environments/development.rb
• config.cache_store
=
:file_store,
'tmp/cache’
(AcFveSupport::Cache::FileStore)
• config.cache_store
=
:memory_store
(AcFveSupport::Cache::MemoryStore)
– {}
in
memory
–background-‐.
But
you
can
run
out
of
memory
– No
sharing
between
processes.
You
cannot
use
it
if
you
run
more
than
one
instance
of
your
rails
apps.
17. AcFon
Caching
• Features
– Cached
the
acFon
without
the
layout.
it
will
only
cache
your
acFon
content.
So,
if
you
need
some
sort
of
data
you
might
want
to
use
before_filter
and
set
you
instance
variable
18.
19. AcFon
Caching
• Features
(cont)
• CondiFonal
AcFon
acFon
using
:if
(or
:unless)
=>
Proc.new{….}
to
specify
when
the
acFon
should
be
cached.
• Specific
path
using
:cache_path
=>
Proc.new
{
|controller|
or
:cache_path
=>
<method>
:expires_in
=>1.hour
to
specify
when
the
acFon
should
be
cached.
(only
with
memcached
&
rails
>
2.1)
20. Fragment
Caching
• Is
useful
for
dynamic
web
applicaFons
• Allows
you
to
fragment
many
pieces
of
the
view.
The
pieces
will
be
wrapped
in
a
cache
block
and
served
out
of
the
cache
store
when
the
next
request
comes
in.
Client
Apache
Mongrel
header
hOp://localhost:3000/users
body
widgets
21. Fragment
Caching
To
implement
fragment
caching,
you
cache
your
method
in
the
view.
All
keys
are
prefixed
with
"views/"
22. Fragment
Caching
You
can
create
your
own
key:
<%
cache("#{@user.id}-‐recents_joined")
do
%>
or
use
the
rails
way
<%
cache([user,
post,
“toolbar”])
do
%>
23. Memcached
• Is
a
hash
in
memory,
key-‐value
store
{}
in
memory
(LiveJournal)
– To
implement
/config/environments/producFon.rb
config.cache_store
=
:mem_cache_store
Same
thing
as
config.cache_store
=
:memory_store
but
it
runs
as
a
separate
process.
You
can
have
several
rails
instances
that
references
the
same
mencached
instance
-‐
Note:
make
sure
to
install
the
gem
memcached-‐client.
24. Memcached
uses
• Fragment
Cache
Store
• AcFon
&
Fragment
Caching
25. Memcached
uses
• As
an
Object
Store
– Rails.cache.read
– Rails.cache.write
– Rails.cache.fetch
– Rails.cache.delete
– Rails.cache.exists?
– Rails.cache.clear
– Rails.cache.increment
– Rails.cache.clear
27. Memcached
….
Some
points:
-‐
Expire
at
def
self.recent
Rails.cache.fetch("recent_posts",
:expires_in
=>
30.minutes)
do
self.find(:all,
:limit
=>
10)
end
end
Run
this
query
every
30
minutes…
-‐
You
don’t
need
to
have
memcached
installed
to
develop
locally
You
will
get
MemCacheError
(No
connecFon
to
server):
No
connecFon
to
server
Cache
miss:
But,
your
app
will
work
just
fine.
Rails
will
always
execute
the
contents
of
the
fetch
blocks,
and
will
return
nil
for
any
reads.
28. Expiring
cached
pages
One’s
first
inclinaFon
may
be
to
expire
pages
in
the
Controller
and
usually
via
the
update
method.
Depending
on
which
technique
you
choose
to
expire
pages
you
can
use
the
method
expire_page
{acFon,fragment}
Instead
of
having
expire
methods
around
your
controllers,
to
clear
cache
files
based
on
when
a
model
is
updated,
sweepers
are
the
way
to
go.
29. Expiring
cached
page
AcFonController::Caching::Sweeper
class.
(Share
Objects)
– Can
observe
Controllers
– Can
observe
Models
Hooks:
Any
observer
callbacks
aWer
create
aWer
destroy
aWer_save,
etc.
Also
in
any
controllers
callbacks
• before/aWer_<controller_name>
• before/aWer_<controller_name>_<acFon>
30. Expiring
cached
page
To
implement
sweepers:
Declare
a
new
load
path
in
/config/environment.rb
to
keep
the
sweepers
separate
from
models
and
controllers.
config.load_paths
<<
"#{RAILS_ROOT}/app/sweepers”
Create
the
folder
and
the
observer
files
31. Expiring
cached
page
And
then
we
will
tell
the
controller
to
use
the
sweeper
cache_sweeper
:user_sweeper,
:only
=>
[:create,
:update,
:destroy]
When
to
call
the
method
Observe
the
model
33. Another
way
to
expire.
Clearing
the
cache
And
you
could
use
it
in
a
cron
call…
34. Some
thoughts
ImplemenFng
page
caching
can
be
easy.
However,
expiring
can
be
prove
to
be
a
bit
more
challenging
.
• I
find
tesFng
kind
of
tricky.
• I
read
through
numerous
blog
posts
but
I
couldn’t
quite
figure
out
how
to
get
things
to
work
as
I
hoped.
• The
following
are
alternaFves
I’ve
recently
used:
– Custom
Macthers
by
overwriFng
the
matches?
method
• AcFonController::Caching::AcFons
–
Build
your
CachePage
/
Fragment
Page
class
and
use
• AcFonController::Base.expire_page(
)
• AcFonController::Caching::Fragments
– expire_fragment
– fragment_cache_key
– fragment_exist?
– read_fragment
– write_fragment