rubygitherokuruby-on-rails-5asset-pipeline

Assets pipeline rails Heroku


Recently I upgraded my project to Rails 5 and I'm going crazy with the assets pipeline when trying to upload everything to Heroku.

The issue is the following: I have a collection of Ejercicios and, when u click on one of them, the app should show its information, including an image. The routes to the images are stored in my db like this img1: "ejercicios/abdominales/1_4_I1.bmp". That file, for example, would be on app/assets/images/ejercicios/abdominales/1_4_I1.bmp.

The related view show.html.haml prints the images like this: = image_tag(@ejercicio.img1) if @ejercicio.img1?.

It worked perfectly on local but not in production in Heroku, so read about the assets pipeline in order to make it work. So I changed my show.html.haml like this: = image_tag asset_path(@ejercicio.img1) if @ejercicio.img1? and I added the lines the tutorial mentions in Gemfile and application.rb. The executed bundle install and bundle exec rake assets:precompile RAILS_ENV=production, added the new 'public' folder to my git, committed and pushed my git, and finally pushed everything to heroku.

But it doesn't work, the 'alt' of the image is shown. Using the inspector I can see that the images in the html follow the normal url to the image and not the one with the fingerprint, so the helper asset_path seems not to be working properly.

Here's my production.rb in config/environments

KeepMeFit::Application.configure do

  config.eager_load = true
  config.cache_classes = true

  config.consider_all_requests_local       = false
  config.action_controller.perform_caching = true

  config.serve_static_assets = true

  config.assets.compress = true

  config.assets.compile = true

  config.assets.digest = falsenginx

  config.force_ssl = true

  config.i18n.fallbacks = true

  config.active_support.deprecation = :notify


  config.action_mailer.default_url_options = { :host => "http://keepmefit.herokuapp.com/"}
end

My 'application.rb' in 'config':

require File.expand_path('../boot', __FILE__)

require 'rails/all'

require 'will_paginate/array'

if defined?(Bundler)
  Bundler.require(*Rails.groups(:assets => %w(development test)))
end

module KeepMeFit
  class Application < Rails::Application
    config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
    config.i18n.default_locale = :es

    config.encoding = "utf-8"

    config.filter_parameters += [:password, :password_confirmation]

    config.active_support.escape_html_entities_in_json = true

    config.assets.enabled = true
    config.serve_static_assets = true

    config.assets.initialize_on_precompile = false

    config.assets.version = '1.0'

  end
end

And my Gemfile:

source 'https://rubygems.org'

ruby '2.3.3'

gem 'rails', '5.1.4'

group :development, :test do
    gem 'sqlite3'
  gem 'activemodel'
  gem 'json'

    gem 'rspec-rails'
    gem 'guard-rspec'
    gem 'rb-notifu'
    # gem 'railroady'
end

gem 'rails_12factor', group: :production
group :production do
    gem 'pg'
end

group :test do
    gem 'capybara'
    gem 'factory_girl_rails', '4.1.0'
    gem 'launchy'
end

group :development do
    gem 'annotate'
    gem 'better_errors'
    gem 'binding_of_caller'
    gem 'meta_request'
end


group :assets do
  gem 'sass-rails'
  gem 'coffee-rails'
    gem 'coffee-script-source', '1.8.0'

  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'
gem 'bcrypt', '~> 3.1.11', platforms: [:ruby, :x64_mingw, :mingw]

gem 'haml'
gem 'haml-rails'

gem 'bootstrap-sass'

require 'rbconfig'
gem 'wdm', '>= 0.1.0' if RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i

gem 'modernizr-rails'

#gem "font-awesome-rails"

gem 'bootstrap-datepicker-rails'
gem 'tzinfo-data'

gem 'faker', '1.1.2'

gem 'will_paginate', '~> 3.1.0'
gem 'bootstrap-will_paginate'

gem 'turbolinks'
gem 'jquery-turbolinks'

gem 'friendly_id'

gem 'gon'

gem 'cloudinary'

Solution

  • The asset pipeline has basically two use-cases:

    First, it precompiles and combines various stylesheets or JavaScript file into single bundles. Being able to precompile — for example — SCSS to CSS simplifies development. And one big combined files can be downloaded faster than many small files.

    Second, it adds hashes to the filenames. This allows caching these files for a long time, which improves performance too. Even if there is only a small change in one of the files, then the hash and therefore the filename will change. The changed filename will not be in the cache and therefore the browser reloads the file immediately.

    But in your case, your images are static anyway. There is no point precompiling images and adding hashes to files that are not supposed to change.

    Therefore, I would just put that images directly into the public folder and would bypass the asset pipeline for these kinds of static images.