2

First let me start by saying I'm a complete novice when it comes to Ruby & Rails, so hopefully I'm not making a noob mistake.

I've picked up the source for an app which I have successfully deployed to heroku; and running in development mode it works fine but when I switch it to production mode the images are not shown.

The app is using the assets_sync Gem and the images as well as other assets should be served from AWS using an S3 bucket. The css and js files are coming through correctly but not the images. This article explains quite well how it should work https://firmhouse.com/blog/complete-guide-to-serving-your-rails-assets-over-s3-with-asset_sync

As far as I can tell the css and images are precompiles; with the css generated from sass, and the images combined into one sprite. I found this article useful for explaining what was going on here http://compass-style.org/help/tutorials/spriting/ (probably nothing new for experienced rails developers)

If I dig a little deeper and view the css of the running app the background image url property is missing the bucket name from the url.

Here's an example; I'm certain the part //.s3 should be //mybucket.s3:

someclass {
    background: url(http://.s3.amazonaws.com/assets/myicon.png)
}

If I take the url and place directly in the browser address bar - no image!. But as soon as I add the bucket name the image is downloaded. That is, the following works, which confirms the images exist on the s3 bucket.

http://my-bucket.s3.amazonaws.com/assets/myicon.png

This implies the css isn't precompiled correctly and perhaps can't find the bucket name from the config.

I've checked that the heroku config is correct. With the following set:

  • FOG_PROVIDER,
  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • FOG_DIRECTORY
  • FOG_REGION

I've hit a wall with this spending a fair bit of time Googling the issue without result. So has anyone seen this issue before, or suggest ways of working out what could be going wrong?

Chris Moutray
  • 18,029
  • 7
  • 45
  • 66

1 Answers1

2

Okay, welcome to the Rails community!


Precompile

From using the asset_sync gem ourselves, the best advice I can give is to precompile locally before pushing to Heroku. Further, you have to do several things to get it working:

  1. You need to use the asset_path_helpers in your CSS
  2. You need to change the asset_path for your production environment, to reflect the S3 implementation

Here's what you need to do:

--

Preprocess

#app/assets/stylesheets/application.css.scss #-> notice the SCSS
someclass {
    background: asset_url("myicon.png")
}

You need to use one of the css preprocessors in Rails (basically SCSS), to give you the ability to use the dynamic asset path helpers. This is the first step, as it will then reference your assets correctly.

--

Asset Host

Secondly, you then need to change the asset_host in your /config/environments/production.rb file:

#config/environments/production.rb
config.action_controller.asset_host = "//#{ENV['FOG_DIRECTORY']}.s3.amazonaws.com"

This will allow Rails to prepend the correct URL to your asset paths when you're creating them, thus allowing you to serve them from S3

--

Finally, you should always precompile locally when using asset_sync. I forgot the reason why, but it's essentially to get all the files in the correct order etc:

$ rake assets:precompile RAILS_ENV=production

This allows asset_sync to upload the files it requires to run correctly. Or at least it should :)

Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • 1
    Thanks Rich very helpful. I've already got *Asset Host* in the production config. So that's a good start. I'll try the final point first and try a local precompile and then if this doesn't work I'll focus on the css asset helper, since this looks like the problem. – Chris Moutray Aug 13 '14 at 08:28
  • But could you expand on the final point? If I precompile locally, what then? Do I (git) commit the assets now generated to `/public/assets` and (git) push to heroku... and heroku will just sync them rather than do another precompile? – Chris Moutray Aug 13 '14 at 08:30
  • 1
    The `asset_sync` gem is actually very simple - it just copies the files created in your precompile process & sends them to S3. The caveat, at least in my experience, is that this only works in `development` (rather than performing the precompile in production). So if you precompile locally (`asset_sync` will send your assets to S3), and then you can just push as you would normally to Heroku – Richard Peck Aug 13 '14 at 08:37
  • I'm a little stuck with the first point in that a sprite file and the css styles are magically generated from the icons. So it seems I don't have control over use of css preprocessors. – Chris Moutray Aug 13 '14 at 13:37
  • What do you mean by the sprite Chris? – Richard Peck Aug 13 '14 at 13:57
  • 1
    Thank you for your patience Rich :) As far as I can tell the app is doing this http://compass-style.org/help/tutorials/spriting/ - there is a folder with icons and there's the file app.scss with the line `@import "icons/*.png";` this seems to combine the png's, to produce a sprite ie a single png and I'm assuming it creates a style for each with a different background position. – Chris Moutray Aug 13 '14 at 14:47