如何在Rails 3.1中获取资源的绝对URL?

49

image_path返回的是路径而不包含主机名。

url_for助手函数无法接受单个路径,因此 url_for(image_path('image.png')) 这样的语法是行不通的。虽然内部的 url_forActionDispatch::Http::Url.url_for 中似乎可以解决这个问题(源代码),但并没有公共接口可供使用。

我该怎么办呢?最好能够创建一个类似image_url的函数,像路由的url_for一样工作,这样我就可以调用image_url('image.png')并得到所有default_url_options所提供的绝对URL地址。


1
这篇博客有一个代码片段,你可以使用:http://stick.gk2.sk/blog/2009/12/image_url-function-in-ruby-on-rails/ - Spike Gronim
@Spike:这种方法的缺点是它忽略了默认的URL选项。例如,无法通过手动或应用程序配置中的default_url_options哈希表覆盖推断的请求参数。 - Steven
@SpikeGronim 这在延迟作业中不起作用,因为请求将为空。 - lulalala
对于Rails版本大于4.2.1的用户,请使用asset_url和相关选项的:host选项,例如 asset_url('my_image.png', host: root_url)。请参阅asset_url文档 - Nic Nilov
7个回答

53
def image_url(source)
  URI.join(root_url, image_path(source))
end

使用assets_host或与root_url连接来获取URL。


1
在3.2中, 为了让helper正常工作,您必须在mailer中添加add_template_helper(MailerHelper)。 - Syl
@Syl 为什么要使用 MailerHelper?这与邮件无关,而是与资产有关。 - tig

14

尝试在您的application_helper.rb中使用以下代码(来自Spike列出的页面上的注释之一):

def image_url(source)
  "#{root_url}#{image_path(source)}"
end

12
为了去掉额外的斜线:def image_url(source) "#{root_url[0...-1]}#{image_path(source)}" end - iGEL
我在Rails 3.1中使用它时遇到了麻烦,直到我将名称更改为url_for_image。我不确定,但我认为方法image_url被视为路由。 - Luke Francl
我还不得不更改 image_url 方法名称为 get_image_url 才能让它正常工作。 - tdewell

6

我们的生产和测试环境是在s3/cloudfront上...但本地/开发环境不是。因此,我编写了以下代码(可能有些过度,而且可能可以简化):

  def get_digest_file(source)
     return asset_path(source.to_s.downcase) unless Rails.application.config.assets.digests.present?
     return ActionController::Base.asset_host + "/assets/" + Rails.application.config.assets.digests[source.to_s.downcase]
  end

顺便提一下,如果使用 Turbo-Sprockets,这个答案会稍有不同。 - courtsimas

5

最近看来,sass-rails 现在按照预期方式解释 scss 文件中的 image_url 命令,将其解析为所涉及图片的最终位置。


2
有没有办法在 Sass 之外完成这个操作?image_url 在视图中不起作用。 - Luke Francl
1
是的。这是我之前使用过的地方(内联样式):"background:url(#{asset_path('desktop-header@2x.jpg')}) top center no-repeat;" - courtsimas

4

来自Rails 3中图像路径的完整URL

request.protocol + request.host_with_port + image_path('image.png')

你甚至可以创建一个助手函数来DRY它,类似于下面:

def full_image_path(img_path)
    request.protocol + request.host_with_port + image_path(img_path)
end

0
如果您在视图中无法访问root_url,可以将其传递给视图,或者还可以添加一个.env变量,然后在根目录中调用它。
asset_url('image.png', host: "https://#{ENV['HOSTNAME']}/")

0

您可以使用绝对路径为任何背景图像或其他资源定义CSS。因此,您可以根据此动态生成它 使用Sass/Scss获取CSS文件中的绝对图像路径的方法

CSS

body {
  background-image: image-url(background.png);
}

在你的环境文件中将其更改为你自己的。
config.action_controller.asset_host = "http://your.domain.com/"

然后你的 CSS 会看起来像这样:

body {
  background-image: url(http://your.domain.com/assets/background.png);
}

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