Get absolute URL for paperclip attachment
Asked Answered
M

7

26

Is it possible to get the absolute URI for a Paperclip attachment? Right now, the problem is that the production environment is deployed in a sub-URI (on Passenger: RackBaseURI), but <paperclip attachment>.url returns the Rails-app relative URI (/system/images/...). Is there a way to get the absolute URI for Paperclip attachments?

I'm using Paperclip v2.7 and Rails 3.2.8.

Magically answered 23/9, 2012 at 7:27 Comment(0)
C
29

try

URI.join(request.url, @model.attachment_name.url)

or

URI(request.url) + @model.attachment_name.url

It's safe if you use S3 or absolute url.

Update: this answer is better than mine ;) https://mcmap.net/q/426454/-get-absolute-url-for-paperclip-attachment

Camera answered 21/1, 2013 at 19:24 Comment(3)
undefined local variable or method `request' for #<ModelName:0x000001083fd438>Zirconia
@Zirconia you can't do that in a model — request is only available in controllers and viewsSpode
I wonder how can I do this inside Grape Entities... request isn't available there also. Any suggestions?Primatology
I
41
asset_url(model.attachment_name.url(:style))

Relevant github issue

Inflexible answered 8/8, 2014 at 20:40 Comment(3)
It's for Rails 4+ I think?Wurster
asset_url cannot be used in controller directly, but URI.join can :-)Gerda
api.rubyonrails.org/classes/ActionView/Helpers/…Faltboat
C
29

try

URI.join(request.url, @model.attachment_name.url)

or

URI(request.url) + @model.attachment_name.url

It's safe if you use S3 or absolute url.

Update: this answer is better than mine ;) https://mcmap.net/q/426454/-get-absolute-url-for-paperclip-attachment

Camera answered 21/1, 2013 at 19:24 Comment(3)
undefined local variable or method `request' for #<ModelName:0x000001083fd438>Zirconia
@Zirconia you can't do that in a model — request is only available in controllers and viewsSpode
I wonder how can I do this inside Grape Entities... request isn't available there also. Any suggestions?Primatology
D
20

According to this github issue, it is cleaner to use ActionController::Base.asset_host so it would result the helper:

  def add_host_prefix(url)
    URI.join(ActionController::Base.asset_host, url)
  end

This supposes you have in every /config/environments/<environment>.rb file the following:

Appname::Application.configure do

  # ....

  config.action_controller.asset_host = 'http://localhost:3000' # Locally

  # ....

end
Destine answered 9/1, 2014 at 18:5 Comment(0)
O
6

The most widely applicable way of doing this is to first define your asset hosts in the relevant config/environment file:

config.action_controller.asset_host = "http://assethost.com"
config.action_mailer.asset_host = "http://assethost.com"

Then in views and mailers:

asset_url(model.attachment.url(:style))

In the console:

helper.asset_url(model.attachment.url(:style))

In a model:

ApplicationController.helpers.asset_url(model.attachment.url(:style))
Opportunity answered 3/12, 2014 at 21:0 Comment(0)
F
5

You can do this:

<%= image_tag "#{request.protocol}#{request.host_with_port}#{@model.attachment_name.url(:attachment_style)}" %>

Or make a helper method to wrap it.

def absolute_attachment_url(attachment_name, attachment_style = :original)
  "#{request.protocol}#{request.host_with_port}#{attachment_name.url(attachment_style)}"
end

And use it like this:

<%= image_tag absolute_attachment_url(attachment_name, :attachment_style)}" %>

Ex: Model = Person (@person), attachment_name = avatar, style = :thumb

<%= image_tag absolute_attachment_url(@person.avatar, :thumb)}" %>
Framboise answered 23/9, 2012 at 21:19 Comment(1)
attention. this won't work when having config.action_controller.asset_host set as it will give you duplicate/screwed protocol + host.Sow
R
4

This doesn't solve the original poster's problem exactly (it operates in the view, not the model), but may be helpful for people who are trying to "get absolute URL for paperclip attachment" within their view: In the same way that

image_tag(user.avatar.url(:large))

puts the image itself into your view,

image_url(user.avatar.url(:large))

returns just the URL you'll need if you want to link to the asset directly (e.g. in a link_to call).

Reneta answered 16/7, 2014 at 20:25 Comment(1)
"The Attachment#url method is misleading since it returns a relative path (like the Routes _path methods) not a full url (like the Routes _url methods). Googling turns up several "answers", but they are all hacks." github.com/thoughtbot/paperclip/issues/584#issue-1548822Inflexible
P
2

You can add to your application.rb (or for specific enviroment in config/environments/*):

config.paperclip_defaults = {
    url: "http://my.address.com/system/:class/:attachment/:id_partition/:style.:extension",
    path: ':rails_root/public/system/:class/:attachment/:id_partition/:style.:extension',
}

Restart and reimport your images.

PS: obviously you can replace http://my.address.com with an environment variable.

Pytlik answered 6/6, 2017 at 15:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.