5

I am facing the following problem:

I am doing a Rails 4 webapp and we are using paperclip for profile images. If the user does not upload an image we provide a default one (like the facebook silhouette placeholder). So as paperclip eases handling default images, we are doing the following in the Profile model:

class Profile < ActiveRecord::Base
  belongs_to :user
  has_attached_file :image, :styles => { :medium => "300x300", :thumb => "100x100" }, :default_url => "assets/profiles/:style/placeholder.gif"
end

The big problem is that I need the complete URL of the image and NOT only the path so I am struggling to get the host and port before that path. Using action view helpers there did not help (asset_url helper)

I was thinking in initializing some constant or configuration or environment variable per environment. Will it be correct? Any other suggestions?

EDIT: I forgot to mention this: The resource (Profile) may have a custom picture or a default one. When it has a custom image, we store it in Amazon S3 and in that case profile.image.url returns full URL. In the other case, when it has not a custom picture it has a default image stored in app/assets/images and in that case profile.image.url returns just the path. I would like that the method image.url consistently return full URLs. – flyer88 just now edit

flyer88
  • 1,073
  • 3
  • 15
  • 33
  • Why do you need complete url? paperclip doesn't expect you to give full URL according to this example -> https://github.com/thoughtbot/paperclip#quick-start – usha Dec 06 '13 at 19:24
  • I ask myself the same. We are doing an api for iphone and the front-end guys said to us they need complete URL and not only paths. ¯/\_(ツ)_/¯ – flyer88 Dec 06 '13 at 20:36
  • Just slightly more general: no explicit "in Model" requirement: http://stackoverflow.com/questions/42566/getting-the-hostname-or-ip-in-ruby-on-rails – Ciro Santilli OurBigBook.com Oct 09 '14 at 20:38

1 Answers1

3

If, as you mention in your comment, you are providing an API endpoint, it might make more sense to determine the host, port, etc. in the controller. Something like this:

# routes.rb
get "/profile/:id" => "api#profile"

# profile.rb
def image_url_or_default request
  if image
    "#{request.protocol}#{request.host_with_port}#{image.url}"
  else
    "http://s3.amazon.com/my_bucket/default.jpg"
  end
end

# api_controller.rb
def profile
  profile = Profile.find params[:id]
  render text:profile.image_url_or_default(request)
end

profile.image.url will be the full URL of the image.

Troy
  • 5,319
  • 1
  • 35
  • 41
  • I have just tested getting the image url in the controller and it still throws me the path (for default images). I need complete URLs – flyer88 Dec 09 '13 at 15:01
  • 1
    Now that you're in the controller, you have access to the request object, so you can use request.protocol and request.host_with_port to guild the full URL, like so: "#{request.protocol}#{request.host_with_port}#{profile.image.url}" (Updated answer) – Troy Dec 09 '13 at 16:59
  • Yes, I noted that, thanks. Anyway I am not sure I want this solution. I am rendering the response as json in a rabl.json template and there I have a key ``{profile_image_url: ...}`` among other values. I was hoping to get the full URL in the model as the paperclip's default path. In your way I will need to set an instance variable in the controller ``@image_url = profile.image.present? ? profile.image.url : "#{request.host_with_port}#{profile.image.url}"``.The problem is that when the resource has NO s3 image, it uses the default one, and the default one only renders the path and not full URL. – flyer88 Dec 09 '13 at 18:49
  • I don't mention in my question the most important thing of my problem. The problem is that the resource (``Profile``) may have a custom picture or a default one. When It has a custom image, we store it in Amazon S3 and in that case ``profile.image.url`` returns full URL. In the other case, when it has not a custom picture it has a default image stored in app/assets/images and in that case ``profile.image.url`` returns just the path. I would like that the method image.url consistently return full URLs. – flyer88 Dec 09 '13 at 18:57
  • The reason that I suggested "computing" the URL in the controller is that you have access to the request object there which has the protocol and host of the server serving the request. You can store that information in some kind of settings file that you access from a model, but if you ever move your app to another server or change the hostname of your server, you will have to change the configuration as well. Using the request variable in the controller allows you to get that information automatically. You could pass the request to the model like `profile.image_url_or_default(request)`. – Troy Dec 10 '13 at 04:09