Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,9 @@ configuration.yml
# Developer env
.idea
.vscode

# Artifacts created by running examples/*.rb
examples/*.jpg
examples/*.mp4
examples/log/
examples/tmp/
101 changes: 101 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Contributor guide for coding agents

This file is for agents contributing to this repository. If you are *using* the installed
`cloudinary` gem in another project, read the bundled docs instead — find them with
`ruby -e 'puts Gem::Specification.find_by_name("cloudinary").gem_dir + "/docs"'`.

## Commands

```bash
bundle install # install dependencies
bundle exec rspec # full suite — HITS A LIVE CLOUD, see Testing
bundle exec rspec spec/utils_spec.rb # a single file
bundle exec rspec spec/active_storage spec/carriewave_spec.rb # integration adapters
gem build cloudinary.gemspec # build the gem; inspect what ships
```

`CLOUDINARY_URL` must be set for most of the suite. `tools/get_test_cloud.sh` allocates a
throwaway cloud (this is what CI uses); `npx @cloudinary/cloud` also works.

There is **no linter configured** in this repo — no RuboCop config exists. Do not add one
as part of an unrelated change.

## Testing

- **The suite is not mocked.** Unlike the other Cloudinary SDKs, `spec/` has no
unit/integration split: most files perform real uploads and Admin API calls against the
`CLOUDINARY_URL` cloud. Never point it at a production environment.
- Specs tag their fixtures (`TEST_TAG`, `TIMESTAMP_TAG` in `spec/spec_helper.rb`) and
clean up by tag. Preserve that pattern so runs do not leak assets.
- `spec/active_storage/dummy/` is a real dummy Rails app with a database; those specs boot
Rails. `spec/carriewave_spec.rb` stubs CarrierWave — it is **not** a dependency of this
gem.
- Nondeterministic AI output (captions, tags, moderation verdicts) must be asserted by
request shape, state transition, and response schema — never by exact output values.
- `rspec-retry` is enabled; a flaky live call may retry rather than fail outright.

## Project structure

- `lib/cloudinary.rb` — entry point, config loading, Rails hook-in.
- `lib/cloudinary/uploader.rb` — Upload API. Raises `CloudinaryException` for everything.
- `lib/cloudinary/api.rb` — Admin API. Raises typed subclasses of
`Cloudinary::Api::Error` (`NotFound`, `RateLimited`, ...) defined in `base_api.rb`.
- `lib/cloudinary/utils.rb` — URL generation and signing; the largest and most
transformation-logic-dense file.
- `lib/cloudinary/search.rb` — chainable Search API builder.
- `lib/cloudinary/helper.rb`, `video_helper.rb` — Rails view helpers (`cl_image_tag` etc.).
- `lib/active_storage/service/cloudinary_service.rb` — Active Storage service; patches
`ActiveStorage::Blob`, so load order matters (see docs/upload-with-activestorage.md).
- `lib/cloudinary/carrier_wave*` — CarrierWave storage adapter, loaded only when
`CarrierWave` is defined.
- `docs/` — version-matched Markdown docs shipped in the gem.
- `examples/` — runnable task examples shipped in the gem; one per `docs/` task page.
- `samples/` — **legacy** sample applications, not part of the tested example set and not
shipped in the gem. Do not treat them as current guidance.
- `spec/` — the test suite; `tools/` — cloud allocation and release shell scripts.

## Code style

- Two-space indent, `snake_case`, module functions via `def self.method`.
- Public API methods take positional arguments then a trailing options hash, and pass
unrecognized options through to the API rather than validating them:

```ruby
def self.example_method(public_id, options = {})
call_api("example", options) do
{ :timestamp => Time.now.to_i, :public_id => public_id }
end
end
```

- Results are `Hash` objects with **string** keys. Do not convert to symbols.
- The version lives in exactly one place, `lib/cloudinary/version.rb`, and
`tools/get_test_cloud.sh` greps it — do not reformat that line.

## Git workflow

- Branch from `master`; keep changes focused; one topic per pull request.
- Run the suite against a throwaway cloud before opening a PR.
- Do not rewrite published `CHANGELOG.md` entries; add new entries at the top. Docs-only
changes get no changelog entry.
- Never commit credentials. `config/cloudinary.yml` is gitignored for this reason — it is
a local dev file and must not be added.

## Boundaries

**Always**
- Keep `docs/` and `examples/` consistent with the code they document, 1:1 per task.
- Verify a documented behavior by running it against a real cloud before writing it down.
- Keep API secrets out of examples, docs, specs, and fixtures.

**Ask first**
- Changing supported Ruby or Rails versions, dependencies, or the gemspec `files` list.
- Renaming or removing any public method, or changing an exception class raised.
- Changing release, CI, or publishing configuration.

**Never**
- Commit credentials or real account identifiers.
- Point the test suite at a production Cloudinary environment.
- Add a linter, reformat unrelated files, or modify `samples/` as part of another change.
- Document a Cloudinary platform capability as an SDK method unless this gem implements
it (see docs/platform-capabilities.md).
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) Cloudinary Ltd.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
195 changes: 102 additions & 93 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,129 +1,138 @@
[![Build Status](https://app.travis-ci.com/cloudinary/cloudinary_gem.svg?branch=master)](https://app.travis-ci.com/github/cloudinary/cloudinary_gem)
[![CI](https://github.com/cloudinary/cloudinary_gem/actions/workflows/ci.yml/badge.svg)](https://github.com/cloudinary/cloudinary_gem/actions/workflows/ci.yml)
[![Gem Version](https://badge.fury.io/rb/cloudinary.svg)](https://rubygems.org/gems/cloudinary)
[![Gem Version](https://badgen.net/rubygems/dt/cloudinary)](https://rubygems.org/gems/cloudinary)
[![License](https://img.shields.io/github/license/cloudinary/cloudinary_gem.svg)](LICENSE)

Cloudinary Ruby on Rails SDK
===================
# Cloudinary Ruby on Rails SDK

## About
Upload, transform, optimize, and manage images and videos with Cloudinary from Ruby and Rails — the `cloudinary` gem on RubyGems.

The Cloudinary Ruby on Rails SDK allows you to quickly and easily integrate your application with Cloudinary.
Effortlessly optimize, transform, upload and manage your cloud's assets.
## Install

#### Note
```bash
gem install cloudinary
```

This Readme provides basic installation and usage information. For the complete documentation, see
the [Ruby on Rails SDK Guide](https://cloudinary.com/documentation/rails_integration).
Or add it to your `Gemfile`:

## Table of Contents
```ruby
gem "cloudinary"
```

- [Key Features](#key-features)
- [Version Support](#Version-Support)
- [Installation](#installation)
- [Usage](#usage)
- [Setup](#Setup)
- [Transform and Optimize Assets](#Transform-and-Optimize-Assets)
- [CarrierWave Integration](#CarrierWave-Integration)
- [Active Storage Integration](#Active-Storage-Integration)
## Quick start

## Key Features
Set your API environment variable (Console > Settings > API Keys):

- [Transform](https://cloudinary.com/documentation/rails_video_manipulation#video_transformation_examples) and
[optimize](https://cloudinary.com/documentation/rails_image_manipulation#image_optimizations) assets.
- Generate [image](https://cloudinary.com/documentation/rails_image_manipulation#deliver_and_transform_images) and
[video](https://cloudinary.com/documentation/rails_video_manipulation#rails_video_transformation_code_examples) tags.
- [Asset Management](https://cloudinary.com/documentation/rails_asset_administration).
- [Secure URLs](https://cloudinary.com/documentation/video_manipulation_and_delivery#generating_secure_https_urls_using_sdks)
.
```bash
export CLOUDINARY_URL=cloudinary://<api_key>:<api_secret>@<cloud_name>
```

## Version Support
Upload an image and get an optimized delivery URL:

| SDK Version | Ruby 1.9.3 | Ruby 2.x | Ruby 3.x | Ruby 4.x |
|-------------|------------|----------|----------|----------|
| 2.x | ✘ | ✘ | ✔ | ✔ |
| 1.x | ✔ | ✔ | ✔ | ✘ |
```ruby
require "cloudinary"

result = Cloudinary::Uploader.upload(
"https://res.cloudinary.com/demo/image/upload/sample.jpg",
public_id: "quickstart-sample"
)
puts "Uploaded: #{result['public_id']}"

# Build a 400x400 auto-cropped URL with automatic format and quality
url = Cloudinary::Utils.cloudinary_url(
result["public_id"],
width: 400, height: 400, crop: "fill",
gravity: "auto", fetch_format: "auto", quality: "auto"
)
puts "Optimized URL: #{url}"
```

| SDK Version | Rails 5.x | Rails 6.x | Rails 7.x | Rails 8.x |
|-------------|-----------|-----------|-----------|-----------|
| 2.x | ✘ | ✔ | ✔ | ✔ |
| 1.x | ✔ | ✔ | ✔ | ✘ |
Save as `quickstart.rb` and run `ruby quickstart.rb`. [Create a free account](https://cloudinary.com/users/register_free) if you don't have one — or run `npx @cloudinary/cloud` to [provision one without signing up](docs/get-credentials.md).

## Installation
In Rails the same URL is a view helper: `<%= cl_image_tag("quickstart-sample", width: 400, height: 400, crop: "fill") %>`.

```bash
gem install cloudinary
```
## Common tasks

# Usage
- [Get Cloudinary credentials](docs/get-credentials.md)
- [Configure Cloudinary](docs/configure-cloudinary.md)
- [Upload an image](docs/upload-image.md)
- [Upload a large video](docs/upload-large-video.md)
- [Sign a browser upload](docs/sign-browser-upload.md)
- [Transform and deliver an image](docs/transform-and-deliver-image.md)
- [Transform and deliver a video](docs/transform-and-deliver-video.md)
- [Search and manage assets](docs/search-and-manage-assets.md)
- [Moderate an upload](docs/moderate-upload.md)
- [Use structured metadata](docs/use-structured-metadata.md)
- [Troubleshoot errors](docs/troubleshoot-errors.md)

### Setup
Rails integration, which ships in this gem:

```ruby
require 'cloudinary'
```
- [Use with Rails](docs/use-with-rails.md) — view helpers, `cloudinary.yml`, credentials
- [Upload with Active Storage](docs/upload-with-activestorage.md)
- [Upload with CarrierWave](docs/upload-with-carrierwave.md)

### Transform and Optimize Assets
- [See full documentation](https://cloudinary.com/documentation/rails_image_manipulation).
Runnable versions live in [`examples/`](examples/) — each is a complete file you can run directly.

```ruby
cl_image_tag("sample.jpg", width: 100, height: 150, crop: "fill")
```
## When to use this SDK

### Upload
- [See full documentation](https://cloudinary.com/documentation/rails_image_and_video_upload).
- [Learn more about configuring your uploads with upload presets](https://cloudinary.com/documentation/upload_presets).
Use this gem in **Ruby and Rails server-side code**: uploads, signed operations, asset
administration, search, moderation, delivery URL generation, and Rails view helpers.

```ruby
Cloudinary::Uploader.upload("my_picture.jpg")
```
For other jobs, better-fitting tools exist:

- Browser or frontend framework rendering: the [frontend SDKs](https://cloudinary.com/documentation/frontend_sdks) ([md](https://cloudinary.com/documentation/frontend_sdks.md)).
- Complete in-browser upload UI: [Upload Widget](https://cloudinary.com/documentation/upload_widget) ([md](https://cloudinary.com/documentation/upload_widget.md)).
- Text-to-image generation and image-to-video: [platform APIs](https://cloudinary.com/documentation/image_generation_addon) ([md](https://cloudinary.com/documentation/image_generation_addon.md)), not wrapped by this gem.
- Multi-step media workflow automation: [MediaFlows](https://cloudinary.com/documentation/mediaflows_user_guide) ([md](https://cloudinary.com/documentation/mediaflows_user_guide.md)).
- Interactive agent-driven asset operations: [Cloudinary MCP servers and Skills](https://cloudinary.com/documentation/cloudinary_llm_mcp) ([md](https://cloudinary.com/documentation/cloudinary_llm_mcp.md)).

The full capability map — plus the Skills, MCP servers, and CLI worth setting up first —
is in [docs/platform-capabilities.md](docs/platform-capabilities.md).

## Status and compatibility

Stable, actively maintained. See [CHANGELOG.md](CHANGELOG.md).

| SDK version | Ruby | Rails |
|-------------|------|-------|
| 2.x | 3.x, 4.x | 6.1 and later |
| 1.x | 1.9.3 – 3.x (no longer maintained) | 5.x – 7.x |

### CarrierWave Integration
- [See full documentation](https://cloudinary.com/documentation/rails_carrierwave).
CI covers Ruby 3.1, 3.2, 3.3, 3.4, and 4.0.

### Active Storage Integration
- [See full documentation](https://cloudinary.com/documentation/rails_activestorage).
## Documentation

### Security options
- [See full documentation](https://cloudinary.com/documentation/solution_overview#security).
- [Bundled task docs](docs/README.md) — ship inside the gem, version-matched.
- [Ruby on Rails SDK guide](https://cloudinary.com/documentation/rails_integration) — the full documentation ([md](https://cloudinary.com/documentation/rails_integration.md)).

### Samples
- See [samples folder](https://github.com/cloudinary/cloudinary_gem/tree/master/samples).
Documentation links in this README point at the browsable HTML page, with an `(md)`
companion link that returns the same page as raw Markdown. Inside `docs/` and `examples/`
the links are Markdown-only, since those files are written to be read by coding agents.
Either form works for any page: add `.md` for Markdown, drop it for HTML.

## Contributions
- See [CONTRIBUTING](CONTRIBUTING.md).
## For AI coding agents

## Get Help
- Contributing to this repo: read [AGENTS.md](AGENTS.md).
- Using the installed gem: the docs in the gem's `docs/` directory match your installed
version and are the source of truth. Locate them with:

If you run into an issue or have a question, you can either:
```bash
ruby -e 'puts Gem::Specification.find_by_name("cloudinary").gem_dir + "/docs"'
```

- Issues related to the SDK: [Open a GitHub issue](https://github.com/cloudinary/cloudinary_gem/issues).
- Issues related to your account: [Open a support ticket](https://cloudinary.com/contact)
Start with [platform-capabilities](docs/platform-capabilities.md) before assuming a
feature exists.

## About Cloudinary
## Support

Cloudinary is a powerful media API for websites and mobile apps alike, Cloudinary enables developers to efficiently
manage, transform, optimize, and deliver images and videos through multiple CDNs. Ultimately, viewers enjoy responsive
and personalized visual-media experiences—irrespective of the viewing device.
- SDK bugs and feature requests: [GitHub issues](https://github.com/cloudinary/cloudinary_gem/issues)
- Account and platform questions: [Cloudinary support](https://support.cloudinary.com)

## Additional Resources
## Security

- [Cloudinary Transformation and REST API References](https://cloudinary.com/documentation/cloudinary_references):
Comprehensive references, including syntax and examples for all SDKs.
- [MediaJams.dev](https://mediajams.dev/): Bite-size use-case tutorials written by and for Cloudinary Developers
- [DevJams](https://www.youtube.com/playlist?list=PL8dVGjLA2oMr09amgERARsZyrOz_sPvqw): Cloudinary developer podcasts on
YouTube.
- [Cloudinary Academy](https://training.cloudinary.com/): Free self-paced courses, instructor-led virtual courses, and
on-site courses.
- [Code Explorers and Feature Demos](https://cloudinary.com/documentation/code_explorers_demos_index): A one-stop shop
for all code explorers, Postman collections, and feature demos found in the docs.
- [Cloudinary Roadmap](https://cloudinary.com/roadmap): Your chance to follow, vote, or suggest what Cloudinary should
develop next.
- [Cloudinary Facebook Community](https://www.facebook.com/groups/CloudinaryCommunity): Learn from and offer help to
other Cloudinary developers.
- [Cloudinary Account Registration](https://cloudinary.com/users/register/free): Free Cloudinary account registration.
- [Cloudinary Website](https://cloudinary.com): Learn about Cloudinary's products, partners, customers, pricing, and
more.
See [SECURITY.md](SECURITY.md) for private vulnerability reporting. Keep your
`api_secret` in server-side code; for client uploads, use the server-signed pattern in
[Sign a browser upload](docs/sign-browser-upload.md).

## Licence
## License

Released under the MIT license.
Released under the MIT license — see [LICENSE](LICENSE). Copyright (c) Cloudinary Ltd.
Loading
Loading