Rails:如何访问Observer中的当前控制器?

时间:2011-11-15 18:49:46

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

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

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

4 个答案:

答案 0 :(得分:4)

正如其他人所说,从观察者访问控制器有点违反了MVC原则。此答案也适合您的特定用例。

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

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

这是通过将扫地机同时用作观察者和控制器过滤器来实现的,这很容易实现,因为观察者是单身人士(即他们包括 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
    
  4. 现在您可以从观察者回调中访问控制器。但是,如果在控制器操作之外触发了观察者,则controllernil

答案 1 :(得分:2)

从Observer访问Controller违反了MVC模式。不违反MVC的方法是在调用flash[:notice]后从控制器分配SomeModel.create()

答案 2 :(得分:1)

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

<强>替代地

在application_helper文件中创建一个帮助方法来检查flash和diplay。

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!"

答案 3 :(得分:0)

观察者和控制者之间的Rails没有任何联系,我担心你不会以标准的方式达到你的目标。但是我建议使用线程来实现这个目标。