URL for an image in the Assets directory of Rails - ruby-on-rails

I need the public facing url of an image in my app/assets/images directory.
On development, I can navigate to the image by hitting localhost:3000/assets/image.jpg.
However, when I push this app to heroku, that url no longer works.
I can't visit my_app.com/assets/image.jpg or I get a routing error saying "No route matches get assets/image.jpg."
How can I navigate to that URL? I am not really interested in helper methods to generate the URL, I just need the full length url.

Are you including the rails_12factor gem in production? This will do a number of things for you, including set config.serve_static_assets to true which is false by default in production.

Related

Rails assets controller serves public assets instead of assets' index page

In my Rails app, I have an assets controller (Since the requirement of the model name is Asset).
I use
resources :assets
to route my controller to this URL to display /assets.
Everything works fine in the development mode. However, after I deployed the application on AWS Beanstalk, it displays Error 404 from Nginx.
After going through Nginx error log file in /var/log/nginx/error.log, I found this.
open() "/var/app/current/public/assets" failed (2: No such file or directory), client: 172.31.21.101, server: _, request: "GET /assets?status=active HTTP/1.1"
What I understand from the log, it means the application tries to look for assets /var/app/current/public/assets instead of GET /assets route.
Therefore, my question is, how can I make the application serve the assets folder the view file? Or is there any workaround? One solution I can think of is changing the assets folder to something else.
It's a name collision of the routes you're creating.
As of default, rails assets are stored in public/assets. Rails then tries to use xsendfile (if you have it correctly configured) to deliver the given asset from the public directory.
To avoid these collision, you can either change your RESTful route to a name other than :assets or you can customize the asset prefix with this code:
# config/application.rb
config.assets.prefix = '/some_other_path'
EDIT: I highly recommend to rename the RESTful route, because some poorly written gems do not use assets.prefix but the hardcoded /assets path. Nested routes could be also fine if it is possible. (Thanks to Gabor Garami)

Rerouting to AWS hosted assets from a Heroku Rails app

I have a Heroku hosted Rails app that has reached the 300MB limit for the slug size and can no push to Heroku. To fix this issue, I've setup an AWS S3 account and want to redirect the assets being requested from my Rails app to the new S3 location. The Rails app is basically just serving JSON files that point to the static assets using a relative URL. An iOS app using the Rails JSON then has a hardcoded domain URL, and appends the path to the resources to that domain and requests assets it needs.
I want to update my Heroku app and change my asset locations without requiring an update to the iOS app in order to change the asset domain. So, I need to redirect static asset requests from the Rails app to the AWS server.
In my git repo, I've ignored the assets in the public folder that I've moved to the AWS server. The asset files are present on my local machine, but are not part of the git repo when uploaded to Heroku.
So far I've tried changing the config.action_controller.asset_host which does not seem to work since these are static assets and are being returned by the web server before Rails gets it.
I tried using routes rules to redirect to a different domain, but these routes never seem to be captured. The static files appear to be returned before the Rails app has a chance to handle the request.
I've tried using the rack-rewrite gem to try and redirect my assets to a different domain with the following in `initializers/rack_rewrite.rb:
require 'rack/rewrite'
AppNamespace::Application.config.middleware.insert_before(Rack::Lock, Rack::Rewrite) do
r301 %r{/images(.*)}, 'http://my-subdomain.amazonaws.com/images$1'
end
This doesn't seem to work either and it always just returns the static files.
So far I've been trying for hours to figure out the proper way to handle this situation. I'm not a Rails developer by trade, I build iOS apps, so please let me know if I'm going about this the wrong way or completely missed the "right" way of doing this.
I solved this using routes and the 'rails_serve_static_assets'. I had to move the local images out of the public folder in order to avoid Nginx from returning the images before hitting the Rails app. The route ended up like so:
match '/images/(*path)', :to => redirect { |params, request|
"#{Rails.configuration.assets.aws_url}#{request.path}"
}

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/'

Can I Identify The Environment Using HTML Code?

I just figured out how to create custom error pages in the public folder using I18n. Those error pages have links that will return the user to a page in the application such as the home page.
When my application was running 3.2.13 I had the custom error pages in the app folder using config.exceptions_app = self.routes in application.rb. When I had that code all I had to do was use a link_to statement pointing to the route I wanted the user to return to. If I was in the development environment it would go to http://localhost:3000/somelink and in production it would go to http://myrailsapp.com/somelink. I replaced these with the ones in the public folder after rewriting them in Rails 4 because it appears that config.exceptions_app = self.routes is ignored in Rails 4.
My error pages in the public folder are html, not html.erb so there is no ruby/rails code. I would like to replicate what I had previously where I can check the environment in my error pages and point to localhost for development or my domain URL for production. I currently have code in my error page similar to this:
My Link Text
I'm definitely open to changing these to html.erb files. I initially thought about that but from my research and trying what I found nothing is working for Rails 4.
Any help would be appreciated.
You don't need any "autodetection" in html, just cut the domain part from the url and use a local path instead.
Just change http://myrailsapp.com/en/home to /en/home.
And yes, you do need the opening slash to be independent from the current_url in your link.

Heroku Image URL change

I'm developping a Rails4 application with heroku hosting, and i encounter a bit of a problem:
I have a helper method to randomly pick an image by its path in /assets/images/path_to_image and this helper method is called in my HAML file. It works perfectly in my local environment. The images urls are stored in the DB. The problem is that Heroku changes the image names from logo.jpg to logo-a6d14b20c77aa6466e616313edcd3d34.jpg which makes my helper method useless. Any idea on how i could solve this problem? Is it a matter of pre-compiling the assets ?
Thanks a lot
B.
In rails4 by default assets gets the digest URL with them and getting served.
If you want you can use some middleware to redirect assets from non digest path to digest path.
or you can turn off the digest in production.rb file all together like below.
config.assets.digest = false
If you want that redirect solution I can post here as well.
Let me know!
Is it a matter of pre-compiling the assets?
Yes, I would say so
The problem you've got is that production environments compile all your assets, and consequently give you the hashed file-name you're seeing. The reason why this is a problem is that if you're referencing a static file (logo.png) in CSS or HTML, the compiled path will be different, causing the problem to occur. We learnt if you're going to reference any assets, always use a dynamic file (.scss / .haml / .html.erb) and then use the provided helpers
The way around this is to use the asset path helpers, which are basically like this:
image_path
asset_path
Heroku
It seems you're well versed with Rails so I don't bore you with the details
Heroku works best by serving static assets & pre-compiling them before you deploy:
#config/production.rb
config.serve_static_assets = true
You then need to pre-compile the assets with the production environment, like this:
> rake assets:precompile RAILS_ENV=production
This goes through your assets & assigns all the correct paths, if you've used the asset path helpers as mentioned above. After that, push to heroku & I always pre-compile the assets when on Heroku too (we use the asset_sync gem):
> heroku run rake assets:precompile --app [app_name]

Resources