Serving images in rails - ruby-on-rails

For every version of my app, I upload my assets to the cloud CDN, and the images on the website are loaded as something like imagename-somehash.
I have static images that are large, i.e like carousel images, which don't change often or at all. So even when the app changes, they can remain cached by clients who previously visited the website.
How would one do that? Any images I have under app/assets folder gets upload to CDN with the imagename-somehash format, so the image changes with every version of the app.
I'm using rails 4.2. Is this possible?

In rails guides there is an article What is Fingerprinting and Why Should I Care? which gives some insights about that hash on the end of a file and how it works.
Check your environments files. In production you may want config.assets.digest to be true.

You can put these images in public folder and can mention full url in views for these images
OR You can also put it on
vendor/assets/images
but in that case you would have to disabled precompile path
If you want to serve only some assets from your CDN, you can use custom :host option your asset helper, which overwrites value set in config.action_controller.asset_host.
<%= asset_path 'image.png', host: 'mycdnsubdomain.fictional-cdn.com' %>

Related

Am I handling the 'public' directory the right way?

I am using Ruby on Rails 4.1.1 and I want to add a linked image - my app's logo - in email messages but I had a doubt since my previous question.
By using files located in the public directory it seems that to link to an image in your Asset Pipeline you can use
link_to(LINK_TEXT_OR_IMAGE_TAG_HELPER, image_path(IMAGE_NAME))
but for those located in the app/assets it seems do not work the same, at least in rendered email messages in production mode. All assets that are compiled in Production have a fingerprint ID... is the fingerprint causing the load of static assets to do not render images in email messages?
I doubt since I would like to access images from both browser and email. I tried to solve the issue by moving the image from app/assets/images/logo.png to public/images/logo.png and by changing statements in my application.css.scss file from image-url("logo.png") to url("/images/logos.png"). However I do not know if I am following "the Rails way" or a "best practice". Do I? Should I add to the public directory all assets that I plan to use outside my application and in the app/assets directory all assets that I plan to use internally to my application?
For emails, it almostisn't any different compared to standard Rails views.
You can link to an image in your mailer using the image_tag helper you'd normally use in regular views as well:
<%= image_tag('some_image.jpg') %>
You also need to tell Action Mailer where it can find the assets, because it will use absolute URLs to refer to your images:
config.action_mailer.asset_host = 'http://www.example.com/'

Hotlinking to my Rails 4 app's assets from a static site

I have a rails 4 app on heroku, and I want to embed some of my image assets in a static website that I'm making.
The problem is that rails adds a digest to the asset path.
<img src="http://myapp.herokuapp.com/assets/tools/my-image-43b65377b7644fae3f34d288f3235b80.png"/>
This makes it very hard for me to hotlink to my assets, because their digests may change over time.
Is there anyway to embed my images without having to insert this digest? I know that rails 3.1 allowed you to do so.
In rails-4, non digested assets are not generated anymore.
If you want to hotlink assets, place a copy of image you'll use in public/. To avoid duplication, you can use a symlink pointing to the proper location in app/assets/images/.
It's worth noting that rails does a very good job at caching images in browser, and it is usually recommended to add far future timeout for assets caching in front server. So you should probably avoid to hotlink images that are prone to change often.

How should I handle the rails asset pipeline for uploaded images that change the scope of their public view?

After reading about how rails is handling image assets, I am confused and am having trouble deciding where to keep uploaded images in my app's directory tree. If a user has uploaded an image to my rails app, should I make the image_save_path /assets/images/ or /public/images ?
My concern/question: If I want to allow users to make their images public when they choose to do so, should an uploaded image that is 'un-published' (image is served only if current_user == image.owner) be considered more protected if it resides in assets/images instead of public/images? Equally protected? Less protected somehow?
Am I right to assume that the benefit of using the asset pipeline for images is simply that the file names get hashed in production mode and that's it? Is there some implied additional or diminished security here in terms of how the resource is served? Is this more a matter of subtle opinion or does the rails convention have something to say here?
Thanks!
EDIT1:
How would you handle uploaded content that you want to make available to the uploading user, but not discoverable to guests or other users? Should (can?) one store uploaded content outside the tree under web_root ?
Application assets are those assets that are part of your application, such as backgrounds and icons (in the case of images). The asset pipeline has nothing to do with user-uploaded images. I'd suggest to keep them separated, serve them from separate CDN if needed.
The hashing of filenames in the asset pipeline is done only during asset compilation, so a link to a specific image is made unique for the image contents. This helps to avoid setting complex caching headers to images and other assets, as when the image changes, the filename changes too, and the cached version won't be used at all.
All this does not apply to user-uploaded images, you are not going to compile on-the-fly the assets for their images.

Why should I use the Asset Pipeline to serve images?

In the Ruby on Rails guide to the Asset Pipeline, it says
Any assets under public will be served as static files by the
application or web server. You should use app/assets for files that
must undergo some pre-processing before they are served.
http://guides.rubyonrails.org/asset_pipeline.html
To me, this says that images should be kept in the public directory as they can be served statically by my web server and require no pre-processing.
Are there advantages to putting your images in assets/?
Asset precompile appends unique hash value to image filenames, which allows users to get latest version of it despite of cache or expire settings on the server. This is useful when you want to change images in website design.
You don't want to use /assets/images for images what are unlikely to change (like user uploads).
Because it would harm the versatility of the asset pipeline.
With images being served via the asset pipeline, if you change the asset pipeline (for instance, have it upload files to S3) you would have to then sync your images via some other task.
There may be other, deeper reasons, but that is what would give me pause.
EDIT:
Side note: In production thanks to assets:precompile everything from /assets/ will be served from public.

Where should my images go in Rails? What does precompile do exactly?

I'm using Rails 3 with assets pipeline enabled.
And I know images such as icons or logos should go in app/assets/images.
But where should I put images that may be a lot and big? For example images uploaded by the users, such as photos
I don't want them to be duplicated by precompile (not sure if it does that, I don't know how it works). And I want them to be ready to use as soon as they get uploaded.
Any ideas?
The image_tag wasn't working as expected. In the documentation it says 'By default, files are loaded from public/images', but that wasn't working.
The solution was to add /images to the path (with leading backslash, or it won't work)
<%= image_tag '/images/some_dir/some_image.jpeg' %>
Amazon S3 is a great, inexpensive way to store images that your users upload. I recommend using the Paperclip gem which integrates with s3. There's a section in the paperclip documentation with instructions on how to use s3. No clue what precompiling images means or how it applies to uploaded image files, but they will be available as soon the upload is complete. Using this also has some additional benefits such as acting as a backup system.

Resources