Ruby On Rails integration
Overview
Cloudinary provides an open source GEM package for Ruby.
As you probably already know, Cloudinary can be easily used without any installed software. However, using the client library included in the Ruby GEM will make your life even easier: it includes an API wrapper for easy access, Rails view helper tags, Active Record integration, easy upload, configuration management and a migration tool.
The GEM was tested with Ruby 1.8.7, 1.9.2, 1.9.3 and Rails 2.3.x, 3.0.x, 3.1.x, 3.2.x.
Installation
To install the Cloudinary Ruby GEM, run:
gem install cloudinary
If you use Rails 3.x or higher, edit your Gemfile, add the following line and run bundle
gem 'cloudinary'Or in Rails 2.x, edit your environment.rb and add:
config.gem 'cloudinary'If you would like to use our optional integration module of image uploads with ActiveRecord or Mongoid using CarrierWave, install CarrierWave GEM:
gem install carrierwave
Rails 3.x Gemfile:
gem 'carrierwave' gem 'cloudinary'
Rails 2.x environment.rb
config.gem 'carrierwave', :version => '~> 0.4.10' config.gem 'cloudinary'
Note: The CarrierWave GEM should be loaded before the Cloudinary GEM.
Configuration
Each request for building a URL of a remote cloud resource must have the cloud_name parameter set. Each request to our secure APIs (e.g., image uploads, eager sprite generation) must have the api_key and api_secret parameters set. See API, URLs and access identifiers for more details.
Setting the cloud_name, api_key and api_secret parameters can be done either directly in each call to a Cloudinary method or by globally setting using a YAML configuration file.
Cloudinary looks for an optional file named cloudinary.yml, which should be located under the 'config' directory of your Rails project. It contains settings for each of your deployment environments. You can always override the values specified in cloudinary.yml by passing different values in specific Cloudinary calls.
You can download your customized cloudinary.yml configuration file using our Management Console.
Here's an example of a cloudinary.yml file:
development: cloud_name: "sample" api_key: "874837483274837" api_secret: "a676b67565c6767a6767d6767f676fe1" production: cloud_name: "sample" api_key: "874837483274837" api_secret: "a676b67565c6767a6767d6767f676fe1"
Another configuration option is to use a Rails initializer file. You can place a file named cloudinary.rb in the /config/initializers of your Rails project. Here's a sample initializer code:
Cloudinary.config do |config| config.cloud_name = 'sample' config.api_key = '874837483274837' config.api_secret = 'a676b67565c6767a6767d6767f676fe1' config.cdn_subdomain = true end
One last configuration option allows you to dynamially configure the Cloudinary library by defining the CLOUDINARY_URL environment variable. The configuration URL is available in the Management Console's dashboard of your account. Here's a sample value:
CLOUDINARY_URL=cloudinary://874837483274837:a676b67565c6767a6767d6767f676fe1@sample
In addition to the three mandatory configuration parameters mentioned above, you can define various optional configuration parameters either globally or for each API call specifically. Optional parameters:
- cdn_subdomain - Boolean (default: false). Whether to automatically build URLs with multiple CDN sub-domains. See this blog post for more details.
- private_cdn - Boolean (default: false). Should be set to true for Advanced plan's users that have a private CDN distribution.
- secure_distribution - The domain name of the CDN distribution to use for building HTTPS URLs. Relevant only for Advanced plan's users that have a private CDN distribution.
- cname - Custom domain name to use for building HTTP URLs. Relevant only for Advanced plan's users that have a private CDN distribution and a custom CNAME.
- static_image_support - Boolean (default: false). Whether to deliver uploaded static images through Cloudinary.
- enhance_image_tag - Boolean (default: false). Whether to wrap the standard image_tag view helper's method. Set to true if static_image_support is set to true.
Display and transform images
Adding images to your Rails view is very easy. You just need to use the cl_image_tag helper method instead of the standard image_tag method. This method generates the full image resource URL based on the given parameters and internally uses image_tag for adding the image to your HTML code:
For example, displaying the uploaded image with the sample public ID, while providing an alternate text:
cl_image_tag("sample.jpg", :alt => "Sample Image")

If cloud_name is configured to be demo, this tag is equivalent to:
image_tag("http://res.cloudinary.com/demo/image/upload/sample.jpg", :alt => "Sample Image")
Now, let's say that you wish to display a transformed version of the uploaded image. Simply provide transformation instructions.
For example, displaying a the 'sample' image transformed to fill a 100x150 area:
cl_image_tag("sample.jpg", :width => 100, :height => 150, :crop => :fill)

This is equivalent to:
image_tag( "http://res.cloudinary.com/demo/image/upload/w_100,h_150,c_fill/sample.jpg", :width => 100, :height => 150)
Note that if you do not provide the :crop parameter, no resize or crop transformation will be run. This is actually useful when you want to use the resource with the original dimensions and let the browser stretch or shrink it for displaying in a given size.
If for some reason you want to transform an uploaded image to a certain dimension and display it within your page in a different dimension, you can use the optional :html_width and :html_height parameters. Here's an example of the Cloudinary method and the equivalent image tag:
cl_image_tag("sample.jpg", :width => 100, :height => 150, :crop => :fill, :html_width => 50, :html_height => 75)

This is equivalent to:
image_tag( "http://res.cloudinary.com/demo/image/upload/w_100,h_150,c_fill/sample.jpg", :width => 50, :height => 75)
You can also use named transformations. If, for example, you created a transformation named 'jpg_with_quality_30', you can access it by setting the :transformation parameter that can accept either a name of a single transformation or an array of transformation names to chain:
cl_image_tag("sample.jpg", :transformation => 'jpg_with_quality_30')

Changing image format is simply done by changing the extension of the file name:
cl_image_tag("sample.png")Creating a thumbnail based on a detected face is done by specifying the :thumb crop mode and selecting the :face gravity:
cl_image_tag("butterfly.jpg", :width => 90, :height => 90, :crop => :thumb, :gravity => :face)
The facebook_profile_image_tag, twitter_profile_image_tag and twitter_name_profile_image_tag view helper methods can be used to embed profile pictures:
facebook_profile_image_tag("billclinton.jpg", :width => 90, :height => 130, :crop => :fill, :gravity => :north_west)

twitter_name_profile_image_tag("billclinton.jpg")
For a full list of supported transformations and their usage, refer to Image transformations.
If you re-uploaded an image with a Public ID that already exists, you can force displaying the new image by providing the :version parameter:
cl_image_tag("sample.jpg", :version => 1315746344)
Direct upload
You can upload resources from your Ruby code or Ruby on Rails server. Uploading is done over HTTP using a secure protocol based on the api_key and api_secret parameters you provide.
For uploading an image, use the following method:
Cloudinary::Uploader.upload(file, options = {})
It accepts the following parameters:
-
file
- The resource to upload. Can be one of the following:
- An IO input stream of the data (e.g., File.open(file, "rb"))
- An HTTP URL of a resource available on the Internet.
- An object that responds to the 'read' method that returns the actual content of the resource.
- public_id (Optional) - Public ID to assign to the uploaded resource. Random ID is generated otherwise and returned as a result for this call.
- tags (Optional) - A tag name or an array with a list tag names to assign to the uploaded resource.
- format (Optional) - A format to convert the uploaded image to before saving in the cloud. For example: 'jpg'.
- Transformation parameters (Optional) - Any combination of transformation-related parameters for transforming the uploaded image before storing in the cloud. For example: :width, :height, :crop, :gravity, :quality, :transformation.
- eager (Optional) - A list of transformations to create for the uploaded image during the upload process, instead of lazily creating them when being accessed by your site's visitors.
- resource_type (Optional) - Valid values: 'image' and 'raw'. Default: 'image'.
A call to the upload process returns a Hash with content similar to that shown in the following example:
{
:url => 'http://res.cloudinary.com/demo/image/upload/sample.jpg',
:secure_url =>
'https://cloudinary-a.akamaihd.net/demo/image/upload/sample.jpg',
:public_id => 'sample',
:version => '1312461204',
:width => 864,
:height => 564,
:bytes => 120253
}Some examples:
Uploading an image from a local file:
Cloudinary::Uploader.upload('/home/my_image.jpg')
Specifying a Public ID for an uploaded file:
Cloudinary::Uploader.upload(File.open('/tmp/image1.jpg'), :public_id => 'sample')
Uploading an image from a remote Web URL:
Cloudinary::Uploader.upload('http://www.example.com/image.jpg')
Uploading an image using received Rails controller params:
Cloudinary::Uploader.upload(params[:image])
Assigning tags to uploaded image:
Cloudinary::Uploader.upload('/home/my_image.jpg', :tags => ['special', 'for_homepage'])
Uploading an image while applying an incoming transformation of fitting in 100x150 PNG before storing in the cloud:
Cloudinary::Uploader.upload('/home/my_image.jpg', :width => 100, :height => 150, :crop => :fit, :format => 'png')
Eagerly generate transformed version of the original uploaded image while storing in the cloud:
Cloudinary::Uploader.upload('/home/my_image.jpg', :eager => [ {:width => 100, :height => 150, :crop => :fit, :format => 'png'}, {:transformation => 'jpg_with_quality_30'} ])
Uploading an image while applying a set of incoming chained transformations and generating multiple eager transformations:
Cloudinary::Uploader.upload("sample.jpg", :transformation => [ {:width => 100, :height => 120, :crop => :limit}, {:crop => :crop, :x => 5, :y => 10, :width => 40, :height => 10} ], :eager => [ {:width => 0.2, :crop => :scale}, {:effect => "hue:30"} ])
For deleting a previously uploaded image, use the following method:
Cloudinary::Uploader.destroy(public_id, options = {})
For example, the following method would delete the uploaded image assigned with the ID 'zombie':
Cloudinary::Uploader.destroy('zombie')
CarrierWave - ActiveRecord & Mongoid integration
If you support dynamically uploading images in your Ruby on Rails application, the images are probably attached to a certain model entity. Rails is using ActiveRecord for model entities in default. While Mongoid documents are used for a MongoDB based model. Examples might include keeping the image as the 'picture' attribute of a Post entity or as the 'profile_picture' attribute of a User entity.
There's a great Ruby GEM for integrating image uploads with your model. It is called CarrierWave. By default, CarrierWave stores images on the local hard drive, but it also has plenty more plugins available for image storing and manipulation.
Cloudinary GEM provides a plugin for CarrierWave. Using it means that you enjoy the benefits of CarrierWave for easily uploading images from HTML forms to your model, while enjoying the great benefits of Cloudinary: uploaded images are stored in cloud, transformed and manipulated in the cloud, and delivered automatically through a CDN.
Below we have provided quick instructions for using Cloudinary with CarrierWave in your Rails project.
In our example, we have the Post model entity. You can attach an image to each post. Attached images are managed by the 'picture' attribute (column) of the Post entity.
To get started, first define a CarrierWave uploader class and tell it to use the Cloudinary plugin. (See CarrierWave documentation for more details).
In this example we want to convert the uploaded image to a PNG before storing it in the cloud and we want to assign it the post_picture tag. We also define two required transformations for displaying the image in our site: :standard and :thumbnail. A randomly generated unique Public ID is generated for each uploaded image and persistently stored in the model.
class PictureUploader < CarrierWave::Uploader::Base include Cloudinary::CarrierWave process :convert => 'png' process :tags => ['post_picture'] version :standard do process :resize_to_fill => [100, 150, :north] end version :thumbnail do resize_to_fit(50, 50) end end
You can specify a custom Public ID. In the following example it is the content of the short_name attribute of the Post entity.
class PictureUploader < CarrierWave::Uploader::Base include Cloudinary::CarrierWave ... def public_id return model.short_name end end
The picture attribute of Post is simply a String (a DB migration script is needed of course). We mount it to the PictureUploader class we've just defined:
class Post < ActiveRecord::Base ... mount_uploader :picture, PictureUploader ... end
In our HTML form for Post editing, we add a File field for uploading the picture and also a hidden cache field for supporting page reloading and validation errors while not losing the uploaded picture. The example below is in HAML (you can of course do exactly the same using ERB)
= form_for(:post) do |post_form| = post_form.hidden_field(:picture_cache) = post_form.file_field(:picture)
In our controller, we save or update the attributes of the post in the standard way. For example:
post.update_attributes(params[:post])Note: if you are using direct image uploads from the browser to Cloudinary, a signed identifier is sent to the controller instead of the actual image data. Cloudinary's CarrierWave plugin seamlessly handles direct identifiers, verifies the signature and updates the model with a reference to the uploaded image.
At this point, the image uploaded by the user to your server is uploaded to Cloudinary, which also assigned the given Public ID and tag and converts it to PNG. The Public ID together with the version of the uploaded image are stored in the 'picture' attribute of our Post entity. Note that by default the transformations are not generated at this point, but instead are only generated when accessed for the first time. This is true unless you specify process :eager => true or simply eager for each transformation.
class PictureUploader < CarrierWave::Uploader::Base include Cloudinary::CarrierWave version :standard do process :eager => true process :resize_to_fill => [100, 150, :north] end version :thumbnail do eager resize_to_fit(50, 50) end end
Now you can use standard image_tag calls for displaying the uploaded images and their derived transformations. Cloudinary GEM automatically generates the correct full URL for accessing your resources:
image_tag(post.picture_url, :alt => post.short_name) image_tag(post.picture_url(:thumbnail), :width => 50, :height => 50)
Custom and dynamic transformations
Cloudinary's plugin for CarrierWave supports all standard resize and crop of CarrierWave. In addition, you can apply any custom transformation supported by Cloudinary.
You can use the cloudinary_transformation method for specifying any supported transformation parameters. Calling cloudinary_transformation can be also done in combination with the standard resize and crop methods. The following uploader class shows a common example of using custom transformations:
class PictureUploader < CarrierWave::Uploader::Base include Cloudinary::CarrierWave # Generate a 164x164 JPG of 80% quality version :simple do process :resize_to_fill => [164, 164, :fill] process :convert => 'jpg' cloudinary_transformation :quality => 80 end # Generate a 100x150 face-detection based thumbnail, # round corners with a 20-pixel radius and increase brightness by 30%. version :bright_face do cloudinary_transformation :effect => "brightness:30", :radius => 20, :width => 100, :height => 150, :crop => :thumb, :gravity => :face end end
You can take this further and apply chained transformations for reaching complex results. Any transformations can be applied as an incoming transformation while uploading or as part of the different versions that are generated either lazily or eagerly while uploading. The following uploader class includes such chained transformations applied using the transformation parameter of the cloudinary_transformation method.
class PictureUploader < CarrierWave::Uploader::Base include Cloudinary::CarrierWave # Apply an incoming chained transformation: limit image to 1000x1200 and # add a 30-pixel watermark 5 pixels from the south east corner. cloudinary_transformation :transformation => [ {:width => 1000, :height => 1200, :crop => :limit}, {:overlay => "my_watermark", :width => 30, :gravity => :south_east, :x => 5, :y => 5} ] # Eagerly transform image to 150x200 with a sepia effect applied and then # rotate the resulting image by 10 degrees. version :rotated do eager cloudinary_transformation :transformation => [ {:width => 150, :height => 200, :crop => :fill, :effect => "sepia"}, {:angle => 10} ] end end
Some websites have a graphic design that forces them to display the same images in many different dimensions. Formally defining multiple uploader's versions might become annoying.
You can still use CarrierWave and leverage Cloudinary's dynamic transformations by applying any desired transformation while building your view. Any version can be generated dynamically from your view without depending on CarrierWave versions. Simply use the full_public_id attribute with cl_image_tag for building cloud-based transformation URLs for the uploaded images attached to your model.
cl_image_tag(post.picture.full_public_id, :format => "jpg", :width => 100, :height => 200, :crop => :crop, :x => 20, :y => 30, :radius => 10)
Custom coordinates based cropping
If you allow your users to manually select the cropping area, we recommend to keep the x,y coordinates persistently in the model for being able to perform different cropping on the original image in the future. The following uploader class fetches the custom coordinates from attributes of the model object. The custom_crop method in this example simply returns a Hash of additional Cloudinary's transformation parameters to apply.
class PictureUploader < CarrierWave::Uploader::Base include Cloudinary::CarrierWave version :full do process :convert => 'jpg' process :custom_crop end def custom_crop return :x => model.crop_x, :y => model.crop_y, :width => model.crop_width, :height => model.crop_height, :crop => :crop end end
If you want to store only the cropped version of the image, you can use the incoming transformation of our upload API. This way the original image is not stored in the cloud. Only the cropped version is stored. You can then use further transformations to resize the cropped image. The following example calls process :custom_crop in the class itself (instead of in a 'version') while the custom-coordinates are kept as transient attributes on the model (defined with attr) instead of storing them persistently.
class PictureUploader < CarrierWave::Uploader::Base include Cloudinary::CarrierWave process :custom_crop version :thumbnail do process :convert => 'jpg' resize_to_fill(120, 150, 'North') end def custom_crop return :x => model.crop_x, :y => model.crop_y, :width => model.crop_width, :height => model.crop_height, :crop => :crop end end
Sprite generation
Integrating a sprite in your view is very easy using the cl_sprite_tag helper method.
For example, for integrating a sprite that contains images that has the logo tag, add the following code to the head section of your HTML template:
cl_sprite_tag("logo")Displaying an image with the public ID amazon_logo contained within the sprite:
<div class="amazon_logo"/>
You can also specify transformation instructions for running on all images before merging into the sprite. For example:
cl_sprite_tag("logo", :width => 150, :height => 60, :crop => :fit)
Refer to Sprite with transformations for more details.
Sometimes you need to re-generate a sprite when its contained images change and you want to make sure that all users receive the updated sprite immediately (bypass cache).
To do this, you should directly request to generate the sprite. Calling this method returns the new version of the generated sprite, which you should use for integrating the sprite in your view. You can also let Cloudinary manage that for you.
The following example generates (or re-generates) a sprite and stores its version in a file on the local drive:
Cloudinary::Uploader.generate_sprite('logo', :version_store => :file)
In your view you can tell cl_sprite_tag to read the current version from the file in order to build a correct URL to deliver the latest version of the sprite:
cl_sprite_tag("logo", :version_store => :file)
Cloudinary Ruby GEM also provides a useful set of methods for managing tags of uploaded images.
Assign the given tag to images with the given list of Public IDs:
Include ':exclusive => true' in specified options if you wish to remove the given tag from all other resources.
Cloudinary::Uploader.add_tag(tag, public_ids = [], options = {})
Cloudinary::Uploader.add_tag('logo', ['amazon_logo', 'google_logo', 'apple_logo'])
Clear the given tag from images with the given list of Public IDs:
Cloudinary::Uploader.remove_tag(tag, public_ids = [], options = {})
For example:
Cloudinary::Uploader.remove_tag('logo', ['microsoft_logo', 'hp_logo', 'rim_logo'])
Clear all existing tags from images with the given list of Public IDs and assign to all of them the given tag:
Cloudinary::Uploader.replace_tag(tag, public_ids = [], options = {})
For example:
Cloudinary::Uploader.replace_tag('special_logo', ['heroku_logo', 'engine_yard_logo'])
Migration
If your web application is already live in production with many resources already uploaded and stored somewhere, you can use the Cloudinary migration tool for Ruby.
This tool allows you to manage the migration process: upload all resources to Cloudinary, perform the uploading quickly using multiple worker threads, handle communication errors, and allow pausing and resuming the migration process at any time.
In order to use the migration tool, you need to install the sqlite3 Ruby GEM ('gem install sqlite3'), in addition to the Cloudinary GEM.
The following is an example of migration code that migrates all images of the Post entities that are stored in a database:
migrator = Cloudinary::Migrator.new( :retrieve=>proc{|id| Post.find(id).data }, :complete=>proc{|id|, result| $stderr.print "done #{id} #{result}\n" } ) Post.find_each(:conditions=>["id > ?", migrator.max_given_id], :select => "id") do |post| migrator.process(:id => post.id, :public_id => "post_#{post.id}") end migrator.done
When constructing the Migrator object you can provide the following parameters:
-
:retrieve
- A method that is called on a given ID you recognize. It must return the resource to upload in one of the following formats:
- A public HTTP URL.
- The actual content of the resource.
- An IO stream for reading the resource's content.
- An ActiveRecord::Base instance.
- A Cloudinary::CarrierWave instance.
- :complete - A callback method that is called when a resource was successfully uploaded. The method receives the internal ID of the resource and the result returned from the server (that includes the Public ID and the version).
- :threads (Optional) - Number of worker threads to run simultaneously. An integer value between 1 and 100. Default: 10
- :debug (Optional) - Print debugging information while migrating resources. Default: false.
- :api_key and :api_secret unless they are configured in cloudinary.yml.
You need to feed the migrator with resources to upload. This is done by calling the process method which adds the received resource details to a persistent queue. The process method accepts the following parameters:
- :id - An internal ID you need to provide for recognizing your resources during the migration process.
- :public_id (Optional) - A Cloudinary Public ID to assign to an image resource. A random Public ID is generated.
- :url (Optional) - A public HTTP URL of a an image. If specified, you don't have to provide the:retrieve method to the migration constructor.
- Additional upload parameters (Optional) - You can specify additional standard upload parameters to send to Cloudinary while uploading the image: tags, transformation instructions, and eager transformations.
Note: If you want to use multiple upload threads and you fetch your resources using a database using Rails connections, make sure that the database connection pool size is at least number-of-threads+1. To ensure this, edit config/database.yml and add the following line to the file::
pool: 12