`
hijack
  • 浏览: 37394 次
  • 性别: Icon_minigender_1
  • 来自: Mars
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

url_for in ActionMailer

阅读更多

url_for in ActionMailer

ActionMailer是Rails中发送email的一个controller。今天遇到的一个问题就是在ActionMailer controller/viewer中生成URL。我说的生成URL主要指url_for方法生成绝对路径,也就是 url_for(:only_path => false, :controller => xxx, :action => xxx)。我们都知道组成一个绝对路径需要有protocol, host, port和相对路径。在ActionMailer里面, request instance是不存在的,所以组成绝对路径的protocol, host 和 port是得不到的。

动态语言在AOP方面有着天然的优势。上面的问题可以很方面用一个around filter来解决。下面是代码片断

    module InstanceMethods
      def url_for_everywhere
        begin
          request = self.request
          ::ActionController::UrlWriter.module_eval do
            @old_default_url_options = default_url_options.clone
            default_url_options[:host] = request.host
            default_url_options[:port] = request.port unless request.port == 80
            protocol = /(.*):\/\//.match(request.protocol)[1] if request.protocol.ends_with?("://")
            default_url_options[:protocol] = protocol
          end
          yield
        ensure
          ::ActionController::UrlWriter.module_eval do
            default_url_options[:host] = @old_default_url_options[:host]
            default_url_options[:port] = @old_default_url_options[:port]
            default_url_options[:protocol] = @old_default_url_options[:protocol]
          end
        end
      end
    end

思路很简单,::ActionController::UrlWriter中有默认的default_url_options的一些参数,filter选把这些参数保存起来,尝试去取当前request对应的参数,如果有那么应用,并继续执行后面的程序(url_for就在这里),最后需要把最原始的default_url_options restore。通过这样一个around filter我们就可以透明地解决ActionMailer中url_for不能使用的问题。当然也可以把它插件化 ;)

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics