How do I get the base URL (e.g. http://localhost:3000) of my Rails app?
Asked Answered
B

4

9

I'm using Paperclip to allow users to attach things, and then I'm sending an email and wanting to attach the file to the email. I'm trying to read the file in and add it as an attachment, like so:

# models/touchpoint_mailer.rb
class TouchpointMailer < ActionMailer::Base
  def notification_email(touchpoint)
    recipients "[email protected]"
    from "Touchpoint Customer Portal <[email protected]>"
    content_type "multipart/alternative"
    subject "New Touchpoint Request"
    sent_on Time.now
    body :touchpoint => touchpoint

    # Add any attachments the user has included
    touchpoint.assets.each do |asset|
      attachment :content_type => asset.file_content_type,
                 :body => File.read(asset.url)
    end
  end
end

This gives me the following error No such file or directory - /system/files/7/original/image.png?1254497688 with the stack trace saying it's the call to File.read. When I visit the show.html.erb page, and click on the link to the image, which is something like http://localhost:3000/system/files/7/original/image.png?1254497688, the image is displayed fine.

How can I fix this problem?

Bostick answered 2/10, 2009 at 15:37 Comment(0)
A
4

asset.url returns the URL to the file. This is usually /system/classname/xx/xx/style/filename.ext. You'd put this in an image_tag.

You want asset.path. It returns the full path to the file, which will usually be something like /home/username/railsapp/public/system/classname/xx/xx/style/filename.ext

HTH.

Asti answered 8/2, 2010 at 15:29 Comment(0)
D
22

Typically root_url should provide this.

File.read is expecting a file path, not a url though. If you are generating the images, you should call the image generating code and return the bytes of the generated image instead of calling File.read(…)

Dolan answered 2/10, 2009 at 15:57 Comment(9)
I'm not generating them, I'm letting the user upload them and storing them on the filesystemBostick
But when I specify the filepath (via the asset.url method) I get an error saying it can't find the file; however when I link to it (e.g. link_to asset.name, asset.url) it works fine and I can view the image.Bostick
Try File.read(File.join(Rails.root, "public", asset.url)) (assuming the images are on the file system under public/system/files/….Dolan
Hmm the problem seems to be the string of characters it adds after the filename, trying what cwninja said I get the error "Invalid argument". Is there any way to get the base path to the file without that gobbeldygook after it?Bostick
asset.url.gsub(/\?.*/, "") as a quick fix?Dolan
(Obviously you should be wrapping all this ick up in your model, # data method maybe?)Dolan
That works, but now I'm getting an Permission Denied error when I try to read the file, although Rails has permission to save the file to the folder.Bostick
The permission denied seems to be at the root directory (e.g. C:\Documents\Wayne\Projects\Portal\) but Rails is able to do everything else to that directory. Maybe it has to do with the fact this is via a mailer and not a controller?Bostick
mailer vs controller should not make a difference. As you are on windows (boooooo!), you may need to do a File.read(File.join(Rails.root, "public", *asset.url.gsub(/\?.*/, "").split("/")). It may be trying to read C:\Documents\Wayne\Projects\Portal\public\system/files/7/original/image.png which does not look like a valid windows (booooo!) file name.Dolan
A
4

asset.url returns the URL to the file. This is usually /system/classname/xx/xx/style/filename.ext. You'd put this in an image_tag.

You want asset.path. It returns the full path to the file, which will usually be something like /home/username/railsapp/public/system/classname/xx/xx/style/filename.ext

HTH.

Asti answered 8/2, 2010 at 15:29 Comment(0)
B
3
request.env["HTTP_HOST"]

I don't know why this one line of code is so elusive on the web. Seems like it should be up front and center.

Bushcraft answered 9/2, 2013 at 22:4 Comment(3)
It was working great until i tried to use it in a rails mailer, and ran into this undefined method 'env' for nil:NilClass so it doesn't work everywhere.Katheykathi
As far as I know, the request object doesn't exist in mailers. That is why you have to specifically define a value for host. Not sure why this keeps getting voted up?Near
This is insecure! The "HTTP_HOST" header is set by the user, and a malicious user could change it to anything he/she wants when submitting a request. This could mean password reset links could be sent to someone else's server, or images could be changed, etc. DO NOT USE THISHerriot
P
1

as ZiggyTheHamster is saying: the asset.url is the generated url that would be used on webpages (which is why you're getting the unix-style directory slashes, as pointed out in the comments.)

asset.path should give you the OS-aware path to the file, but even that isn't needed with paperclip. Paperclip::Attachment is already an IOStream.

You just need :body => asset like so:

touchpoint.assets.each do |asset|
  attachment :content_type => asset.file_content_type,
             :body => asset
end
Pip answered 13/3, 2011 at 10:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.