在Rails中,扫描程序不会在仅模型设置中调用

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)

希望这将有助于其他人在路上.再说一次,如果你在我的工作代码中看到我应该做的事情不同的地方,请告诉我.如果您在我的工作代码中看到一些可以更严格的内容,请告诉我.

  • 所以我在上面的所有工作都在我的开发服务器上工作.然而,当我在生产服务器上尝试它时,它就破了.我尝试了许多替代方法,但它们都没有真正起作用.最后,我重写了应用程序的那一部分,因此它从控制器运行页面到期.似乎现在正在工作. (2认同)

小智 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)