ReportingCloud

Ruby

Topic

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 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:

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:

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

    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 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:

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:

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:

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:

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: the request of this script with curl.
  • Merge Data: how arrays and hashes map to merge fields and merge blocks.
  • Merge Settings: the settings that MergeSettings passes, and the defaults of the Ruby SDK.
  • Ruby: every method of the Ruby SDK, its attributes and its errors.