【问题标题】:Full url for an image-path in Rails 3Rails 3 中图像路径的完整 url
【发布时间】:2011-07-25 23:35:34
【问题描述】:

我有一张图片,其中包含载波上传:

Image.find(:first).image.url #=> "/uploads/image/4d90/display_foo.jpg"

在我看来,我想为此找到绝对网址。附加 root_url 会产生一个双重 /

root_url + image.url #=> http://localhost:3000//uploads/image/4d90/display_foo.jpg

我不能使用url_for(我知道),因为要么 允许传递路径, 一个选项列表来标识资源和@ 987654326@ 选项。由于我没有可以通过“控制器”+“动作”识别的资源,我无法使用:only_path 选项。

url_for(image.url, :only_path => true) #=> wrong amount of parameters, 2 for 1

在 Rails3 中创建完整 url 路径的最干净和最好的方法是什么?

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 url path


    【解决方案1】:

    您也可以像这样设置 CarrierWave 的 asset_host 配置设置:

    # config/initializers/carrierwave.rb
    CarrierWave.configure do |config|
      config.storage = :file
      config.asset_host = ActionController::Base.asset_host
    end
    

    这个 ^ 告诉 CarrierWave 使用您应用的 config.action_controller.asset_host 设置,该设置可以在您的 config/envrionments/[environment].rb 文件之一中定义。 See here 了解更多信息。

    或者明确设置:

      config.asset_host = 'http://example.com'
    

    重新启动您的应用,一切顺利 - 无需辅助方法。

    * 我正在使用 Rails 3.2 和 CarrierWave 0.7.1

    【讨论】:

    • 我喜欢这个,又好又干净
    【解决方案2】:

    试试path方法

    Image.find(:first).image.path
    

    UPD

    request.host + Image.find(:first).image.url
    

    你可以把它包装成一个助手来永远干燥它

    request.protocol + request.host_with_port + Image.find(:first).image.url
    

    【讨论】:

    • 返回整个(系统)路径。 => "/home/..../public/uploads/image/4d90/foo.jpg" 我需要在 atom 提要中使用的 URL,而不是路径。
    • 哦,是的。然后试试request.host + Image.find(:first).image.url
    • 也不是 :( "localhost/uploads/image/4d90/display_foo.jpg" 它错过了 :3000-port(开发中)和 http(s)://。
    • request.protocol + request.host_with_port + Image.find(:first).image.url
    • 我正在使用延迟作业来排队发送电子邮件作业。作业呈现电子邮件模板。但是此时请求将为零(它本身不再是 HTTP 请求的一部分)。
    【解决方案3】:

    另一个简单的使用方法是 URI.parse,在你的情况下是

    require 'uri'
    
    (URI.parse(root_url) + image.url).to_s
    

    还有一些例子:

    1.9.2p320 :001 > require 'uri'
     => true 
    1.9.2p320 :002 > a = "http://asdf.com/hello"
     => "http://asdf.com/hello" 
    1.9.2p320 :003 > b = "/world/hello"
     => "/world/hello" 
    1.9.2p320 :004 > c = "world"
     => "world" 
    1.9.2p320 :005 > d = "http://asdf.com/ccc/bbb"
     => "http://asdf.com/ccc/bbb" 
    1.9.2p320 :006 > e = "http://newurl.com"
     => "http://newurl.com" 
    1.9.2p320 :007 > (URI.parse(a)+b).to_s
     => "http://asdf.com/world/hello" 
    1.9.2p320 :008 > (URI.parse(a)+c).to_s
     => "http://asdf.com/world" 
    1.9.2p320 :009 > (URI.parse(a)+d).to_s
     => "http://asdf.com/ccc/bbb" 
    1.9.2p320 :010 > (URI.parse(a)+e).to_s
     => "http://newurl.com" 
    

    【讨论】:

      【解决方案4】:

      只接受楼的回答并提供帮助:

      # Use with the same arguments as image_tag. Returns the same, except including
      # a full path in the src URL. Useful for templates that will be rendered into
      # emails etc.
      def absolute_image_tag(*args)
        raw(image_tag(*args).sub /src="(.*?)"/, "src=\"#{request.protocol}#{request.host_with_port}" + '\1"')
      end
      

      【讨论】:

      • 这个助手在标准视图中工作得很好,但是你不能在 Mailer 视图中使用它,因为 Mailers 没有“请求”的感觉,所以你的助手会失败。
      • 是的。我不确定,但我认为使用 Rails 3.1 和资产管道,您可以使用资产主机来组合完整的 URL。对于早期版本,我认为需要对主机进行硬编码。
      • @M.G.Palmer 由于carrierwave上传的图像位于公共文件夹中,这仍然有效吗?
      • @lulalala 我应该这样认为,也许您需要使用 absolute_image_tag("/../#{filename}") 之类的方法从默认的 /images 路径中“启动”。但是我从来没有使用过carrierwave所以YMMV。
      【解决方案5】:

      这里有很多答案。但是,我不喜欢它们中的任何一个,因为它们都依赖于我记得显式添加端口、协议等。我发现这是最优雅的方式:

      full_url = URI( root_url )
      full_url.path = Image.first.image.url
      # Or maybe you want a link to some asset, like I did:
      # full_url.path = image_path("whatevar.jpg")
      full_url.to_s
      

      最好的一点是,我们可以轻松地改变一件事,不管是什么,你总是以同样的方式做。假设您想放弃协议并使用The Protocol-relative URL,请在最终转换为字符串之前执行此操作。

      full_url.scheme = nil
      

      是的,现在我有一种方法可以将我的资产图像 url 转换为协议相关 url,我可以在代码 sn-p 上使用它,其他人可能想在他们的网站上添加它,无论他们使用什么协议,它们都可以工作在他们的网站上(前提是您的网站支持任一协议)。

      【讨论】:

        【解决方案6】:

        我使用了default_url_options,因为request 在邮件程序中不可用,并且避免在config.action_controller.asset_host 中重复主机名(如果之前没有指定)。

        config.asset_host = ActionDispatch::Http::URL.url_for(ActionMailer::Base.default_url_options)
        

        【讨论】:

          【解决方案7】:

          您不能在电子邮件中引用请求对象,那么如何:

          def image_url(*args)
              raw(image_tag(*args).sub /src="(.*?)"/, "src=\"//#{ActionMailer::Base.default_url_options[:protocol]}#{ActionMailer::Base.default_url_options[:host]}" + '\1"')
          end
          

          【讨论】:

            【解决方案8】:

            您实际上可以通过以下方式轻松完成此操作

            root_url[0..-2] + image.url
            

            我同意它看起来不太好,但可以完成工作.. :)

            【讨论】:

              【解决方案9】:

              我发现了这个避免双斜线的技巧:

              URI.join(root_url, image.url)
              

              【讨论】:

                猜你喜欢
                • 2014-07-30
                • 1970-01-01
                • 2013-05-07
                • 1970-01-01
                • 2012-07-26
                • 1970-01-01
                • 1970-01-01
                • 2010-11-22
                • 1970-01-01
                相关资源
                最近更新 更多