当前位置:  开发笔记 > 后端 > 正文

如何从Rails Observer/Model调用expire_fragment?

如何解决《如何从RailsObserver/Model调用expire_fragment?》经验,为你挑选了4个好方法。

我几乎尝试过所有东西,但似乎不可能从模型中使用expire_fragment?我知道你不应该而且它不是非MVC,但肯定有很多方法可以做到.

我在lib/cache_helper.rb中创建了一个带有所有过期助手的模块,每个模块都只是一堆expire_fragment调用.我在/ app/sweepers下设置了所有缓存清理器,并在我的应用程序控制器中有一个"include CacheHelper",因此当通过控制器调用时,应用程序中的缓存可以正常工作.

然后事情是我有一些外部守护进程,特别是一些重复的cron任务,它们调用一个调用某种方法的rake任务.此方法执行一些处理并将条目输入到模型中,之后我需要使缓存过期.

这是最好的方法,因为我无法在模型中指定缓存清理程序.直观的观察者似乎是最好的解决方案,但后来它抱怨expire_fragment未定义等等,我甚至尝试将ActionController缓存类包含在观察者中,但这不起作用.我喜欢有关如何为此创建解决方案的一些想法.谢谢.



1> Orion Edward..:

免责声明:我的导轨有点生锈,但这或类似的东西应该有用

ActionController::Base.new.expire_fragment(key, options = nil) 



2> TheDeadSerio..:

猎户座提供的解决方案完美无缺.为了方便起见,我将以下代码放入其中config/initializers/active_record_expire_fragment.rb

class ActiveRecord::Base
  def expire_fragment(*args)
    ActionController::Base.new.expire_fragment(*args)
  end
end

现在,您可以在ActiveRecord :: Base的所有实例上使用expire_fragment,例如 User.first.expire_fragment('user-stats')



3> vladr..:

这很容易做到.您可以实现Orion的建议,但您也可以实现下面所示的更广泛的技术,这使您可以从任何模型访问当前控制器,无论您决定打破MVC分离的目的(例如,搞乱片段缓存,访问current_user,生成)路径/ URL等)

为了从任何模型访问当前请求的控制器(如果有的话),将以下内容添加到environment.rb或更好地添加到新插件(例如,vendor/plugins/controller_from_model/init.rb包含以下代码的create ):

module ActiveRecord
  class Base
    protected
      def self.thread_safe_current_controller #:nodoc:
        Thread.current[:current_controller]
      end

      def self.thread_safe_current_controller=(controller) #:nodoc:
        Thread.current[:current_controller] = controller
      end

      # pick up the correct current_controller version
      #  from @@allow_concurrency
      if @@allow_concurrency
        alias_method :current_controller,  :thread_safe_current_controller
        alias_method :current_controller=, :thread_safe_current_controller=
      else
        cattr_accessor :current_controller
      end
  end
end

然后,在app/controllers/application.rb,

class ApplicationController < ActionController::Base
  before_filter { |controller|
    # all models in this thread/process refer to this controller
    #  while processing this request
    ActiveRecord::Base.current_controller = controller
  }

  ...

然后,从任何模型,

if controller = ActiveRecord::Base.current_controller
  # called from within a user request
else
  # no controller is available, didn't get here from a request - maybe irb?
fi

无论如何,在您的特定情况下,您可能希望ActiveRecord::Base在相关控制器类加载时将代码注入各种后代,以便实际的控制器感知代码仍然驻留在其中app/controllers/*.rb,但为了获得某些功能而不是必须这样做(虽然丑陋且难以维护.)

玩得开心!


让脚射击开始!

4> maurycy..:

在我的一个脚本中,我使用以下hack:

  require 'action_controller/test_process'

  sweepers = [ApartmentSweeper]

  ActiveRecord::Base.observers = sweepers
  ActiveRecord::Base.instantiate_observers

  controller = ActionController::Base.new
  controller.request = ActionController::TestRequest.new
  controller.instance_eval do
    @url = ActionController::UrlRewriter.new(request, {})
  end

  sweepers.each do |sweeper|
    sweeper.instance.controller = controller
  end

然后,一旦调用了ActiveRecord回调,清扫器就可以调用expire_fragment.

推荐阅读
和谐啄木鸟
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有