# Ruby

> Install the txtextcontrol-reportingcloud gem, merge sample_invoice.tx to PDF with merge_document and send a downloaded template with the request from Ruby.

- **Product:** ReportingCloud
- **Section:** Documentation
- **Kind:** Topic
- **Path:** ReportingCloud > Getting Started > Ruby
- **2766 words**
- **Web URL:** https://docs.textcontrol.com/reporting-cloud/getting-started/ruby/
- **LLMs URL:** https://docs.textcontrol.com/reporting-cloud/getting-started/ruby/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/reporting-cloud/getting-started/ruby/llms-full.txt

---

Ruby scripts and applications use ReportingCloud through the gem `txtextcontrol-reportingcloud`, the Ruby SDK, whose class `TXTextControl::ReportingCloud::ReportingCloud` wraps the Web API. With the gem and one script, you merge the demo template `sample_invoice.tx` of your template storage with invoice data and save the result as a PDF file from the command line. A second variant of the script sends the template with the request instead of naming a stored one.

### Prerequisites

- **A ReportingCloud account.** A trial account is enough, and it has `sample_invoice.tx` in its template storage. [Creating an Account](https://docs.textcontrol.com/reporting-cloud/installation/account/llms-full.txt) shows how to sign up. The Ruby SDK authenticates with the user name and password of the account, the email address you signed up with and its password; it has no option for an API key.
- **Ruby with RubyGems.** The steps were tested with Ruby 3.3 and Ruby 4.0. The gem declares no minimum version of Ruby and no dependencies; it uses the standard library.

### Check Your Ruby Version

Open a terminal and print the version of Ruby:

```bash
ruby --version
```

The output names the version, such as `ruby 4.0.6`. A message that `ruby` isn't found means that Ruby isn't installed or isn't on the path.

### Install the Gem

1. Create a directory for the project and change to it:

    ```bash
    mkdir my-application && cd my-application
    ```
2. Install the gem with RubyGems:

    ```bash
    gem install txtextcontrol-reportingcloud
    ```

RubyGems installs version 1.2.1 of the gem, the current one. In an application that uses Bundler, add `gem 'txtextcontrol-reportingcloud'` to the *Gemfile* and run `bundle install` instead, as [Installing an SDK](https://docs.textcontrol.com/reporting-cloud/installation/sdks/#ruby) shows. On Ruby 4.0, the *Gemfile* also needs `gem 'base64'` and `gem 'ostruct'`: the script and the gem load these libraries, which Ruby 4.0 no longer provides to Bundler by default.

### Set the Credentials

The script reads the user name and password from the environment variables `REPORTINGCLOUD_USERNAME` and `REPORTINGCLOUD_PASSWORD`, which keeps them out of your source code. Set them in the terminal in which you run the script:

```bash
export REPORTINGCLOUD_USERNAME="<email address>"
export REPORTINGCLOUD_PASSWORD="<password>"
```

In PowerShell, the commands are `$env:REPORTINGCLOUD_USERNAME = "<email address>"` and `$env:REPORTINGCLOUD_PASSWORD = "<password>"`. Put a password that contains `$` in single quotes in bash, so that the shell doesn't expand it.

### Write the Script

Create a file *merge.rb* in the project directory with the following code:

```ruby
require "base64"
require "txtextcontrol/reportingcloud"
require "txtextcontrol/reportingcloud/merge_body"

# Read the credentials from the environment, never from source code
username = ENV["REPORTINGCLOUD_USERNAME"]
password = ENV["REPORTINGCLOUD_PASSWORD"]

if username.to_s.empty? || password.to_s.empty?
  abort "Set REPORTINGCLOUD_USERNAME and REPORTINGCLOUD_PASSWORD."
end

reporting_cloud = TXTextControl::ReportingCloud::ReportingCloud.new(username, password)

# One record: the fields of the invoice and the line items of the item block
merge_data = [
  {
    "yourcompany_companyname" => "Text Control, LLC",
    "invoice_no" => "778723",
    "billto_name" => "Joey Montana",
    "billto_companyname" => "Montana, LLC",
    "billto_street" => "1 Washington Dr",
    "billto_zip" => "27878",
    "billto_city" => "Charlotte",
    "payment_due" => "20/1/2016",
    "item" => [
      {
        "qty" => "1",
        "item_no" => "1",
        "item_description" => "Item description 1",
        "item_unitprice" => "2663",
        "item_discount" => "20",
        "item_total" => "2130.40"
      },
      {
        "qty" => "1",
        "item_no" => "2",
        "item_description" => "Item description 2",
        "item_unitprice" => "5543",
        "item_discount" => "0",
        "item_total" => "5543"
      }
    ],
    "total_sub" => "7673.4",
    "total_tax" => "537.138",
    "total" => "8210.538"
  }
]

merge_body = TXTextControl::ReportingCloud::MergeBody.new(merge_data)

begin
  # Merge the template of the template storage and receive one Base64 string per record
  documents = reporting_cloud.merge_document(merge_body, "sample_invoice.tx", :pdf)

  File.binwrite("invoice.pdf", Base64.strict_decode64(documents[0]))
  puts "Written to invoice.pdf"
rescue RuntimeError => error
  # The message is the response body of the Web API
  puts error.message
end
```

#### What the Code Does

- **`require "txtextcontrol/reportingcloud"`** loads the class `ReportingCloud`. `MergeBody` is in a file of its own and is required separately, and `base64` of the standard library decodes the documents.
- **`ReportingCloud.new`** takes the user name and password, which the gem sends with every request in a Basic `Authorization` header, and sends the requests to `https://api.reporting.cloud`.
- **`merge_data`** is an array of *records*, the data of one document each. The keys of a hash are the names of the *merge fields* in the template, placeholders such as `invoice_no`, and the array `item` fills the *merge block* `item`, which repeats a table row for each line item. Merge fields without data are removed from the document.
- **`MergeBody.new`** carries the records and optionally merge settings and a template.
- **`merge_document`** sends the request `POST /v1/document/merge` and returns an array with one Base64 string per created document. Its parameters are the body, the name of a stored template, the return format, whether to append all records into one document and test mode, the last two `false` by default.
- **`:pdf`** is the return format `PDF`. The gem documents `:rtf`, `:doc`, `:docx`, `:html`, `:tx` and `:txt` as the other values.
- **`File.binwrite`** writes the first and only document, decoded from Base64, to *invoice.pdf*.

### Run the Script

Run the script in the terminal in which you set the credentials:

```bash
ruby merge.rb
```

The script prints `Written to invoice.pdf`. Open the file in a PDF viewer to see the merged invoice; a trial account adds the ReportingCloud logo to every document. Each run is a merge request and counts 1 against the monthly document quota of your plan.

### Send the Template With the Request

A template doesn't have to be in your storage. `MergeBody.new` also takes the template itself as a Base64 string, which the gem sends in the `template` property of the request; the Web API merges it without storing it. The template can be any file of a supported format that your script reads with `Base64.strict_encode64(File.binread(...))`. Here, the script downloads `sample_invoice.tx` from the storage with `download_template`, which returns it as a Base64 string and counts against no quota, and sends it back. In *merge.rb*, replace everything from the line `merge_body = ...` to the end with:

```ruby
begin
  # Download the template from the storage, as Base64, as a template file of your own would be read
  template = reporting_cloud.download_template("sample_invoice.tx")

  # Send the template with the data instead of naming a stored template
  merge_body = TXTextControl::ReportingCloud::MergeBody.new(merge_data, nil, template)
  documents = reporting_cloud.merge_document(merge_body, nil, :pdf)

  File.binwrite("invoice_template_sent.pdf", Base64.strict_decode64(documents[0]))
  puts "Written to invoice_template_sent.pdf"
rescue RuntimeError => error
  puts error.message
end
```

The `nil` in place of the merge settings keeps the defaults, and the `nil` in place of the template name says that no stored template is used: passing both a template name and a template, or neither, raises an `ArgumentError`. Run `ruby merge.rb` again and open *invoice\_template\_sent.pdf*.

### Troubleshooting

When the Web API answers with an error, the gem raises a `RuntimeError` whose message is the response body; the script prints it. The status code isn't part of the message.

- **`Invalid username/password combination or invalid APIKey`.** The user name or password is wrong, or the environment variables are set in another terminal. The user name is the email address of the account.
- **`Template doesn't exist in storage`.** The template name is not in your template storage. Check it on the **My Templates** page of the portal.
- **`cannot load such file -- txtextcontrol/reportingcloud`.** Ruby doesn't find the gem. Install it with `gem install txtextcontrol-reportingcloud` for the Ruby you run the script with; with Bundler, run the script with `bundle exec ruby merge.rb`.
- **`cannot load such file -- base64`** or **`-- ostruct`** with `bundle exec` on Ruby 4.0. Add `gem 'base64'` and `gem 'ostruct'` to the *Gemfile* and run `bundle install`.

### Next Steps

- [Web API](https://docs.textcontrol.com/reporting-cloud/getting-started/web-api/llms-full.txt): the request of this script with curl.
- [Merge Data](https://docs.textcontrol.com/reporting-cloud/mail-merge/data-sources/llms-full.txt): how arrays and hashes map to merge fields and merge blocks.
- [Merge Settings](https://docs.textcontrol.com/reporting-cloud/mail-merge/settings/llms-full.txt): the settings that `MergeSettings` passes, and the defaults of the Ruby SDK.
- [Ruby](https://docs.textcontrol.com/reporting-cloud/sdks/ruby/llms-full.txt): every method of the Ruby SDK, its attributes and its errors.

---

## Nearby

- **Previous:** [Java](https://docs.textcontrol.com/reporting-cloud/getting-started/java/llms-full.txt)
- **Next:** [Portal](https://docs.textcontrol.com/reporting-cloud/portal/llms-full.txt)
