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)
Related
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}"
}
I'm using Carrierwave to handle file uploads. Files get stored under public/uploads/. Project uses Ember.js templates, and the img tags point to the proper src. (I've verified that the files are present at those paths.) However, the server returns a 404 for each.
It looks like this is a common problem, and the common solution is to:
config.serve_static_assets = true
However, this isn't working. I'm still getting 404s. Any other ideas about how to deal with this?
It should be noted that I'm not using Apache or nginx.
Rails no longer compiles the assets without digests. In order for this to work properly, you need to use a rails helper to include the proper asset name (with the digest), or use a gem like https://github.com/alexspeller/non-stupid-digest-assets as a workaround.
I'm making a blog system for my Rails application and I'm stuck with this problem a while and don't know what's going on with my routes.
I installed a template for my app and all the css/js/images files from this template are in "public/" not in the assets folder. It was the only way I found to make the template working.
My blog system have this routes:
When I access "/blog" it serves the index view and it loads all the assets from "assets" and "public". But when I try to access "/blog/" or the matched route "/blog/category_slug/post_slug" rails tries to load the files from "public/" with this URL:
"base_url/blog/category_slug" and that's really weird!
I'm current using Rails 4.0.2. Any thoughts?
Fixed the problem adding a "/" before the path to the assets:
From: "css/bootstrap.css"
To: "/css/bootstrap.css"
I still don't know why this only happens in the blog controller, but that worked.
Thanks.
I may be wrong here, but routes are automatically generated for files in your public directory.
So if this was in your rails project
public/images/cat.jpg
You could literally type " public/images/cat.jpg " and it would appear in the browser. Is there anyway to rake routes and get these asset routes? Or they not actually roots? Do they work differently?
#{RAILS_ROOT}/images/cat.jpg
That will do.
They are not actually routes, they are considered "static assets" and are simply served up as is.
From the Rails asset pipeline documentation:
Any assets under public will be served as static files by the application or web server.
So in the end, there's nothing really special about them; they are merely served up. That's about it.
Also, the URL www.example.com/public/images/cat.jpg will not work, you'll need to ditch the public part, so that it appears like www.example.com/images/cat.jpg, or simply /images/cat.jpg if this is a link.
The Rails Asset Pipeline guide instructs you to use config.assets.paths in config/application.rb but I don't have access to the request's subdomain at this point.
I'd like to be able to prepend an extra path (for the current request only) based on the request's subdomain.
My application specific details
It's a basic CMS app. The root domain.com host handles the administrative part with standard controller/view rendering and default asset paths.
Requests to subdomain.domain.com renders the site based on subdomain. It calls prepend_view_path in a before_filter and adds Rails.root.join('vendor/sites/[subdomain]/templates') for the current request only.
I'd like to be able to prepend Rails.root.join('vendor/sites/[subdomain]/assets') to the Sprockets search paths when the request host is [subdomain].domain.com.
EDIT
I ended up just dropping in a mixin for Sprockets::Environment that overwrites the call method:
module SiteAssetsResolver
def call(env)
begin
# prepend path based on subdomain (from env)
super # Sprockets::Server#call
ensure
# remove path based on subdomain
end
end
end
MyApp::Application.assets.extend(SiteAssetsResolver)
Just as you did for your view path, add a before filter and append the new path to Rails.application.config.assets.paths
I got this idea while watching Railscasts #279 Understanding the Asset Pipeline
I agree with commenter on your question that said "The asset pipeline isn't really meant to be compiling your assets each request in production." -- making it not really possible to do exactly what you ask.
So how about an alternative to accomplish what you're really trying to accomplish here, which is different asset resolution for different subdomains. Put your sub-domain specific assets in sub-directories of your asset folders.
Now, in the view/helpers, when you call asset_path or any other helpers that take a relative asset path, ask it for "#{subdomain}/name_of_asset" instead of just "name_of_asset".
Now, because of the way the asset compiler works, it's possible this subdirectory method won't work, you may have to put the subdomain at the beginning of the actual filename instead. "#{subdomain}_name_of_asset". Not sure.
And this still wouldn't give you a sort of 'default fall through' where some assets in some subdomains don't have subdomain-specific assets, they just 'fall through' to the default. Which would be nice. It's possible a way can be figured out to do that too, not sure.
But at any rate, following this approach of asking for a different asset at display-time using logic in view/helper.... is going to get you further than your original suggested approach, which probably isn't possible.