Preventing Heroku from using precompiled assets in development mode - ruby-on-rails-3

Currently it seems Heroku is determined to pre-compile assets when I push my code up to my instances.
This is great for production servers, however for my "RAILS_ENV=development" server, this causes issues, as I now get pages with all the JavaScript files served up individually from my asset manifest, and then another file with the same code all grouped up as the pre-compiled asset.
This cause my jquery datatables libraries to break, throwing popup errors, which I don't get on my local environment (development or production) or in my production Heroku instance.
Is there anyway to disable pre-compilation of assets on Heroku for development mode instances ? Or is there any reason why these aren't already disabled on development Heroku servers already ?

If Heroku detect a public/assets/manifest.yml file then they will not attempt to precompile your assets and assume you are dealing with them yourself. More details at http://devcenter.heroku.com/articles/rails31_heroku_cedar

AFAIK, Heroku has to precompile assets to work around their readonly FS and the fact that the Rails asset pipeline wants to write files to the FS. The only thing I could suggest would be to work out why your assets are breaking when being compiled.

I worked around this by adding some voodoo to my Rakefile to disable the assets:precompile rake task.
first I add the user-env-compile labs component
heroku labs:enable user-env-compile
then add this to the beginning of my Rakefile
# found from http://blog.jayfields.com/2008/02/rake-task-overwriting.html
# used by conditional heroku asset compile magick
class Rake::Task
def overwrite(&block)
#actions.clear
enhance(&block)
end
end
Then I add this rake task in lib/tasks/disable_assets_on_heroku.rake
if ENV['RAILS_ENV'] == 'development'
namespace :assets do
task(:precompile).overwrite do
puts "Asset precompile skipped in #{ENV['RAILS_ENV']}"
end
end
end

Related

Rails and Bundle for production with Passenger missing assets

We're having a small issue with our app. Currently we've made an update of the internal design and uploaded to the server, however running the following;
RAILS_ENV=production bundle exec rake assets:precompile
only precompiles certain items into the asset folder under public directory. Anyone else ran into the problem like this with suggestion how to fix. We have everything set correctly in environments and initializers.
Sounds like some files are not getting into the precompile list. Try adding this to your config/application.rb
config.assets.precompile = [/^[^_]/]
This should be a catch all that will pick up all your js and css. Let me know if that works for you guys. Also you should be sure to tell that guy that you are listening to that deploying via FTP is silly.

Rails asset pipeline tests pass production broken

I had the following problem with the asset pipeline.
I have an HTML email with an image inside.
I have tests covering the case in which the email is sent successfully.
All tests pass.
When going to production, the feature requiring the email to be sent is broken, because the HTML layout is referencing a non existent image.
This obviously applies to all precompiled assets.
It seems to me that suddenly tests are no longer reliable. Is there any way to avoid this situation to happen again?
I found the perfect solution form my own case. If you set
config.assets.compile = false
config.assets.digest = true
in test environment, your tests will rely on precompiled assets.
Since it is annoying to precompile assets every time during quick development and testing phases, in my case it's enough to have this configuration on CI only.
You can setup an initializer called ci_config.rb with the following:
if ENV['CI']
class YourApp::Application
config.assets.compile = false
config.assets.digest = true
end
end
And configure you CI to run rake assets:precompile on start and rake assets:clean on end.
Compare the default configuration options in application.rb, production.rb and development.rb, and read Configuring Rails Applications in Ruby on Rails Guide to learn options.
Important options are, followings:
config.serve_static_assets: set this to false (production default), then, rails will not serve static contents.
config.assets.compile: whether compile assets using asset pipeline to compile if needed.
If you set above two options to false (that's the default for production), then you need to 1) precompile and place static contents at proper places, 2) configure web server (apache or nginx, may be) to serve static contents as needed.
So, for production, you need not only place the files, but also configure web server to serve them OR you can configure serve_static_assets to create assets on-the-fly. You may need to adjust test configuration but for test serve_static_assets is true unless you change it.

Are Files in Public/Assets Required with Asset Pipeline?

I'm in the process of upgrading a 3.0 Rails App to 3.1.4 including the Asset Pipeline.
I'm on Heroku, so I'm I have this in my application.rb
config.assets.initialize_on_precompile = false
I noticed that when I run:
bundle exec rake assets:precompile
it creates files in a public/assets directory (even though my assets are in app/assets already).
For example, it creates files like application-72b2779565ba79101724d7356ce7d2ee, as well as replicating the images I have in app/assets.
My questions are:
(1) should be uploading these files to my production server?
(2) if I'm suppose to be uploading these, am I suppose to update each application-xxxxxxxx or only the latest one?
To your first question: Heroku will not allow you to modify the filesystem. So your assertion is correct- You will need to pre-compile the asset pipeline before you send it up to Heroku, so that it can be utilized in your production environment.
And the latter: You'll want to make sure you have the latest compilation. Any others wont be used. The "xxxxxxx" portion is to make sure that your users have the latest and greatest version of your assets. It's a way of versioning what the browser gets, and making sure they're not caching a bad copy of the JavaScript, when you want to set up their cache to hold on to the JS and CSS files as long as they can, instead of constantly getting it from your web server.
Take my Heroku comments with a slight grain of salt, as I have not deployed to Heroku before. I just know how their system works to some degree.

Rails 3.1 precompiled assets breaking javascript remote_forms in production mode

I've fixed all the errors about "xxx" is not compiled and all the assets show up -- when running locally everything works fine:
All ajax requests work
Form submissions use the rails remote tag and fire off properly
However when running in production mode locally (and on Heroku):
Some ajax will work -- however things like PUT's that should be updatating records (and do in dev) don't... They will hit the page but not do the actual database update
Remote forms are completely broken and resulting in regular form submission
The source can be cloned from here: https://github.com/bluescripts/reru_scrum
Maybe I'm miscompiling the assets wrong or maybe I'm missing an appropriate include in my application.js file?
I've been compiling via:
rake assets:precompile
You're missing //= require jquery_ujs in your application.js. This file comes with jquery-rails gem and is responsible besides other things for handling remote links and forms.
Btw, I'd suggest removing .Gemfile.swp from your repo and adding .*.swp to .gitignore.

Rails 3.1 asset pipeline production w/out javascript runtime environment

I am struggling with the idea of deploying a large app using the the asset pipeline and the precompile Capistrano task.
I don't want to install the javascript runtime environment and precompile the assets on each production server.
The assets need to be uploaded to two Nginx servers that don't have a copy of the app.
So I have created a Capistrano task that precompiles the assets locally and then uploads the assets to the the Nginx servers, and the manifest files to the app servers.
The problem is the assets on my local machine could differ from the assets the git branch I am deploying from.
Is there a better way or must I just be dillagent to always deploy from the correct clean branch?
Edit here is the cap task that does the precompile and upload
namespace :assets do
after "deploy:update_code", "assets:precompile"
after "assets:precompile", "assets:upload_assets"
after "assets:precompile", "assets:upload_manifest"
desc "precompile assets"
task :precompile do
run_locally("bundle exec rake assets:clean && bundle exec rake assets:precompile RAILS_ENV=#{rails_env}")
end
desc "precompile and upload assets to webserver"
task :upload_assets, :roles => :nginx do
top.upload( "public/assets", "/usr/local/fieldphone/#{rails_env}/", :via => :scp, :recursive => true)
end
#
desc "upload manifest file"
task :upload_manifest, :roles => :app do
top.upload( "public/manifest.yml", "#{release_path}/public/", :via => :scp )
end
end
You say that assets on your local machines could differ from that on the deploy branch. In normal circumstances your dev environment doesn't need compiled assets.
That being so I'd suggest that you alter your task to remove the assets once they have been deployed, leaving your local working copy clean at all times. This would guarantee that each deploy gets the latest (correct) version of files. (If you are not doing so, I'd also suggest that you use the default options for dev mode which relies on Sprockets to do all the asset serving).
I don't think there's anything really wrong with committing the files to the repo and deploying that to the Nginx server - that's similar to the vendor cache for gems - it's redundant, but there for a reason.
Another option would be to actually deploy the app to your Nginx servers, and have Capistrano compile the assets there, but not start the app on those servers (create a Capistrano role for "assets" and deploy the app to it, but don't launch it on that role). This could get a bit messy...
As a last option, if you don't want to muddy the waters of your asset servers, or want to keep your options open for deploying assets somewhere else, you could have Capistrano git stash any unsaved changes first, checkout the master branch, and then compile the assets, upload them, remove them, checkout the previous branch (git checkout -), reapply the stashed changes (git stash apply --index), and continue! :)
Resources:
http://git-scm.com/book/en/Git-Tools-Stashing
Is there any way to git checkout previous branch?