Amazon S3 for Your Ruby-on-Rails App

With the increased application penetration into the clouds, users may face the issue of keeping data in a cloud storage. One of the most popular solutions in this area is Amazon Simple Storage Service (Amazon S3).
Getting started with Amazon S3
First, we need to include support for Amazon S3 in the Amazon Web Services (AWS) account.

Create a bucket for your project, but remember that a name must be unique across all Amazon S3 accounts. Then, you are able to manage access permissions to your bucket in the Properties tab.

After this, we can go to our Ruby-on-Rails 3.0 application and start configuring it to interact with Amazon S3. Most of Ruby-on-Rails 3.0 gems that support cloud storages use the fog library.
Configuring CarrierWave uploader
One of the popular uploaders—CarrierWave—has a description of how to store uploads on Amazon S3. You can initialize a storage type in the Uploader
class.
class AvatarUploader < CarrierWave::Uploader::Base
storage :fog
end
You can do the same in initializer
.
#config/initializers/carrier_wave.rb
CarrierWave.configure do |config|
config.storage = :fog
end
Now, we have an issue with the development and test environments. We don’t need to use Amazon S3 in these environments. I suggest that we do a simple trick: put a storage type into your config file and use initializer
.
#config/config.yaml
development: &development
carrier_wave:
storage: file
production:
amazon:
provider: AWS
bucket: altoros-blog
aws_access_key_id: \YOUR KEY\
aws_secret_access_key: \YOUR SECRET\
carrier_wave:
storage: fog
test:
<<: *development
#config/initializers/carrier_wave.rb
CarrierWave.configure do |config|
if (APP_CONFIG[:carrier_wave][:storage] == 'fog') && APP_CONFIG[:amazon]
config.fog_credentials = {
provider: APP_CONFIG[:amazon][:provider],
aws_access_key_id: APP_CONFIG[:amazon][:aws_access_key_id],
aws_secret_access_key: APP_CONFIG[:amazon][:aws_secret_access_key]
# :region => 'eu-west-1'
# :host => 's3.example.com'
# :endpoint => 'https://s3.example.com:8080'
}
config.fog_directory = APP_CONFIG[:amazon][:bucket]
config.fog_public = false
config.storage = :fog
else
config.storage = :file
end
end
Configuring assets
Another useful gem that will help us to store assets on Amazon S3 is Asset Sync. To configure this gem, we should tell it a path where we want to store assets.
#config/environments/production.rb
config.action_controller.asset_host = "//#{ APP_CONFIG[:amazon][:bucket] }.s3.amazonaws.com"
The default matcher for compiling files includes application.js
, application.css
, and all non-JavaScript/CSS files (i.e., .coffee
and .scss
files are not automatically included, as they compile to JavaScript/CSS).
To include specific files, you should put them to a precompile config.
#config/environments/production.rb
config.assets.precompile += ['admin.js', 'admin.css', 'common.js', 'common.css']
To include all your asset files, you should put the following regular expression to config.
#config/environments/production.rb
config.assets.precompile << /(^[^_\/]|\/[^_])[^\/]*$/
We should also configure asset_sync
. We can generate a default config file by executing the Rake task.
rails g asset_sync:install --provider=AWS
Then, we should put the Amazon S3 config information in it.
#config/initializers/asset_sync.rb
if defined?(AssetSync)
AssetSync.configure do |config|
config.fog_provider = APP_CONFIG[:amazon][:provider]
config.aws_access_key_id = APP_CONFIG[:amazon][:aws_access_key_id]
config.aws_secret_access_key = APP_CONFIG[:amazon][:aws_secret_access_key]
config.fog_directory = APP_CONFIG[:amazon][:bucket]
# Increase upload performance by configuring your region
# config.fog_region = 'eu-west-1'
#
# Don't delete files from the store
# config.existing_remote_files = "keep"
#
# Automatically replace files with their equivalent gzip compressed version
# config.gzip_compression = true
#
# Use the Rails generated 'manifest.yml' file to produce the list of files to
# upload instead of searching the assets directory.
# config.manifest = true
#
# Fail silently. Useful for environments such as Heroku
# config.fail_silently = true
end
end
In addition, we can see the region option in both gems. It is highly recomended to configure it correctly to increase upload performance. Now, when we call assets:precompile
, assets will be uploaded to a specified Amazon S3 bucket.
So, these steps should be enough to basically configure your app to work with Amazon S3.
Further reading
- Organizing Storage in Multiple Fog Containers Using CarrierWave
- Planning Your Cloud Stack: Storage and Database Solutions
- Using IBM Bluemix Object Storage in Ruby Projects
About the author
Nikolai Sharangovich is an experienced Ruby on Rails developer with a deep understanding of the object-oriented design and modern software principles. He likes to collaborate with product people to achieve a maximum impact. Find him on GitHub.