Complete Ruby Integration Guide

CubeMaster API Integration Guide

Using Ruby on Rails (RestClient)

To use the CubeMaster API, you need an API key (TokenID) for authentication. Here's how to get started:

  1. Visit the CubeMaster website: https://cubemaster.net.
  2. Locate the "Sign In" option (typically found in the top-right corner).
  3. Fill out the registration form with your details (e.g., name, email, password, company information).
  4. After signing up, log in to your account dashboard.
  5. Navigate to the "Settings" - "Integration" section to generate your API key (TokenID).
  6. Generate an API key. Once generated, you’ll receive a unique TokenID (e.g., abc123xyz789). Copy this key and store it securely, as it will be used in the HTTP headers of your API requests.
  7. Copy the TokenID and store it securely.

Note: The TokenID will be used in the HTTP headers of your POST request for authentication.

Tip: In Ruby on Rails, use the dotenv-rails gem to manage environment variables. Add your TokenID to a .env file:

CUBEMASTER_API_KEY=abc123xyz789

Then access it in your code with ENV['CUBEMASTER_API_KEY'].

Ensure your Rails app is ready to make API calls using the RestClient gem.

  1. Open your Rails project’s Gemfile and add:
  2. gem 'rest-client'
  3. Run bundle install in your terminal to install the gem.
  4. Create a new controller (e.g., LoadsController) to handle API interactions:
    rails g controller Loads create
  5. In config/routes.rb, add a route for the create action:
    post '/loads/create', to: 'loads#create'
  6. Verify your Rails app is running locally by executing rails server and visiting http://localhost:3000.

UI Element: In your view (e.g., app/views/loads/new.html.erb), add a simple form to trigger the API call:

<%= form_with url: "/loads/create", method: :post do |form| %>
  <%= form.submit "Create Load", class: "btn btn-primary" %>
<% end %>

A RESTful API (Representational State Transfer) is a way for applications to communicate over the internet using standard HTTP methods like GET, POST, PUT, and DELETE. Here’s a beginner-friendly breakdown:

  • Endpoint: A URL (e.g., https://api.cubemaster.net/loads) where the API listens for requests.
  • HTTP Methods:
    • GET: Retrieve data.
    • POST: Send data to create something (like our load).
  • Request: You send data (e.g., JSON) to the API.
  • Response: The API sends back data (e.g., success message or error).
  • Headers: Extra info sent with the request, like authentication tokens.

In this guide, we’ll use a POST request to the /loads endpoint to build a load, sending JSON data and receiving a JSON response.

Assume your customer’s legacy database stores order/shipment data (e.g., items, quantities, dimensions). Integrate this into your API request.

  1. Create a model for your legacy data (e.g., Order):
    rails g model Order name:string length:decimal width:decimal height:decimal weight:decimal qty:integer
  2. Migrate the database: rails db:migrate.
  3. Seed sample data in db/seeds.rb:
    Order.create(name: "ITEM001", length: 72, width: 30, height: 75, weight: 1002.45, qty: 16)
    Order.create(name: "ITEM002", length: 27.31, width: 37.5, height: 76.67, weight: 521.45, qty: 28)
    Run rails db:seed.
  4. In your controller, fetch this data to build the Cargoes array:
    orders = Order.all
    cargoes = orders.map do |order|
      {{
        "Name": order.name,
        "Length": order.length,
        "Width": order.width,
        "Height": order.height,
        "Weight": order.weight,
        "Qty": order.qty,
        "OrientationsAllowed": "OrientationsAll",
        "TurnAllowedOnFloor": false,
        "ColorKnownName": "Brown" # Example default
      }}
    end

This data will be merged into the API request payload in the next step.

Now, build the request payload and send it to the CubeMaster API using RestClient.

In app/controllers/loads_controller.rb:

require 'rest-client'
require 'json'

class LoadsController < ApplicationController
  def create
    # Fetch legacy data
    orders = Order.all
    cargoes = orders.map do |order|
      {{
        "Name": order.name,
        "Length": order.length,
        "Width": order.width,
        "Height": order.height,
        "Weight": order.weight,
        "Qty": order.qty,
        "OrientationsAllowed": "OrientationsAll",
        "TurnAllowedOnFloor": false,
        "ColorKnownName": "Brown"
      }}
    end

    # Full payload
    payload = {{
      "Title": "New Mixed Truck Load",
      "Description": "Hello Web API",
      "Cargoes": cargoes + [
        {{
          "Name": "SKU0005",
          "Length": 27.31,
          "Width": 9.5,
          "Height": 75.67,
          "Weight": 501.45,
          "OrientationsAllowed": "OrientationsAll",
          "TurnAllowedOnFloor": true,
          "Qty": 24,
          "ColorKnownName": "Beige"
        }},
        {{ "Name": "SKU0005", "Qty": 23 }},
        {{ "Name": "SKU0008", "Qty": 34 }}
      ],
      "Containers": [
        {{
          "VehicleType": "Dry",
          "Name": "53FT-Intermodal",
          "Length": 630,
          "Width": 98,
          "Height": 106,
          "ColorKnownName": "Blue"
        }}
      ],
      "Rules": {{
        "IsWeightLimited": true,
        "IsSequenceUsed": false,
        "FillDirection": "FrontToRear",
        "CalculationType": "MixLoad"
      }}
    }}.to_json

    # Send POST request
    response = RestClient.post(
      'https://api.cubemaster.net/loads',
      payload,
      {{
        content_type: :json,
        'TokenID': ENV['CUBEMASTER_API_KEY']
      }}
    )

    # Handle response (next step)
    @result = JSON.parse(response.body)
    render 'result'
  rescue RestClient::ExceptionWithResponse => e
    @error = e.response
    render 'error'
  end
end

Request JSON:

{{
    "Title": "New Mixed Truck Load",
    "Description": "Hello Web API",
    "Cargoes": [
        {{
            "Name": "ITEM001",
            "Length": 72,
            "Width": 30,
            "Height": 75,
            "Weight": 1002.45,
            "OrientationsAllowed": "OrientationsAll",
            "TurnAllowedOnFloor": false,
            "Qty": 16,
            "ColorKnownName": "Brown"
        }},
        {{
            "Name": "ITEM002",
            "Length": 27.31,
            "Width": 37.5,
            "Height": 76.67,
            "Weight": 521.45,
            "OrientationsAllowed": "OrientationsAll",
            "TurnAllowedOnFloor": false,
            "Qty": 28,
            "ColorKnownName": "Brown"
        }},
        {{
            "Name": "SKU0005",
            "Length": 27.31,
            "Width": 9.5,
            "Height": 75.67,
            "Weight": 501.45,
            "OrientationsAllowed": "OrientationsAll",
            "TurnAllowedOnFloor": true,
            "Qty": 24,
            "ColorKnownName": "Beige"
        }},
        {{ "Name": "SKU0005", "Qty": 23 }},
        {{ "Name": "SKU0008", "Qty": 34 }}
    ],
    "Containers": [
        {{
            "VehicleType": "Dry",
            "Name": "53FT-Intermodal",
            "Length": 630,
            "Width": 98,
            "Height": 106,
            "ColorKnownName": "Blue"
        }}
    ],
    "Rules": {{
        "IsWeightLimited": true,
        "IsSequenceUsed": false,
        "FillDirection": "FrontToRear",
        "CalculationType": "MixLoad"
      }}
}}

Process the API response in your view to display key details to the user.

In app/views/loads/result.html.erb:

<h2>Load Calculation Result</h2>
<% if @result['status'] == 'succeed' %>
  <div class="alert alert-success">
    <%= @result['message'] %>
  </div>
  <h3>Summary</h3>
  <ul>
    <li>Cargoes Loaded: <%= @result['loadSummary']['cargoesLoaded'] %></li>
    <li>Volume Loaded: <%= @result['loadSummary']['volumeLoaded'] %></li>
    <li>Weight Loaded: <%= @result['loadSummary']['weightLoaded'] %></li>
  </ul>
  <h3>3D Diagram</h3>
  <img src="<%= @result['filledContainers'][0]['graphics']['images']['path3DDiagram'] %>" alt="3D Load Diagram" class="img-fluid" />
<% else %>
  <div class="alert alert-danger">
    Error: <%= @result['message'] %>
  </div>
<% end %>

Sample Response JSON:

{
    "status": "succeed",
    "message": "Engine created. 5 cargoes. 1 empty containers. Calculation started. Calculation ended. The load built successfully. The load saved to the cloud database.",
    "calculationError": "InvalidCargoSize",
    "document": {
        "title": "New Mixed Truck Load",
        "description": "Hello Web API",
        "calculationTimeInSeconds": 0.6152743,
        "createdBy": "CHANG@LOGEN.CO.KR"
    },
    "loadSummary": {
        "cargoesLoaded": 68,
        "piecesLoaded": 68,
        "volumeLoaded": 5261723.4606,
        "weightLoaded": 42674.59999999999
    },
    "filledContainers": [
        {
            "name": "#1 53FT-Intermodal",
            "loadSummary": {
                "volumeUtilization": 80.39990374424703,
                "weightLoaded": 42674.59999999999
            },
            "graphics": {
                "images": {
                    "path3DDiagram": "https://api.cubemaster.net/runtimes/b28413ca_51ed_44c9_b92e_13147363fd61.PNG"
                }
            }
        }
    ]
}

Techniques for monitoring and debugging your API integration:

  • Rails Logger: Use Rails.logger.info or Rails.logger.error in your controller to log request payloads and responses to log/development.log.
  • RestClient Logging: Enable RestClient logging in config/environments/development.rb:
  • RestClient.log = Logger.new(STDOUT)
  • Error Handling: Catch RestClient::ExceptionWithResponse to log non-200 HTTP responses.
  • Testing with Postman: Test the API independently using Postman with the same JSON payload and TokenID.