【问题标题】:Rails: How to access current controller in an Observer?Rails:如何在观察者中访问当前控制器?
【发布时间】:2011-12-29 19:13:01
【问题描述】:

我需要访问当前控制器或从观察者方法发出通知。

class SomeObserver < ActiveRecord::Observer
    observe :some_model
    cattr_accessor :current_controller

    def after_create(record)
        ...
        current_controller.flash[:notice] = "Some message!"
    end
end

class ApplicationController < ActionController::Base
    before_filter do
        SomeObserver.current_controller = self
    end
    ...
end

【问题讨论】:

    标签: ruby-on-rails ruby controller observer-pattern


    【解决方案1】:

    正如其他人所说,从观察者访问控制器在某种程度上违反了 MVC 原则。给出的答案也适合您的特定用例。

    但是如果您需要更通用的解决方案,您可以尝试调整 Rails Sweepers 的工作方式。

    Sweeper 是普通的观察者,但它们提供对控制器的访问,如果观察者是从控制器动作中调用的。

    这是通过同时使用清扫器作为观察者和控制器过滤器来实现的,这很容易实现,因为观察者是单例的(即它们包括 Singleton 模块)

    简而言之,您必须这样做:

    1. 照常创建您的观察者。
    2. 将单例实例作为around_filter 添加到您的控制器:

      class ApplicationController < ActionController::Base
        around_filter MyObserver.instance #, only: [...]
      end
      
    3. 将过滤器的方法添加到您的观察者:

      attr_accessor :controller
      
      def before(controller)
        self.controller = controller
        true #Don't forget this!
      end
      
      def after(controller)
        self.controller = nil
      end
      

    现在您可以从观察者回调中访问控制器。但是,如果观察者是在控制器操作之外触发的,则 controllernil

    【讨论】:

    【解决方案2】:

    从观察者访问控制器违反了 MVC 模式。在不违反 MVC 的情况下做到这一点的方法是在调用 SomeModel.create() 之后从控制器分配 flash[:notice]

    【讨论】:

      【解决方案3】:

      为什么在观察者中?您应该将 flash 分配放在您的控制器中,原因是 flash 是视图级别的问题。

      或者

      在您的 application_helper 文件中创建一个帮助方法来检查闪存和显示。

      def show_flash
      [:notice, :error, :warning].collect do |key|
        content_tag(:div, flash[key], :id => key, :class => "flash flash_#{key}") unless   flash[key].blank?
      end.join
      end
      

      然后在你的布局中添加

      <% show_flash %>
      

      对于通知、警告和错误类型的消息,它会检查是否设置了它们中的任何一个,如果设置了则将它们打印出来,如果没有则不打印任何内容。

      现在你可以使用

      flash[:notice] = "Some message!"
      

      【讨论】:

      • 感谢您的快速回复。我的应用程序逻辑要求在观察者中进行这些计算。我观察到各种模型和回调不适合这个目的。我知道它不是 MVC 做事的方式,可能我必须在后台任务/进程中移动它并制作一些通知机制来通知前端,但我正在寻找这个问题的快速解决方案。
      • 那么替代方法没有帮助吗?你可以从任何地方闪现[:notice] ..!!
      【解决方案4】:

      Rails 中的观察者和控制器之间没有任何联系,我担心您无法通过标准方式实现目标。不过我建议使用线程来实现这个目标。

      【讨论】:

      • 为什么你提供了这个讨论的相同链接?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-05
      • 1970-01-01
      • 2012-07-23
      • 2011-03-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多