FreightKit

This library interfaces with the web services of various shipping carriers. The goal is to abstract the features that are most frequently used into a pleasant and consistent Ruby API.

FreightKit supports:

  • Downloading scanned documents
  • Finding shipping rates
  • Tracking shipments

On a technical level it supports:

  • Abstracted accessorials
  • Abstracted tracking events
  • Cubic feet and density calculations
  • Freight class calculations (and manual overriding)

Definitions

Carrier: Has unique web services pertaining to whatever real-world services they provide.

Platform: Provides web-accessible services for many carriers at once.

Note: Carriers may extend Platforms and override them when their behavior differs from the Platform.

Plug-in System

FreightKit relies on plug-ins (gems) to define how it connects to individual Carriers and Platforms.

Installation

Using bundler, add to the Gemfile:

gem 'freight_kit'

Or standalone:

$ gem install freight_kit

Note: Plug-ins are required to connect to Carriers and Platforms (see above).

Standard Usage

Start off by initializing the Carrier provided by a Carrier plug-in:

require 'freight_kit'

# Typically just one `Credential` is required
credentials = [
  FreightKit::Credential.new(
    type: :api,
    account: 'account_number',
    username: 'username',
    password: 'password',
    tariff: FreightKit::Tariff.new # optional
  ),
  FreightKit::Credential.new(
    type: :oauth2,
    access_token: 'token',
    expires_at: DateTime.current + 1.day, # DateTime
    scope: 'scope'
  ),
  FreightKit::Credential.new(
    type: :website,
    username: 'username',
    password: 'password'
  ),
  FreightKit::Credential.new(
    type: :selenoid,
    base_url: URI.parse('http://domain:4444'),
    browser: :chrome
  )
]

carrier = FreightKit::SCAC.new(credentials)

Documents

carrier.bol(tracking_number) # BOL generated by carrier
carrier.scanned_bol(tracking_number) # BOL scanned by carrier

carrier.pod(tracking_number)

Tracking

tracking = carrier.find_tracking_info(tracking_number)

tracking.delivered?
tracking.status

tracking.shipment_events.each do |event|
  puts "#{event.name} at #{event.location.city}, #{event.location.state} on #{event.time}. #{event.message}"
end

Quoting

packages = [
  FreightKit::Package.new(
    371 * 16, # 371 lbs
    {
      length: 40, # inches
      width: 48,
      height: 47
    },
    units: :imperial
  ),
  FreightKit::Package.new(
    371 * 16, # 371 lbs
    {
      length: 40, # inches
      width: 48,
      height: 47
    },
    freight_class: 125, # override calculated freight class
    units: :imperial
  )
]

origin = FreightKit::Location.new(
  country: 'US',
  state: 'CA',
  city: 'Los Angeles',
  zip: '90001'
)

destination = FreightKit::Location.new(
  country: 'US',
  state: 'IL',
  city: 'Chicago',
  zip: '60007'
)

accessorials = %i[
  appointment_delivery
  liftgate_delivery
  residential_delivery
]

response = carrier.find_rates(origin, destination, packages, accessorials: accessorials)
rates = response.rates
rates = response.rates.sort_by(&:price).collect { |rate| [rate.service_name, rate.price] }