Why does Rails sometimes create an asset cache with the wrong permissions? - ruby-on-rails

I have an EC2 instance with the usual stack of Apache, Passenger, and Rails. The app is running in production, so Javascript files are cached into an all.js file.
Passenger is configured to pre-start the application instance using the PassengerPreStart directive.
On occasion, the all.js that is created by Rails in public/javascripts has the wrong permissions, 0600 for the deployment user. It's supposed to be 0640, so that Apache can serve the files (they're in the same group, www-data).
Do you have any explanation as to why this is happening? Is there any issue known with PassengerPreStart and Rails' asset caching?

I'm pretty sure this is because of the timestamps that come after the assets. If you do a view source the numbers after the asset/files are a timestamp and I think the browsers get confused, or rails messes it up or something.
You change the default of the timestamp to an empty string but putting the following code somewhere in your Rails application.
/application.rb
ENV[RAILS_ASSET_ID] = ""
That will set it to an empty string. See how that goes.

Related

confusing about autoload_paths vs eager_load_paths in rails 4

I read a post about the rails load_paths, here is the link.
But, I am still confused about the difference between the autoload_paths and eager_load_paths:
I have tested them in a newly created Rails 4 project. It seems that they run the same way, that auto-reload in the development mode but in the production mode.
Author of the linked article here. Here's an attempt to clear up the confusion, going off of #fkreusch's answer.
In Ruby you have to require every .rb file in order to have its code run. However, notice how in Rails you never specifically require any of your models, controllers, or other files in the app/ dir. Why is that? That's because in Rails app/* is in autoload_paths. This means that when you run your rails app in development (for example via rails console) — none of the models and controllers are actually required by ruby yet. Rails uses special magical feature of ruby to actually wait until the code mentions a constant, say Book, and only then it would run require 'book' which it finds in one of the autoload_paths. This gives you faster console and server startup in development, because nothing gets required when you start it, only when code actually needs it.
Now, this behavior is good for local development, but what about production? Imagine that in production your server does the same type of magical constant loading (autoloading). It's not the end of the world really, you start your server in production, and people start browsing your pages slightly slower, because some of the files will need to be autoloaded. Yes, it's slower for those few initial requests, while the server "warms up", but it's not that bad. Except, that's not the end of the story.
If you are running on ruby 1.9.x (if I recall correctly), then auto-requiring files like that is not thread safe. So if you are using a server like puma, you will run into problems. Even if you aren't using a multi-threaded server, you are still probably better off having your whole application get required "proactively", on startup. This means that in production, you want every model, every controller, etc all fully required as you start your app, and you don't mind the longer startup time. This is called eager loading. All ruby files get eagerly loaded, get it? But how can you do that, if your rails app doesn't have a single require statement? That's where eager_load_paths come in. Whatever you put in them, all the files in all the directories underneath those paths will be required at startup in production. Hope this clears it up.
It's important to note that eager_load_paths are not active in development environment, so whatever you put in them will not be eagerly required immediately in development, only in production.
It's also important to note that just putting something into autoload_paths will not make it eager-loaded in production. Unfortunately. You have to explicitly put it into eager_load_paths as well.
Another interesting quirk is that in every rails app, all directories under app/ are automatically in both autoload_paths and eager_load_paths, meaning that adding a directory there requires no further actions.
Basically, autoload_paths are paths Rails will use to try loading your classes automatically. E.g. when you call Book, if that class isn't loaded yet, it will go through the autoload_paths and look for it in those paths.
In production, it might be better to load those upfront to avoid autoload concurrent issues. For that, it provides the eager_load_paths. Paths in that list will be required upfront when your application starts.

Rails 3 asset dir accessible from CNAME root and app subdirectory simultaneously?

I have a rails 3.0.10 application that I have available within an application directory, like this:
https://apps.example.com/myRails3App
The server is RHEL 5 using passenger. Out of the box the application works great and I did not have to wrap my routes in a scope.
Then I set up a CNAME alias from a new domain to point at the application, like this:
http://great.vanityurl.com
Now, after redeploying the application and restarting the server, when I visit the application from apps.example.com/myRails3App all of my assets called from "stylesheet_link_tag" (or "javascript_include_tag") are looking for the assets at "apps.example.com/stylesheets" instead of the correct "apps.example.com/myRails3App/stylesheets" (though standard link tags are working correctly).
Meanwhile the application looks great from the vanityurl, since the reference to great.vanityurl.com/stylesheets resolves correctly.
It would seem that I should use something like Rails' "relative_url_root' but this is of course not available in rails 3.0.10 (as far as I am able to understand).
What should I do to make sure that the application looks and functions identically whether it is visited via the original location (apps.example.com/myRails3App) or the vanity url (great.vanityurl.com)?
You can fix your immediate problem using a combination of:
config.action_controller.asset_host = 'apps.example.com'
config.assets.prefix = "/myRails3App"
To directly control the URLs generated from the Rails asset helpers you're mentioning.
Winfield's answer would work for Rails 3.1, but 3.0 doesn't like 'config.assets.prefix='.
Thankfully, while it wasn't the final solution, he pointed me in the right direction with 'config.action_controller.asset_host=". After checking the Rails 3.0 api for asset_host=, I discovered asset_path=.
I ended up putting this in my application.rb:
config.action_controller.asset_path = proc { |asset_path|
if (Rails.env != "development_local") and (!asset_path.starts_with?("/myRails3App"))
"/myRails3App#{asset_path}"
else
asset_path
end
}
And during deployment I have my capistrano script generate a symlink from {app_root}/public to {app_root}/public/myRails3App, allowing all asset calls to myRails3App/stylesheets, for instance, to work whether or not the user is visiting from a URL in which the application directory is required.
This solution feels dirty, but it works.
Thanks, Winfield, for helping me get my application to be functional.

Rails production static files routing error

When I run my app locally in test/dev my views come up nicely and everything is happy. When I try to navigate to those same erb files running on my remote server/local production server I get errors like the following:
ActionController::RoutingError (No route matches "/stylesheets/scaffold.css")
I've seen similar questions here on SO but none have been able to solve my problem. The closest thing I've found to an answer is the first answer here: Rails 404 error for Stylesheet or JavaScript files
As I understand it the best thing to do would be to configure my webserver to serve static files. How do I do this locally/on Heroku?
Update
As per raidfive's suggestion I changed config.serve_static_assets from false to true and this fixed my issue. However, I see that it says in production.rb that Apache or nginx should already be serving static assets. Is it any less good/professional to serve static assets in this way and if so how would I achieve the desired results if I'm using Heroku?
Update 2
Apparently Heroku does this automatically, I had an extra comma that was causing the mischief. I was able to look in the extended Heroku logs using the following tip to track down the trouble. Thanks SO!
Are you using Rails 3? By default Rails 3 / webrick does not serve static files in production mode. You can easily enable this by setting
config.serve_static_assets to true in your production.rb file.
In Rails5, you should comment
"config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?"
in config/enviroment/production.rb

What does "dispatches" files in rails src folder mean?

I just look up at rails sources and find folder named "dispatches". There is four file in it. I want to know purpose of this files. I know I use this files on my production server, but I never used to think of their purpose. I know there is something about attaching Rails app to Apache server. On my production server rails appname command add this files to public folder automatically. Can I set up this behavior on my development machine?
The rails dispatcher is the entry point for a rails application and is used to bootstrap the environment.
They have a long history and in a lot of ways they are almost obsolete. In days gone by rails apps used to be powered using cgi or fastcgi, which was a way for the webserver to communicate with a rails process. The boot process would be initiated by dispatch.fcgi or dispatch.cgi. Nowadays people are more likely to use apache/nginx+passenger or apache/nginx+mongrel/thin. (Does anyone still use lighttpd?)
I'm a little fuzzy on how dispatch.rb is used, but I think it's used by upstream rails servers such as mongrel/thin to bootstrap the rails process. However, now that rails is rack compatible I'm not entirely sure if that has changed.
You don't need to pay the dispatch.* files any attention.
I hope this helps.

Rails image_tag is looking at my production server for assets!

I read that by setting ActionController::Base.asset_host, you can control where rails looks for assets. However, by default Rails should look in '/public/...'
Somehow my Rails app knows to look at my production address when in development mode and I have not set ActionController::Base.asset_host anywhere. I am not sure where it is finding this information. Is there anywhere else this can be set? I don't think my deploy recipes should have anything to do with it...
<%= image_tag 'my_logo.png' %>
causes Rails to check my production server for the file. Same with stylesheets.
I am not quite sure how Rails knew to look for my production domain. I removed it almost everywhere in my code. According to the docs, "By default, Rails links to these assets on the current host in the public folder" but I am not quite sure what that means. To prevent this from ever being an issue again and to allow some flexible configuration, I added asset host domains to my environment configuration. I now have something like:
EnvironmentConfig = YAML.load(File.read(Rails.root + "config/#{rails_env}" + 'environment.yml'))[rails_env]
ActionController::Base.asset_host = EnvironmentConfig['asset_host']
Everything works great now. Still don't know how Rails knew to look at my production domain.

Resources