cha*_*ark 10 model ruby-on-rails sweeper observer-pattern
我正在开发一个Rails应用程序,我正在使用页面缓存来存储静态html输出.缓存工作正常.但是,我无法使缓存过期.
我相信我的问题部分是因为我没有从控制器到缓存.所有必要的操作都在模型中处理.这看起来应该是可行的,但我发现的所有对基于模型的缓存过期的引用似乎已经过时,或者在其他方面都不起作用.
在我的environment.rb文件中,我正在调用
config.load_paths += %W( #{RAILS_ROOT}/app/sweepers )
Run Code Online (Sandbox Code Playgroud)
我在/ sweepers文件夹中有一个LinkSweeper文件:
class LinkSweeper < ActionController::Caching::Sweeper
observe Link
def after_update(link)
clear_links_cache(link)
end
def clear_links_cache(link)
# expire_page :controller => 'links', :action => 'show', :md5 => link.md5
expire_page '/l/'+ link.md5 + '.html'
end
end
Run Code Online (Sandbox Code Playgroud)
那么...... 为什么在更新模型时不删除缓存页面?(进程:使用脚本/控制台,我从数据库中选择项目并保存它们,但是它们的相应页面没有从缓存中删除),我也在调用通常会调用的链接模型中的特定方法扫地机.两者都不起作用.
如果重要,则缓存文件是Links表中键值的md5哈希值.缓存页面存储为/l/45ed4aade64d427...99919cba2bd90f.html.
从本质上讲,似乎扫地机实际上并没有观察到链路.我还读到(这里)可能只是简单地将sweeper添加到environment.rb中的config.active_record.observers,但这似乎没有做到(我不确定app/sweepers的load_path)在environment.rb中避免了).
cha*_*ark 11
所以我尝试了许多不同的方法,看看哪些有效,哪些无效.
再次,总结一下情况:我的目标是在对象更新时使缓存页面失效,但是在不依赖于Controller操作的情况下使它们过期.传统的扫地机使用控制器中的一条线来通知扫地机它需要运行.在这种情况下,我不能在控制器中使用一行,因为更新发生在模型中.普通清扫器教程不起作用,因为它们假设您与数据库对象的主要交互是通过控制器.
如果您在阅读本文时看到了收紧我的代码的方法,请发表评论并告诉我们.
首先,让我们看一下那些有用的东西,如果你也坚持这一点,并需要帮助.
在我尝试的所有事情中,唯一真正起作用的是在Observer中为模型声明一个after_update命令.在该命令中,我对expire_page操作使用了显式命令,并包含了在routes.rb中声明的路径.
所以.这有效:
在config/routes.rb中:
map.link 'l/:md5.:format', :controller => 'links', :action => 'show'
Run Code Online (Sandbox Code Playgroud)
在app/models/link_observer.rb中:
def after_update(link)
ActionController::Base.expire_page(app.link_path(:md5 => link.md5))
end
Run Code Online (Sandbox Code Playgroud)
请注意,"md5"特定于我的应用.您可能希望使用:id或其他一些唯一标识符.
我还发现声明ActionController :: Base ...行来自正在进行更新的模型中的方法.也就是说,在Link.rb中,在实际更新数据库的方法中,如果我只是将整行插入,它就可以了.但是,由于我可能希望将来在其他方法上使该页缓存失效,我宁愿将其提取到Observer中.
现在,让我们看一些不起作用的事情,以防你在谷歌上搜索.
在link_observer.rb中的after_update(link)方法中调用"expire_page(...)"不起作用,因为它返回了"未定义的方法`expire_page'"错误
创建一个观察模型的Sweeper文件不起作用.我找不到任何错误代码,但它似乎甚至没有意识到它有工作要做.这是在environment.rb中明确调用"config.load_paths + =%W(#{RAILS_ROOT}/app/sweepers)"之后.为了防止我在该代码中发现了一些东西,这里是:
class LinkSweeper < ActionController::Caching::Sweeper
observe Link
def after_update(link)
clear_links_cache(link)
end
def clear_links_cache(link)
# DID NOT WORK expire_page :controller => 'links', :action => 'show', :md5 => link.md5
# DID NOT WORK expire_page '/l/'+ link.md5 + '.html'
# DID NOT WORK ActionController::Base.expire_page(app.link_path(:md5 => link.md5))
end
end
Run Code Online (Sandbox Code Playgroud)
上面的示例在目录/ app/sweepers中有link_sweeper.rb文件.我还尝试将link_sweeper.rb放在app/models目录中,并尝试使用environment.rb中的config.active_record.observers命令调用它:
config.active_record.observers = :link_observer, :link_sweeper
Run Code Online (Sandbox Code Playgroud)
但这也行不通.
是的.这些方法中的一种很有可能会起作用,而且我在代码中弄乱了一些东西.但我想我已经按照这本书做了一切.
最后,总结一下:您希望在模型的Observer中设置after_回调,而不是使用Sweeper来过期页面缓存.您将要使用Base.expire_page方法的显式路径:
def after_update(<model>) # where <model> is the name of the model you're observing
ActionController::Base.expire_page(app.<model>_path(:id => <model>.id)) # where <model> is the name of the model you're observing
end
Run Code Online (Sandbox Code Playgroud)
希望这将有助于其他人在路上.再说一次,如果你在我的工作代码中看到我应该做的事情不同的地方,请告诉我.如果您在我的工作代码中看到一些可以更严格的内容,请告诉我.
小智 5
只需注意:您可以cache_sweeper在ApplicationController中使用.
class ApplicationController < ActionController::Base
cache_sweeper :my_sweeper
end
class MySweeper < ActionController::Caching::Sweeper
observe MyModel
def after_update(my_model)
expire_page(...)
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6189 次 |
| 最近记录: |