【问题标题】:Rails Cache SweeperRails 缓存清扫器
【发布时间】:2011-04-15 19:55:44
【问题描述】:

我正在尝试实现一个缓存清扫器,它会过滤特定的控制器操作。

class ProductsController < ActionController  
    caches_action :index  
    cache_sweeper :product_sweeper  

    def index 
        @products = Product.all 
    end 

    def update_some_state
      #... do some stuff which doesn't trigger a product save, but invalidates cache
    end
end 

清扫班:

class ProductSweeper < ActionController::Caching::Sweeper
    observe Product

    #expire fragment after model update
    def after_save
       expire_fragment('all_available_products')   
    end

    #expire different cache after controller method modifying state is called.
    def after_update_some_state
        expire_action(:controller => 'products', :action => 'index') 
    end
end

ActiveRecord 回调“after_save”可以正常工作,但控制器操作“after_update_some_state”的回调似乎永远不会被调用。

【问题讨论】:

    标签: ruby-on-rails caching


    【解决方案1】:

    看起来我只是在尝试让控制器操作的回调正常工作时丢失了控制器名称。我的清扫器应该是:

    class ProductSweeper < ActionController::Caching::Sweeper
        observe Product
    
        #expire fragment after model update
        def after_save
           expire_fragment('all_available_products')   
        end
    
        #expire different cache after controller method modifying state is called.
        def after_products_update_some_state
            expire_action(:controller => 'products', :action => 'index') 
        end
    
        #can also use before:
        def before_products_update_some_state
            #do something before. 
        end
    end
    

    【讨论】:

    • 那么,可以使用after_save方法代替after_createafter_update?
    【解决方案2】:

    我认为你的扫地机应该是这样的:

    class ProductSweeper < ActionController::Caching::Sweeper
      observe Product
    
      def after_save(product)
         expire_cache(product)
      end
    
      def after_destroy(product)
        expire_cache(product)
      end
    
      private
    
      def expire_cache(product)
        expire_fragment('all_available_products')
        expire_page(:controller => 'products', :action => 'index')
      end 
    

    after_index 不是回调,除非你定义它。

    在控制器中,您应该指定应该触发清扫器的动作,这些动作应该是create, update, destroy,因此您的控制器声明应该如下所示:

    class ProductsController < ActionController  
      caches_action :index  
      cache_sweeper :product_sweeper, :only => [:create, :update, :destroy]  
    
      def index 
        @products = Product.all 
      end 
    
      def create
        @product = Product.new(params[:product])
    
         if @product.save # triggers the sweeper.
           # do something
         else
           # do something else
         end
       end
    
      # update and stuff ...
    end 
    

    希望对你有帮助!

    【讨论】:

    • 缓存清扫器文档说:“清扫器是缓存世界的终结者,负责在模型对象更改时使缓存过期。他们通过成为半观察者、半过滤器并为两者实现回调来做到这一点角色。” 这不是说它会添加 after_index 作为过滤回调吗? api.rubyonrails.org/classes/ActionController/Caching/…
    • 不,Sweepers 不定义过滤器回调,它们像观察者一样工作almost,最大的区别(从我的角度来看)是你必须指定观察者将工作的操作以及,您将可以访问一些特定于控制器的对象和方法,例如:expire_cachesessionparams 等等...
    • 在查看了我的原始帖子后,我意识到试图通过使用 index 作为我试图包装的示例操作来显示我想要完成的事情可能会令人困惑。我更新了我的原始示例,使其更加清晰。
    • 我已经更新了我的答案,我想你有点困惑,扫地机上的 after_save 回调有效,因为你正在观察 Transport 并且它有 ActiveRecord 回调,例如 @987654333 @,before_savebefore_update,所有这些最终都会在清扫器中触发......你试图用after_update_some_status做的不是一个有效的ActiveRecord回调,这就是为什么它永远不会被调用,你应该做的是;在控制器操作上触发回调事件,例如:@product.save@product.update_atributes,然后在清扫器上过期缓存。
    • 看起来我只是在尝试实现控制器操作回调时丢失了控制器名称。 after|before__
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    相关资源
    最近更新 更多