Rails:在Observer中使用URL Helper

时间:2011-06-20 21:46:33

标签: ruby-on-rails ruby-on-rails-3 observer-pattern link-to url-helper

我有一个看起来像这样的观察者:

class CommentObserver < ActiveRecord::Observer
    include ActionView::Helpers::UrlHelper

    def after_create(comment)
        message = "#{link_to comment.user.full_name, user_path(comment.user)} commented on #{link_to 'your photo',photo_path(comment.photo)} of #{comment.photo.location(:min)}"
        Notification.create(:user=>comment.photo.user,:message=>message)
    end

end

基本上我正在使用它做的是当有人在他们的一张照片上发表评论时为某个用户创建简单的通知消息。

此操作失败并显示错误消息:

NoMethodError (undefined method `link_to' for #<CommentObserver:0x00000102fe9810>):

我原本希望包括ActionView::Helpers::UrlHelper可以解决这个问题,但似乎没有效果。

那么,如何在我的观察者中包含URL助手,或者以其他方式呈现?我很乐意将“消息视图”移动到部分或者某个部分,但是观察者没有相关的视图来将其移动到...

3 个答案:

答案 0 :(得分:3)

为什么不在将消息呈现到页面然后使用类似的内容进行缓存时构建消息?

<% cache do %>
  <%= render user.notifications %>
<% end %>

这样可以避免在观察者中进行黑客攻击,并且在Rails中更符合“标准”。

答案 1 :(得分:2)

因此,事实证明,由于您无法在邮件程序视图中使用link_to,因此无法执行此操作。观察者没有关于当前请求的信息,因此不能使用链接助手。你必须以不同的方式做到这一点。

答案 2 :(得分:2)

为了处理这类事情,我创建了一个AbstractController来生成电子邮件的正文,然后我将它作为变量传递给邮件程序类:

  class AbstractEmailController < AbstractController::Base

    include AbstractController::Rendering
    include AbstractController::Layouts
    include AbstractController::Helpers
    include AbstractController::Translation
    include AbstractController::AssetPaths
    include Rails.application.routes.url_helpers
    include ActionView::Helpers::AssetTagHelper

    # Uncomment if you want to use helpers 
    # defined in ApplicationHelper in your views
    # helper ApplicationHelper

    # Make sure your controller can find views
    self.view_paths = "app/views"
    self.assets_dir = '/app/public'

    # You can define custom helper methods to be used in views here
    # helper_method :current_admin
    # def current_admin; nil; end

    # for the requester to know that the acceptance email was sent
    def generate_comment_notification(comment, host = ENV['RAILS_SERVER'])
        render :partial => "photos/comment_notification", :locals => { :comment => comment, :host => host }
    end
  end

在我的观察者中:

  def after_create(comment)
     email_body = AbstractEmailController.new.generate_comment_notification(comment)
     MyMailer.new(comment.id, email_body)
  end