Ivan Tkalin

I’m a software engineer. I solve problems.

Rails 4: Disable assets caching for development/test environments

Ruby on Rails by default caches pre-compiled assets (sass, coffeescripts) to tmp/cache/assets directory in development and test environments. It makes page loading in development and running test faster (when assets are already precompiled), but may cause some weird bugs.

For example, when I was upgrading my Rails 3.2 application to Rails 4, I noticed that there are deprecation messages on CI server, but not on my local machine. I started investigating it and found, that these deprecation messages come from SASS file in one of my gems (it was twitter bootstrap 2.0.1). And these deprecation messages appear on my dev machine only if I clean assets cache before running tests.

Another issue with file system assets cache in test environment, is that when running test in parallel (I use parallel_test gem), and assets cache is not built yet, tests may fail because of errors with concurrent access to cache files from different processes.

Main problem with file system assets cache in development environment was that cache was not always rebuilt when it needed to. For example, when I was upgrading to newer bootstrap version, new bootstrap stylesheets were not build and my development version looked pretty fine, but on production it was totally broken. I was able to reproduce it on my dev machine only after cleaning assets cache.

After facing all these issues, I decided to disable assets file system cache, and change it to memory cache. Which means, that cache is built and stored in memory while process (rspec or rails server) is active. It can be done by adding following code to application.rb:

# Use memory store for assets cache in development/test to avoid caching
# to tmp/assets, because it causes hiding of deprecation messages in
# stylesheets, sometimes break parallel_tests and doesn't always refresh
# gem stylesheets in development
config.assets.configure do |env|
  if Rails.env.development? || Rails.env.test?
    env.cache = ActiveSupport::Cache.lookup_store(:memory_store)
  end
end

I found that for my application, assets cache is built pretty fast, and I didn’t notice any significant performance penalties after doing it. And I didn’t notice (yet) any other downsides of this approach. Now I have a little bit more control over my front-end code and it makes me feel better.