url_for不使用default_url_options[:host]的默认值

6

我有一个ActionMailer的视图,其中包含几个不同的链接。我现在正在localhost:3000上运行它,因此我在app/initializers中的名为setup_mail.rb的文件中设置了如下内容(如此处所示):

ActionMailer::Base.default_url_options[:host] = "localhost:3000"

当我在视图中使用url_for时,它似乎无法提取此值。如果我在每个url_for标签中添加:host => "localhost:3000",它们就可以正常工作。但是没有包含这个值就不能正常工作。
我还有另一个标记project_url,它就像它的样子一样:链接到指定的项目。这个函数可以正常工作,包括主机值,只需要使用project_url(@project)。为什么一个可以工作而另一个不行呢?
根据我所读的所有内容,在初始化程序中设置default_url_options[:host]应该允许我省略url_for标签中的:host值。显然,这并不是世界上最糟糕的事情,但它似乎是不必要的,并且意味着当我最终在某个地方托管项目时,我将不得不去修改所有这些值。更糟糕的是,我不理解这个问题。我仍在学习过程中,所以我想知道我做错了什么。
4个回答

4

这份文档非常清晰明了。

当您决定为您的邮件设置默认的:host时,需要确保在使用url_for时使用:only_path => false选项。由于当没有显式提供:host选项时,url_for视图助手默认生成相对URL,传递:only_path => false将确保生成绝对URL。

您可以创建自己的帮助程序来代替url_for,以强制使用:only_pathfalse

def your_url_for(options = {})
  options.reverse_merge! only_path: false
  url_for(options)
end

您也可以猴子补丁Rails来强制将其作为默认设置,但这取决于您 :)
所有这些都是在添加以下内容的基础上进行的
config.action_mailer.default_url_options = { host: "YOUR HOST" }

将配置文件config/application.rb或其等效文件进行修改。


1
所以我在这里得出的结论是,我实际上无法避免那个额外的参数 - 我只能避免多次重复主机。但除了干扰该方法或创建一个新方法来使用之外,我将不得不在每个url_for标记中使用:host:only_path。即使对于像project_path这样的东西也不适用?这有点令人失望。 - Ben Saufley
如果您像我描述的那样创建自己的帮助程序,或者猴子补丁url_for本身以重载默认的:only_path选项,并选择直接使用url_for,那么这似乎是正确的。在我的应用程序中,我很少需要url_for,所以这从来不是一个真正的问题。 - deefour

2

看起来:only_path选项默认是false的。这就是为什么你需要为每个标签明确提供[:host]或设置url_for的默认选项,以适用于所有标签。以下是如何设置默认主机:

将此代码放入您的应用程序控制器中,它应该可以正常工作。

helper_method :url_for
def default_url_options(options)
  { host: 'localhost:3000' }
end

更多详情请查看设置url_for默认值


这段代码看起来有点过时了。我在用Rails 3.2版本。根据评论来看,这个方法仍然有效,但是这还是一个理想的解决方案吗?你说我需要为每个标签明确提供:host参数,但实际上我并不需要。正如我之前指出的那样,project_url已经正确地使用了默认的主机名。而且为什么像railscasts这样的网站会推荐我上面使用的方法,而不是你所建议的方法呢? - Ben Saufley
你误解了。ActionMailer::Base.default_url_options[:host] 应该是可以工作的,而且一直以来都能够正常工作。但是在你的情况下却不行。这就是为什么我建议尝试通过 default_url_options 进行设置并查看是否有效。所以请尝试将上述代码放入你的应用控制器中。 - CuriousMind
好的,很公正,所以你建议这个作为备份?我很感激。我会记住的。+1。但是我想找出首先导致问题的原因。 - Ben Saufley
要了解问题,需要代码。你可以尝试在Github上上传一个样例Rails应用程序,以重现你在这里描述的问题。然后有人可能会能够帮助你。干杯 :) - CuriousMind

1

如果不想在初始化后更改全局默认设置,可以在邮件发送器中定义一个方法 default_url_options,就像在控制器中一样:

class UserMailer < ActionMailer::Base
  def default_url_options
    { host: Tenant.current(true).host }
  end

  def confirm(user)
    @user = user
    mail(to: @user.email, subject: t(".subject_confirm"))
  end
end

-3

你正在设置ActionMailer::Base的默认值,但似乎希望它重置ActionController::Base的默认值。

在你的邮件视图中使用的<%= link_to %>不一定知道它处于邮件视图中的事实。


我没有使用 link_to,而是使用 url_for,在我看来,这是 ActionMailer 应该使用的方式。我将其用于 ActionMailer 的视图中,而不是控制器中(如果我正确理解了区别)。 - Ben Saufley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接