Javascript – Ruby On Rails 3.1 – assets pipeline – assets rendered twice

asset-pipelinedevelopment-environmentjavascriptrubyruby-on-rails

Big Update:

As I finally found the real solution, I also discovered the real problem. As I wrote down here a lot of useless information, considering the real problem, I'm making a huge update of the question so that other people can find easily what's going on and can see the solution.

The Problem:
It's because of the assets pipeline of Rails 3.1

Actually… It's an easy one: the assets were rendered twice in development-environment. Doing lot of investigations shew me that my Rails 3.1 server was rendering the assets from both the "app/assets" and "public/assets" folders. So, I had every .js and .css files duplicated, which was breaking all my javascript animations (yeah… binding twice the same event and handler to the same element is not what you want… normally).

And if the problem appeared all of a sudden, that was because I had to run "rake assets:precompile" to deploy my application. Since that, when my application was running in development, the server was rendering the static precompiled assets and the dynamic precompiled assets.

The solution (there's now a better one few lines below) – but you can still read it

First one: I just had to delete all the precompiled assets from my public folder.

Better one: Add config.serve_static_assets = false to development.rb which will prevent loading files from /public/assets. Also, don't forget to reset your browser cache.

[Edit: July 20th 2012]

Advanced one: I recently had a new problem because of those static assets. You know, when you use paperclip or some other gem and they add your images in your public folder in some system sub-folder because it's better if you want to deploy your application using capistrano. Well, that's great but! As we added config.serve_static_assets=false, those images aren't rendered in development and that's bad if you want to do some css on them. So! What to do then?

Well in fact you'll have to turn on static assets in development like so:

# Expands the lines which load the assets
config.assets.debug = true
config.serve_static_assets = true

Then to prevent rails from rendering your other assets twice (the precompiled ones), just do this command:

rake assets:clean

It's the opposite of rake assets:precompile and will clean your public/assets folder so that Rails won't render your assets twice. Of course you'll still have to clean your browser cache and clean your assets each time you precompiled them.

[Edit: November 18th 2013] – From @idejuan answer

Another solution:

You can add this line:

config.assets.prefix = '/dev/assets'

To development.rb, where the prefix can be whatever you want. Scripts will not load twice anymore, and images in /public/system will be read! But be carefull as it changes the path to your "static" assets… if you require assets from a gem, it might not load them properly in development…

[End edit]

The remaining question with answer!

Well, why my development application was rendering static precompiled assets?

In fact if you precompile your assets localy, rails render assets from the public folder AND from the assets folder in development and test environment by default. Normally assets from the public folder should overwrite those from the assets folder, but it's not the case and even if it does, we would lost the benefits of the "debug_mode" as we would have to precompile assets each time. So… Assets are rendered twice when precompiled locally in development and test environment.

So, by adding "config.serve_static_assets = false" to your development.rb file, you somehow overwrite the default line that telling Rails to look in your public folder for assets. I hope they'll do something cleaner one day about locally precompiled assets.

Thanks to the ones who helped me for my investigations :).

Kulgar.

Best Answer

You might want to look at

https://stackoverflow.com/a/7854902/686460

"Adding config.serve_static_assets = false to development.rb will prevent loading files from /public/assets"

I think that is a better solution than what you are suggesting here.