Step-by-Step Guide: Consuming CubeMaster API with Ruby on Rails (RestClient)
To use the CubeMaster API, you need an API key (TokenID) for authentication. Here's how to get started:
- Visit the CubeMaster website: https://cubemaster.net.
- Locate the "Sign In" option (typically found in the top-right corner).
- Fill out the registration form with your details (e.g., name, email, password, company information).
- After signing up, log in to your account dashboard.
- Navigate to the "Settings" - "Integration" section to generate your API key (TokenID).
- 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. - 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.
- Open your Rails project’s
Gemfileand add: - Run
bundle installin your terminal to install the gem. -
Create a new controller (e.g.,
LoadsController) to handle API interactions:rails g controller Loads create -
In
config/routes.rb, add a route for the create action:post '/loads/create', to: 'loads#create' - Verify your Rails app is running locally by executing
rails serverand visitinghttp://localhost:3000.
gem 'rest-client'
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.
-
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 - Migrate the database:
rails db:migrate. -
Seed sample data in
db/seeds.rb:
RunOrder.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)rails db:seed. -
In your controller, fetch this data to build the
Cargoesarray: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"
}
}
UI Element: The form submission triggers this action. The TokenID is passed in the headers for authentication.
After sending the request, process the response to display results or handle errors.
Create app/views/loads/result.html.erb:
<h2>Load Creation Result</h2>
<p>Status: <%= @result["status"] %></p>
<p>Message: <%= @result["message"] %></p>
<% if @result["calculationError"].present? %>
<p class="text-danger">Error: <%= @result["calculationError"] %></p>
<% end %>
<h3>Load 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>
<%= link_to "Back", new_load_path, class: "btn btn-secondary" %>
Create app/views/loads/error.html.erb for errors:
<h2>Error Occurred</h2>
<p class="text-danger"><%= @error %></p>
<%= link_to "Try Again", new_load_path, class: "btn btn-secondary" %>
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",
"isShared": true,
"isAutoSaved": true,
"isPending": false,
"calculationTimeInSeconds": 0.6152743,
"processId": "",
"batchId": "",
"createdBy": "CHANG@LOGEN.CO.KR",
"createdAt": "2023-02-11T01:17:01.7392204+09:00",
"updatedAt": "0001-01-01T00:00:00"
},
"loadSummary": {
"cargoesLoaded": 68,
"piecesLoaded": 68,
"cargoesLeft": 0,
"piecesLeft": 57,
"unitloadsLoaded": 0,
"volumeLoaded": 5261723.4606,
"weightLoaded": 42674.59999999999,
"priceLoaded": 0,
"containersLoaded": 1
},
"filledContainers": [ /* Truncated for brevity */ ],
"manifest": [ /* Truncated for brevity */ ],
"reportLinks": {
"overview": "https://cubemaster.net/source/report/openlink.asp?id=cc3717aa-3460-4af0-ae59-6908bc0a496e"
},
"uom": "UnitEnglish"
}
Handling Details: Check status for success, display loadSummary metrics, and show calculationError if present.
Ensure your API integration works smoothly by monitoring and debugging.
-
Logging: Add logging to your controller:
Check logs inRails.logger.info "Request sent: #{payload}" Rails.logger.info "Response received: #{response.body}"log/development.log. - Pry Debugging: Add
gem 'pry'to your Gemfile, then insertbinding.prybefore theRestClient.postcall to inspect variables interactively. -
RestClient Debugging: Enable verbose output:
This prints request/response details to the console.RestClient.log = 'stdout' - Test with Postman: Before coding, test the API in Postman with the same JSON and headers to verify behavior.
- Error Handling: Review the
rescueblock in Step 5 to catch and log API errors.
Tip: If you encounter issues like InvalidCargoSize, double-check your Cargoes data against API requirements.