Ruby on rails 在Rails中,清扫器不是';在仅限型号的设置中无法调用

Ruby on rails 在Rails中,清扫器不是';在仅限型号的设置中无法调用,ruby-on-rails,model,observer-pattern,sweeper,Ruby On Rails,Model,Observer Pattern,Sweeper,我正在开发一个Rails应用程序,使用页面缓存存储静态html输出。缓存工作正常。不过,我很难让缓存过期 我相信我的问题部分是因为我没有从我的控制器中终止缓存。所有必要的操作都在模型中处理。这似乎是可行的,但我发现所有对基于模型的缓存过期的引用似乎都过时了,或者不起作用 在我的environment.rb文件中,我正在呼叫 config.load_paths += %W( #{RAILS_ROOT}/app/sweepers ) 在/sweeper文件夹中,我有一个LinkSweeper文件:

我正在开发一个Rails应用程序,使用页面缓存存储静态html输出。缓存工作正常。不过,我很难让缓存过期

我相信我的问题部分是因为我没有从我的控制器中终止缓存。所有必要的操作都在模型中处理。这似乎是可行的,但我发现所有对基于模型的缓存过期的引用似乎都过时了,或者不起作用

在我的environment.rb文件中,我正在呼叫

config.load_paths += %W( #{RAILS_ROOT}/app/sweepers )
在/sweeper文件夹中,我有一个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
class-LinkSweeperlinks',:action=>show',:md5=>link.md5
过期页面'/l/'+link.md5+'.html'
结束
结束
所以。。。为什么我更新模型时它不删除缓存页面?(过程:使用脚本/控制台,我从数据库中选择项目并保存它们,但它们对应的页面不会从缓存中删除),我还调用链接模型中通常会调用清理器的特定方法。两者都不起作用

如果重要的话,缓存文件是链接表中键值的md5散列。缓存的页面被存储为类似于/l/45ed4aade64d427…99919cba2bd90f.html的内容


从本质上讲,似乎清扫者实际上并没有观察到链接。我还读到()可以简单地将清扫器添加到environment.rb中的config.active\u record.observators中,但这似乎不行(我不确定environment.rb中app/sweeper的加载路径是否排除了这一点)。

通过添加

ActionController::Base.expire_page(app.link_path(:md5 => @link.md5))
到模型本身中更新数据库的方法不过,这感觉有点骇人,我想知道是否有人能解释为什么它不能与正常的清扫器设置一起工作,以及是否有更优雅的方法来处理此问题。


这段代码(除了我为自己的应用程序所做的自定义之外)来自。

所以我尝试了许多不同的方法,看看哪些有效,哪些无效

再次总结一下情况:我的目标是在对象更新时使缓存页面过期,但在不依赖控制器操作的情况下使缓存页面过期。传统的清理程序使用控制器中的一行命令通知清理程序它需要运行。在这种情况下,我不能在控制器中使用行,因为更新正在模型中进行。普通的清扫器教程不起作用,因为它们假定您与数据库对象的主要交互是通过控制器进行的

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
如果,在阅读本文时,您看到了一种收紧我的代码的方法,请发表评论并让我知道

首先,让我们看看那些有用的东西,以防你也被困在这个问题上,需要帮助

在我尝试过的所有方法中,唯一真正有效的方法是在模型的观察者中声明after_update命令。在该命令中,我对expire_页面操作使用了显式命令,并包含了在routes.rb中声明的路径

所以。这项工作:

在config/routes.rb中:

map.link 'l/:md5.:format',  :controller => 'links', :action => 'show'
在app/models/link_observer.rb中:

def after_update(link)
  ActionController::Base.expire_page(app.link_path(:md5 => link.md5))
end
请注意,“md5”是特定于我的应用程序的。您可能需要使用:id或其他唯一标识符

我还发现声明ActionController::Base。。。执行更新的模型中的方法的行。也就是说,在Link.rb中,在实际更新数据库的方法中,如果我只插入整行代码,它就工作了。但是,由于我将来可能希望在其他方法上使页面缓存过期,所以我宁愿将其提取到Observer中

现在,让我们看看一些不起作用的东西,以防你在谷歌上搜索

在link\u observer.rb中的after\u update(link)方法中调用“expire\u page(…)”无效,因为它返回了一个“未定义的方法`expire\u page'”错误

创建观察到模型的清扫器文件无效。我找不到任何错误代码,但它似乎根本没有意识到它有工作要做。这是在environment.rb中显式调用“config.load_path+=%W(#{RAILS_ROOT}/app/sweeppers)”之后发生的。以防万一我在代码中发现了什么,这里是:

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
但这也没用

所以,是的。很有可能这些方法中有一种会起作用,而我把代码中的某些东西弄乱了。但我想我做的一切都是照章办事

最后,总结一下:与其使用清理器终止页面缓存,不如在模型的观察器中设置一个after_uu回调。您需要使用Base.expire\u页面方法的显式路径:

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
def after_update()#您正在观察的模型的名称在哪里
ActionController::Base.expire_页面(app._path(:id=>.id))#您正在观察的模型的名称在哪里
结束

希望这能帮助其他人。同样,如果你看到我的代码中有任何地方我应该做一些不同的事情,请让我知道。如果您在我的工作代码中看到一些更紧凑的内容,请也告诉我。

请注意:您可以在ApplicationController中使用
cache\u sweeper

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
class ApplicationController
我确实让它工作了。我的设置中唯一的细微差别是清扫器是Rails引擎的一部分;这说明了细微的差异(在引擎的init中加载带有require的清扫器文件,而不是将其添加到e中的加载路径中)
require File.join(File.dirname(__FILE__), 'app', 'sweepers', cached_category_count_sweeper')
class CachedCategoryCountSweeper < ActiveRecord::Observer
  observe CategoryFeature

  def before_save(cf)
    expire_cache(cf.category_id_was) if cf.category_id_changed?
  end

  def after_save(cf)
    expire_cache(cf.category_id)
  end

  def after_destroy(cf)
    expire_cache(cf.category_id)
  end

  def expire_cache(c)
    ApplicationController.expire_page("/categories/#{c}/counts.xml") if !c.nil?
  end
end
include ActionController:UrlWriter
config.active_record.observers = :cached_category_count_sweeper
class CachedCategoryCountsController < ApplicationController
  caches_page :index

  # GET /cached_category_counts.xml
  def index
    ...
  end
end
class LinkSweeper < ActiveRecord::Observer
  include ActionController::Caching::Pages
  # or if you want to expire fragments
  #include ActionController::Caching::Fragments

  observe Link

  def after_update(link)
    expire_page( ... )
    #expire_fragment( ... )
  end
end