diff --git a/.gitignore b/.gitignore
index 14e3ed5..af94b4d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,6 +45,7 @@ capybara-*.html
/db/*.sqlite3-journal
/public/system
/coverage/
+coverage
/spec/tmp
**.orig
rerun.txt
@@ -71,3 +72,7 @@ bower.json
# Ignore pow environment settings
.powenv
+
+# secrets
+/config/secrets.yml
+.env
diff --git a/.ruby-gemset b/.ruby-gemset
new file mode 100644
index 0000000..91ffe71
--- /dev/null
+++ b/.ruby-gemset
@@ -0,0 +1 @@
+shipping-service
diff --git a/.ruby-version b/.ruby-version
new file mode 100644
index 0000000..5859406
--- /dev/null
+++ b/.ruby-version
@@ -0,0 +1 @@
+2.2.3
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..d350c61
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,65 @@
+source 'https://rubygems.org'
+
+
+# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
+gem 'rails', '4.2.5'
+
+# Use SCSS for stylesheets
+gem 'sass-rails', '~> 5.0'
+# Use Uglifier as compressor for JavaScript assets
+gem 'uglifier', '>= 1.3.0'
+# Use CoffeeScript for .coffee assets and views
+gem 'coffee-rails', '~> 4.1.0'
+# See https://github.com/rails/execjs#readme for more supported runtimes
+# gem 'therubyracer', platforms: :ruby
+
+# Use jquery as the JavaScript library
+gem 'jquery-rails'
+# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
+gem 'turbolinks'
+# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
+gem 'jbuilder', '~> 2.0'
+# bundle exec rake doc:rails generates the API under doc/api.
+gem 'sdoc', '~> 0.4.0', group: :doc
+
+# Use ActiveModel has_secure_password
+# gem 'bcrypt', '~> 3.1.7'
+
+# Use Unicorn as the app server
+# gem 'unicorn'
+
+# Use Capistrano for deployment
+# gem 'capistrano-rails', group: :development
+
+gem 'active_shipping'
+gem 'dotenv-rails'
+
+group :test do
+ gem 'vcr', '~> 3.0', '>= 3.0.1'
+ gem 'webmock', '~> 1.22', '>= 1.22.6'
+end
+
+group :development, :test do
+ # Call 'byebug' anywhere in the code to stop execution and get a debugger console
+ gem 'byebug'
+ gem 'rspec-rails'
+ gem 'factory_girl_rails'
+ gem 'simplecov'
+ gem 'pry'
+ # Use sqlite3 as the database for Active Record
+ gem 'sqlite3'
+end
+
+group :development do
+ # Access an IRB console on exception pages or by using <%= console %> in views
+ gem 'web-console', '~> 2.0'
+ gem 'better_errors'
+ gem 'binding_of_caller'
+
+ # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
+ gem 'spring'
+end
+
+group :production do
+ gem 'pg'
+end
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000..a0cf9ac
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,234 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ actionmailer (4.2.5)
+ actionpack (= 4.2.5)
+ actionview (= 4.2.5)
+ activejob (= 4.2.5)
+ mail (~> 2.5, >= 2.5.4)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ actionpack (4.2.5)
+ actionview (= 4.2.5)
+ activesupport (= 4.2.5)
+ rack (~> 1.6)
+ rack-test (~> 0.6.2)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
+ actionview (4.2.5)
+ activesupport (= 4.2.5)
+ builder (~> 3.1)
+ erubis (~> 2.7.0)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
+ active_shipping (1.6.5)
+ active_utils (~> 3.2.0)
+ activesupport (>= 3.2, < 5.0.0)
+ nokogiri (>= 1.6)
+ quantified (~> 1.0.1)
+ active_utils (3.2.0)
+ activesupport (>= 3.2)
+ i18n
+ activejob (4.2.5)
+ activesupport (= 4.2.5)
+ globalid (>= 0.3.0)
+ activemodel (4.2.5)
+ activesupport (= 4.2.5)
+ builder (~> 3.1)
+ activerecord (4.2.5)
+ activemodel (= 4.2.5)
+ activesupport (= 4.2.5)
+ arel (~> 6.0)
+ activesupport (4.2.5)
+ i18n (~> 0.7)
+ json (~> 1.7, >= 1.7.7)
+ minitest (~> 5.1)
+ thread_safe (~> 0.3, >= 0.3.4)
+ tzinfo (~> 1.1)
+ addressable (2.4.0)
+ arel (6.0.3)
+ better_errors (2.1.1)
+ coderay (>= 1.0.0)
+ erubis (>= 2.6.6)
+ rack (>= 0.9.0)
+ binding_of_caller (0.7.2)
+ debug_inspector (>= 0.0.1)
+ builder (3.2.2)
+ byebug (8.2.1)
+ coderay (1.1.0)
+ coffee-rails (4.1.1)
+ coffee-script (>= 2.2.0)
+ railties (>= 4.0.0, < 5.1.x)
+ coffee-script (2.4.1)
+ coffee-script-source
+ execjs
+ coffee-script-source (1.10.0)
+ concurrent-ruby (1.0.0)
+ crack (0.4.3)
+ safe_yaml (~> 1.0.0)
+ debug_inspector (0.0.2)
+ diff-lcs (1.2.5)
+ docile (1.1.5)
+ dotenv (2.1.0)
+ dotenv-rails (2.1.0)
+ dotenv (= 2.1.0)
+ railties (>= 4.0, < 5.1)
+ erubis (2.7.0)
+ execjs (2.6.0)
+ factory_girl (4.5.0)
+ activesupport (>= 3.0.0)
+ factory_girl_rails (4.5.0)
+ factory_girl (~> 4.5.0)
+ railties (>= 3.0.0)
+ globalid (0.3.6)
+ activesupport (>= 4.1.0)
+ hashdiff (0.2.3)
+ i18n (0.7.0)
+ jbuilder (2.4.0)
+ activesupport (>= 3.0.0, < 5.1)
+ multi_json (~> 1.2)
+ jquery-rails (4.1.0)
+ rails-dom-testing (~> 1.0)
+ railties (>= 4.2.0)
+ thor (>= 0.14, < 2.0)
+ json (1.8.3)
+ loofah (2.0.3)
+ nokogiri (>= 1.5.9)
+ mail (2.6.3)
+ mime-types (>= 1.16, < 3)
+ method_source (0.8.2)
+ mime-types (2.99)
+ mini_portile2 (2.0.0)
+ minitest (5.8.3)
+ multi_json (1.11.2)
+ nokogiri (1.6.7.1)
+ mini_portile2 (~> 2.0.0.rc2)
+ pg (0.18.4)
+ pry (0.10.3)
+ coderay (~> 1.1.0)
+ method_source (~> 0.8.1)
+ slop (~> 3.4)
+ quantified (1.0.1)
+ rack (1.6.4)
+ rack-test (0.6.3)
+ rack (>= 1.0)
+ rails (4.2.5)
+ actionmailer (= 4.2.5)
+ actionpack (= 4.2.5)
+ actionview (= 4.2.5)
+ activejob (= 4.2.5)
+ activemodel (= 4.2.5)
+ activerecord (= 4.2.5)
+ activesupport (= 4.2.5)
+ bundler (>= 1.3.0, < 2.0)
+ railties (= 4.2.5)
+ sprockets-rails
+ rails-deprecated_sanitizer (1.0.3)
+ activesupport (>= 4.2.0.alpha)
+ rails-dom-testing (1.0.7)
+ activesupport (>= 4.2.0.beta, < 5.0)
+ nokogiri (~> 1.6.0)
+ rails-deprecated_sanitizer (>= 1.0.1)
+ rails-html-sanitizer (1.0.2)
+ loofah (~> 2.0)
+ railties (4.2.5)
+ actionpack (= 4.2.5)
+ activesupport (= 4.2.5)
+ rake (>= 0.8.7)
+ thor (>= 0.18.1, < 2.0)
+ rake (10.5.0)
+ rdoc (4.2.1)
+ json (~> 1.4)
+ rspec-core (3.4.1)
+ rspec-support (~> 3.4.0)
+ rspec-expectations (3.4.0)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.4.0)
+ rspec-mocks (3.4.1)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.4.0)
+ rspec-rails (3.4.0)
+ actionpack (>= 3.0, < 4.3)
+ activesupport (>= 3.0, < 4.3)
+ railties (>= 3.0, < 4.3)
+ rspec-core (~> 3.4.0)
+ rspec-expectations (~> 3.4.0)
+ rspec-mocks (~> 3.4.0)
+ rspec-support (~> 3.4.0)
+ rspec-support (3.4.1)
+ safe_yaml (1.0.4)
+ sass (3.4.21)
+ sass-rails (5.0.4)
+ railties (>= 4.0.0, < 5.0)
+ sass (~> 3.1)
+ sprockets (>= 2.8, < 4.0)
+ sprockets-rails (>= 2.0, < 4.0)
+ tilt (>= 1.1, < 3)
+ sdoc (0.4.1)
+ json (~> 1.7, >= 1.7.7)
+ rdoc (~> 4.0)
+ simplecov (0.11.1)
+ docile (~> 1.1.0)
+ json (~> 1.8)
+ simplecov-html (~> 0.10.0)
+ simplecov-html (0.10.0)
+ slop (3.6.0)
+ spring (1.6.2)
+ sprockets (3.5.2)
+ concurrent-ruby (~> 1.0)
+ rack (> 1, < 3)
+ sprockets-rails (3.0.0)
+ actionpack (>= 4.0)
+ activesupport (>= 4.0)
+ sprockets (>= 3.0.0)
+ sqlite3 (1.3.11)
+ thor (0.19.1)
+ thread_safe (0.3.5)
+ tilt (2.0.2)
+ turbolinks (2.5.3)
+ coffee-rails
+ tzinfo (1.2.2)
+ thread_safe (~> 0.1)
+ uglifier (2.7.2)
+ execjs (>= 0.3.0)
+ json (>= 1.8.0)
+ vcr (3.0.1)
+ web-console (2.2.1)
+ activemodel (>= 4.0)
+ binding_of_caller (>= 0.7.2)
+ railties (>= 4.0)
+ sprockets-rails (>= 2.0, < 4.0)
+ webmock (1.22.6)
+ addressable (>= 2.3.6)
+ crack (>= 0.3.2)
+ hashdiff
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ active_shipping
+ better_errors
+ binding_of_caller
+ byebug
+ coffee-rails (~> 4.1.0)
+ dotenv-rails
+ factory_girl_rails
+ jbuilder (~> 2.0)
+ jquery-rails
+ pg
+ pry
+ rails (= 4.2.5)
+ rspec-rails
+ sass-rails (~> 5.0)
+ sdoc (~> 0.4.0)
+ simplecov
+ spring
+ sqlite3
+ turbolinks
+ uglifier (>= 1.3.0)
+ vcr (~> 3.0, >= 3.0.1)
+ web-console (~> 2.0)
+ webmock (~> 1.22, >= 1.22.6)
+
+BUNDLED WITH
+ 1.11.2
diff --git a/README.rdoc b/README.rdoc
new file mode 100644
index 0000000..dd4e97e
--- /dev/null
+++ b/README.rdoc
@@ -0,0 +1,28 @@
+== README
+
+This README would normally document whatever steps are necessary to get the
+application up and running.
+
+Things you may want to cover:
+
+* Ruby version
+
+* System dependencies
+
+* Configuration
+
+* Database creation
+
+* Database initialization
+
+* How to run the test suite
+
+* Services (job queues, cache servers, search engines, etc.)
+
+* Deployment instructions
+
+* ...
+
+
+Please feel free to use a different markup language if you do not plan to run
+rake doc:app.
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..ba6b733
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,6 @@
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require File.expand_path('../config/application', __FILE__)
+
+Rails.application.load_tasks
diff --git a/app/assets/images/.keep b/app/assets/images/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
new file mode 100644
index 0000000..e07c5a8
--- /dev/null
+++ b/app/assets/javascripts/application.js
@@ -0,0 +1,16 @@
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
+//
+// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+// compiled file.
+//
+// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
+// about supported directives.
+//
+//= require jquery
+//= require jquery_ujs
+//= require turbolinks
+//= require_tree .
diff --git a/app/assets/javascripts/carriers.coffee b/app/assets/javascripts/carriers.coffee
new file mode 100644
index 0000000..24f83d1
--- /dev/null
+++ b/app/assets/javascripts/carriers.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://coffeescript.org/
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
new file mode 100644
index 0000000..f9cd5b3
--- /dev/null
+++ b/app/assets/stylesheets/application.css
@@ -0,0 +1,15 @@
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
+ * compiled file so the styles you add here take precedence over styles defined in any styles
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
+ * file per style scope.
+ *
+ *= require_tree .
+ *= require_self
+ */
diff --git a/app/assets/stylesheets/carriers.scss b/app/assets/stylesheets/carriers.scss
new file mode 100644
index 0000000..ec3071e
--- /dev/null
+++ b/app/assets/stylesheets/carriers.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the carriers controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
new file mode 100644
index 0000000..d83690e
--- /dev/null
+++ b/app/controllers/application_controller.rb
@@ -0,0 +1,5 @@
+class ApplicationController < ActionController::Base
+ # Prevent CSRF attacks by raising an exception.
+ # For APIs, you may want to use :null_session instead.
+ protect_from_forgery with: :exception
+end
diff --git a/app/controllers/carriers_controller.rb b/app/controllers/carriers_controller.rb
new file mode 100644
index 0000000..404f616
--- /dev/null
+++ b/app/controllers/carriers_controller.rb
@@ -0,0 +1,43 @@
+require 'timeout'
+
+class CarriersController < ApplicationController
+ def index
+ ### sample params ###
+ # {"origin"=>{:country=>"US", :state=>"CA", :city=>"Beverly Hills", :zip=>"90210"},"destination"=>{:country=>"US", :state=>"WA", :city=>"Seattle", :zip=>"98103"},"packages"=>[{:weight=>100, :height=>50, :length=>20, :width=>30}]}
+
+ # create ActiveShipping Locations and Packages
+
+ # origin = Carrier.create_origin(params[:origin])
+ # destination = Carrier.create_destination(params[:destination])
+ # packages = Carrier.create_packages(params[:packages]) # as an array
+ #
+ #
+ # @ups_rates = begin
+ # Carrier.get_rates(Carrier.activate_ups, origin, destination, packages)
+ # rescue Timeout::Error
+ # nil
+ # end
+ #
+ # @usps_rates = begin
+ # Carrier.get_rates(Carrier.activate_usps, origin, destination, packages)
+ # rescue Timeout::Error
+ # nil
+ # end
+
+ @ups_rates, @usps_rates = Carrier.get_rates(params)
+
+
+ # examine the rates for errors and turn this into JSON
+ # as long as it takes less than 5 seconds
+ if @ups_rates && @usps_rates
+ all_rates = @ups_rates.concat(@usps_rates)
+ render :json => all_rates.as_json, :status => :ok
+ elsif @ups_rates
+ render :json => @ups_rates.as_json, :status => :ok
+ elsif @usps_rates
+ render :json => @usps_rates.as_json, :status => :ok
+ else
+ render :json => [], :status => :no_content
+ end
+ end
+end
diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
new file mode 100644
index 0000000..de6be79
--- /dev/null
+++ b/app/helpers/application_helper.rb
@@ -0,0 +1,2 @@
+module ApplicationHelper
+end
diff --git a/app/helpers/carriers_helper.rb b/app/helpers/carriers_helper.rb
new file mode 100644
index 0000000..672e928
--- /dev/null
+++ b/app/helpers/carriers_helper.rb
@@ -0,0 +1,2 @@
+module CarriersHelper
+end
diff --git a/app/mailers/.keep b/app/mailers/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/models/.keep b/app/models/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/models/carrier.rb b/app/models/carrier.rb
new file mode 100644
index 0000000..34d2ce8
--- /dev/null
+++ b/app/models/carrier.rb
@@ -0,0 +1,69 @@
+require 'timeout'
+
+class Carrier
+
+ def self.get_rates(params)
+ origin = Carrier.create_origin(params[:origin])
+ destination = Carrier.create_destination(params[:destination])
+ packages = Carrier.create_packages(params[:packages])
+
+ ups_rates = begin
+ Timeout::timeout(5) do
+ response = Carrier.activate_ups.find_rates(origin, destination, packages)
+ response.rates.sort_by(&:price).collect {|rate| [rate.service_name, rate.price, rate.delivery_date]}
+ end
+ rescue
+ nil
+ end
+
+ usps_rates = begin
+ Timeout::timeout(5) do
+ response = Carrier.activate_usps.find_rates(origin, destination, packages)
+ response.rates.sort_by(&:price).collect {|rate| [rate.service_name, rate.price, rate.delivery_date]}
+ end
+ rescue
+ nil
+ end
+ return ups_rates, usps_rates
+ end
+
+ def self.create_origin(origin_params)
+ ActiveShipping::Location.new(
+ country: origin_params[:country],
+ state: origin_params[:state],
+ city: origin_params[:city],
+ zip: origin_params[:zip])
+ end
+
+ def self.create_destination(destination_params)
+ ActiveShipping::Location.new(
+ country: destination_params[:country],
+ state: destination_params[:state],
+ city: destination_params[:city],
+ zip: destination_params[:zip])
+ end
+
+ def self.create_packages(package_params)
+ packages = []
+ package_params.each do |package|
+ p = ActiveShipping::Package.new(
+ package[:weight].to_i,
+ [
+ package[:length].to_i,
+ package[:width].to_i,
+ package[:height].to_i
+ ]
+ )
+ packages.push(p)
+ end
+ return packages
+ end
+
+ def self.activate_ups
+ ActiveShipping::UPS.new(login: ENV["UPS_LOGIN"], password: ENV["UPS_PW"], key: ENV['UPS_ACCESS_KEY'])
+ end
+
+ def self.activate_usps
+ ActiveShipping::USPS.new(login: ENV["USPS_ACCESS_KEY"])
+ end
+end
diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
new file mode 100644
index 0000000..95e3963
--- /dev/null
+++ b/app/views/layouts/application.html.erb
@@ -0,0 +1,14 @@
+
+
+
+ ShippingService
+ <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
+ <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
+ <%= csrf_meta_tags %>
+
+
+
+<%= yield %>
+
+
+
diff --git a/bin/bundle b/bin/bundle
new file mode 100755
index 0000000..66e9889
--- /dev/null
+++ b/bin/bundle
@@ -0,0 +1,3 @@
+#!/usr/bin/env ruby
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+load Gem.bin_path('bundler', 'bundle')
diff --git a/bin/rails b/bin/rails
new file mode 100755
index 0000000..0138d79
--- /dev/null
+++ b/bin/rails
@@ -0,0 +1,9 @@
+#!/usr/bin/env ruby
+begin
+ load File.expand_path('../spring', __FILE__)
+rescue LoadError => e
+ raise unless e.message.include?('spring')
+end
+APP_PATH = File.expand_path('../../config/application', __FILE__)
+require_relative '../config/boot'
+require 'rails/commands'
diff --git a/bin/rake b/bin/rake
new file mode 100755
index 0000000..d87d5f5
--- /dev/null
+++ b/bin/rake
@@ -0,0 +1,9 @@
+#!/usr/bin/env ruby
+begin
+ load File.expand_path('../spring', __FILE__)
+rescue LoadError => e
+ raise unless e.message.include?('spring')
+end
+require_relative '../config/boot'
+require 'rake'
+Rake.application.run
diff --git a/bin/setup b/bin/setup
new file mode 100755
index 0000000..acdb2c1
--- /dev/null
+++ b/bin/setup
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby
+require 'pathname'
+
+# path to your application root.
+APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
+
+Dir.chdir APP_ROOT do
+ # This script is a starting point to setup your application.
+ # Add necessary setup steps to this file:
+
+ puts "== Installing dependencies =="
+ system "gem install bundler --conservative"
+ system "bundle check || bundle install"
+
+ # puts "\n== Copying sample files =="
+ # unless File.exist?("config/database.yml")
+ # system "cp config/database.yml.sample config/database.yml"
+ # end
+
+ puts "\n== Preparing database =="
+ system "bin/rake db:setup"
+
+ puts "\n== Removing old logs and tempfiles =="
+ system "rm -f log/*"
+ system "rm -rf tmp/cache"
+
+ puts "\n== Restarting application server =="
+ system "touch tmp/restart.txt"
+end
diff --git a/bin/spring b/bin/spring
new file mode 100755
index 0000000..62ec28f
--- /dev/null
+++ b/bin/spring
@@ -0,0 +1,15 @@
+#!/usr/bin/env ruby
+
+# This file loads spring without using Bundler, in order to be fast.
+# It gets overwritten when you run the `spring binstub` command.
+
+unless defined?(Spring)
+ require 'rubygems'
+ require 'bundler'
+
+ if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m))
+ Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq }
+ gem 'spring', match[1]
+ require 'spring/binstub'
+ end
+end
diff --git a/config.ru b/config.ru
new file mode 100644
index 0000000..bd83b25
--- /dev/null
+++ b/config.ru
@@ -0,0 +1,4 @@
+# This file is used by Rack-based servers to start the application.
+
+require ::File.expand_path('../config/environment', __FILE__)
+run Rails.application
diff --git a/config/application.rb b/config/application.rb
new file mode 100644
index 0000000..84b564d
--- /dev/null
+++ b/config/application.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../boot', __FILE__)
+
+require "rails"
+# Pick the frameworks you want:
+require "active_model/railtie"
+require "active_job/railtie"
+require "active_record/railtie"
+require "action_controller/railtie"
+require "action_mailer/railtie"
+require "action_view/railtie"
+require "sprockets/railtie"
+# require "rails/test_unit/railtie"
+
+# Require the gems listed in Gemfile, including any gems
+# you've limited to :test, :development, or :production.
+Bundler.require(*Rails.groups)
+
+module ShippingService
+ class Application < Rails::Application
+ # Settings in config/environments/* take precedence over those specified here.
+ # Application configuration should go into files in config/initializers
+ # -- all .rb files in that directory are automatically loaded.
+
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
+ # config.time_zone = 'Central Time (US & Canada)'
+
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
+ # config.i18n.default_locale = :de
+
+ # Do not swallow errors in after_commit/after_rollback callbacks.
+ config.active_record.raise_in_transactional_callbacks = true
+ end
+end
diff --git a/config/boot.rb b/config/boot.rb
new file mode 100644
index 0000000..6b750f0
--- /dev/null
+++ b/config/boot.rb
@@ -0,0 +1,3 @@
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+
+require 'bundler/setup' # Set up gems listed in the Gemfile.
diff --git a/config/database.yml b/config/database.yml
new file mode 100644
index 0000000..1c1a37c
--- /dev/null
+++ b/config/database.yml
@@ -0,0 +1,25 @@
+# SQLite version 3.x
+# gem install sqlite3
+#
+# Ensure the SQLite 3 gem is defined in your Gemfile
+# gem 'sqlite3'
+#
+default: &default
+ adapter: sqlite3
+ pool: 5
+ timeout: 5000
+
+development:
+ <<: *default
+ database: db/development.sqlite3
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+ <<: *default
+ database: db/test.sqlite3
+
+production:
+ <<: *default
+ database: db/production.sqlite3
diff --git a/config/environment.rb b/config/environment.rb
new file mode 100644
index 0000000..ee8d90d
--- /dev/null
+++ b/config/environment.rb
@@ -0,0 +1,5 @@
+# Load the Rails application.
+require File.expand_path('../application', __FILE__)
+
+# Initialize the Rails application.
+Rails.application.initialize!
diff --git a/config/environments/development.rb b/config/environments/development.rb
new file mode 100644
index 0000000..b55e214
--- /dev/null
+++ b/config/environments/development.rb
@@ -0,0 +1,41 @@
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # In the development environment your application's code is reloaded on
+ # every request. This slows down response time but is perfect for development
+ # since you don't have to restart the web server when you make code changes.
+ config.cache_classes = false
+
+ # Do not eager load code on boot.
+ config.eager_load = false
+
+ # Show full error reports and disable caching.
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Don't care if the mailer can't send.
+ config.action_mailer.raise_delivery_errors = false
+
+ # Print deprecation notices to the Rails logger.
+ config.active_support.deprecation = :log
+
+ # Raise an error on page load if there are pending migrations.
+ config.active_record.migration_error = :page_load
+
+ # Debug mode disables concatenation and preprocessing of assets.
+ # This option may cause significant delays in view rendering with a large
+ # number of complex assets.
+ config.assets.debug = true
+
+ # Asset digests allow you to set far-future HTTP expiration dates on all assets,
+ # yet still be able to expire them through the digest params.
+ config.assets.digest = true
+
+ # Adds additional error checking when serving assets at runtime.
+ # Checks for improperly declared sprockets dependencies.
+ # Raises helpful error messages.
+ config.assets.raise_runtime_errors = true
+
+ # Raises error for missing translations
+ # config.action_view.raise_on_missing_translations = true
+end
diff --git a/config/environments/production.rb b/config/environments/production.rb
new file mode 100644
index 0000000..ea56ebf
--- /dev/null
+++ b/config/environments/production.rb
@@ -0,0 +1,83 @@
+Rails.application.configure do
+ # secrets
+ config.secret_key_base = ENV["SECRET_KEY_BASE"]
+ config.secret_token = ENV["SECRET_TOKEN"]
+
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # Code is not reloaded between requests.
+ config.cache_classes = true
+
+ # Eager load code on boot. This eager loads most of Rails and
+ # your application in memory, allowing both threaded web servers
+ # and those relying on copy on write to perform better.
+ # Rake tasks automatically ignore this option for performance.
+ config.eager_load = true
+
+ # Full error reports are disabled and caching is turned on.
+ config.consider_all_requests_local = false
+ config.action_controller.perform_caching = true
+
+ # Enable Rack::Cache to put a simple HTTP cache in front of your application
+ # Add `rack-cache` to your Gemfile before enabling this.
+ # For large-scale production use, consider using a caching reverse proxy like
+ # NGINX, varnish or squid.
+ # config.action_dispatch.rack_cache = true
+
+ # Disable serving static files from the `/public` folder by default since
+ # Apache or NGINX already handles this.
+ config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
+
+ # Compress JavaScripts and CSS.
+ config.assets.js_compressor = :uglifier
+ # config.assets.css_compressor = :sass
+
+ # Do not fallback to assets pipeline if a precompiled asset is missed.
+ config.assets.compile = false
+
+ # Asset digests allow you to set far-future HTTP expiration dates on all assets,
+ # yet still be able to expire them through the digest params.
+ config.assets.digest = true
+
+ # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
+
+ # Specifies the header that your server uses for sending files.
+ # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
+
+ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+ # config.force_ssl = true
+
+ # Use the lowest log level to ensure availability of diagnostic information
+ # when problems arise.
+ config.log_level = :debug
+
+ # Prepend all log lines with the following tags.
+ # config.log_tags = [ :subdomain, :uuid ]
+
+ # Use a different logger for distributed setups.
+ # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
+
+ # Use a different cache store in production.
+ # config.cache_store = :mem_cache_store
+
+ # Enable serving of images, stylesheets, and JavaScripts from an asset server.
+ # config.action_controller.asset_host = 'http://assets.example.com'
+
+ # Ignore bad email addresses and do not raise email delivery errors.
+ # Set this to true and configure the email server for immediate delivery to raise delivery errors.
+ # config.action_mailer.raise_delivery_errors = false
+
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+ # the I18n.default_locale when a translation cannot be found).
+ config.i18n.fallbacks = true
+
+ # Send deprecation notices to registered listeners.
+ config.active_support.deprecation = :notify
+
+ # Use default logging formatter so that PID and timestamp are not suppressed.
+ config.log_formatter = ::Logger::Formatter.new
+
+ # Do not dump schema after migrations.
+ config.active_record.dump_schema_after_migration = false
+end
diff --git a/config/environments/test.rb b/config/environments/test.rb
new file mode 100644
index 0000000..1c19f08
--- /dev/null
+++ b/config/environments/test.rb
@@ -0,0 +1,42 @@
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # The test environment is used exclusively to run your application's
+ # test suite. You never need to work with it otherwise. Remember that
+ # your test database is "scratch space" for the test suite and is wiped
+ # and recreated between test runs. Don't rely on the data there!
+ config.cache_classes = true
+
+ # Do not eager load code on boot. This avoids loading your whole application
+ # just for the purpose of running a single test. If you are using a tool that
+ # preloads Rails for running tests, you may have to set it to true.
+ config.eager_load = false
+
+ # Configure static file server for tests with Cache-Control for performance.
+ config.serve_static_files = true
+ config.static_cache_control = 'public, max-age=3600'
+
+ # Show full error reports and disable caching.
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Raise exceptions instead of rendering exception templates.
+ config.action_dispatch.show_exceptions = false
+
+ # Disable request forgery protection in test environment.
+ config.action_controller.allow_forgery_protection = false
+
+ # Tell Action Mailer not to deliver emails to the real world.
+ # The :test delivery method accumulates sent emails in the
+ # ActionMailer::Base.deliveries array.
+ config.action_mailer.delivery_method = :test
+
+ # Randomize the order test cases are executed.
+ config.active_support.test_order = :random
+
+ # Print deprecation notices to the stderr.
+ config.active_support.deprecation = :stderr
+
+ # Raises error for missing translations
+ # config.action_view.raise_on_missing_translations = true
+end
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
new file mode 100644
index 0000000..01ef3e6
--- /dev/null
+++ b/config/initializers/assets.rb
@@ -0,0 +1,11 @@
+# Be sure to restart your server when you modify this file.
+
+# Version of your assets, change this if you want to expire all your assets.
+Rails.application.config.assets.version = '1.0'
+
+# Add additional assets to the asset load path
+# Rails.application.config.assets.paths << Emoji.images_path
+
+# Precompile additional assets.
+# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
+# Rails.application.config.assets.precompile += %w( search.js )
diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb
new file mode 100644
index 0000000..59385cd
--- /dev/null
+++ b/config/initializers/backtrace_silencers.rb
@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
+# Rails.backtrace_cleaner.remove_silencers!
diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb
new file mode 100644
index 0000000..7f70458
--- /dev/null
+++ b/config/initializers/cookies_serializer.rb
@@ -0,0 +1,3 @@
+# Be sure to restart your server when you modify this file.
+
+Rails.application.config.action_dispatch.cookies_serializer = :json
diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb
new file mode 100644
index 0000000..4a994e1
--- /dev/null
+++ b/config/initializers/filter_parameter_logging.rb
@@ -0,0 +1,4 @@
+# Be sure to restart your server when you modify this file.
+
+# Configure sensitive parameters which will be filtered from the log file.
+Rails.application.config.filter_parameters += [:password]
diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb
new file mode 100644
index 0000000..ac033bf
--- /dev/null
+++ b/config/initializers/inflections.rb
@@ -0,0 +1,16 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format. Inflections
+# are locale specific, and you may define rules for as many different
+# locales as you wish. All of these examples are active by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.plural /^(ox)$/i, '\1en'
+# inflect.singular /^(ox)en/i, '\1'
+# inflect.irregular 'person', 'people'
+# inflect.uncountable %w( fish sheep )
+# end
+
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.acronym 'RESTful'
+# end
diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb
new file mode 100644
index 0000000..dc18996
--- /dev/null
+++ b/config/initializers/mime_types.rb
@@ -0,0 +1,4 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new mime types for use in respond_to blocks:
+# Mime::Type.register "text/richtext", :rtf
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
new file mode 100644
index 0000000..3487bbe
--- /dev/null
+++ b/config/initializers/session_store.rb
@@ -0,0 +1,3 @@
+# Be sure to restart your server when you modify this file.
+
+Rails.application.config.session_store :cookie_store, key: '_shipping-service_session'
diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb
new file mode 100644
index 0000000..33725e9
--- /dev/null
+++ b/config/initializers/wrap_parameters.rb
@@ -0,0 +1,14 @@
+# Be sure to restart your server when you modify this file.
+
+# This file contains settings for ActionController::ParamsWrapper which
+# is enabled by default.
+
+# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
+ActiveSupport.on_load(:action_controller) do
+ wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
+end
+
+# To enable root element in JSON for ActiveRecord objects.
+# ActiveSupport.on_load(:active_record) do
+# self.include_root_in_json = true
+# end
diff --git a/config/locales/en.yml b/config/locales/en.yml
new file mode 100644
index 0000000..0653957
--- /dev/null
+++ b/config/locales/en.yml
@@ -0,0 +1,23 @@
+# Files in the config/locales directory are used for internationalization
+# and are automatically loaded by Rails. If you want to use locales other
+# than English, add the necessary files in this directory.
+#
+# To use the locales, use `I18n.t`:
+#
+# I18n.t 'hello'
+#
+# In views, this is aliased to just `t`:
+#
+# <%= t('hello') %>
+#
+# To use a different locale, set it with `I18n.locale`:
+#
+# I18n.locale = :es
+#
+# This would use the information in config/locales/es.yml.
+#
+# To learn more, please read the Rails Internationalization guide
+# available at http://guides.rubyonrails.org/i18n.html.
+
+en:
+ hello: "Hello world"
diff --git a/config/routes.rb b/config/routes.rb
new file mode 100644
index 0000000..0eedcc3
--- /dev/null
+++ b/config/routes.rb
@@ -0,0 +1,57 @@
+Rails.application.routes.draw do
+ get '/ship' => 'carriers#index'
+ # The priority is based upon order of creation: first created -> highest priority.
+ # See how all your routes lay out with "rake routes".
+
+ # You can have the root of your site routed with "root"
+ # root 'welcome#index'
+
+ # Example of regular route:
+ # get 'products/:id' => 'catalog#view'
+
+ # Example of named route that can be invoked with purchase_url(id: product.id)
+ # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
+
+ # Example resource route (maps HTTP verbs to controller actions automatically):
+ # resources :products
+
+ # Example resource route with options:
+ # resources :products do
+ # member do
+ # get 'short'
+ # post 'toggle'
+ # end
+ #
+ # collection do
+ # get 'sold'
+ # end
+ # end
+
+ # Example resource route with sub-resources:
+ # resources :products do
+ # resources :comments, :sales
+ # resource :seller
+ # end
+
+ # Example resource route with more complex sub-resources:
+ # resources :products do
+ # resources :comments
+ # resources :sales do
+ # get 'recent', on: :collection
+ # end
+ # end
+
+ # Example resource route with concerns:
+ # concern :toggleable do
+ # post 'toggle'
+ # end
+ # resources :posts, concerns: :toggleable
+ # resources :photos, concerns: :toggleable
+
+ # Example resource route within a namespace:
+ # namespace :admin do
+ # # Directs /admin/products/* to Admin::ProductsController
+ # # (app/controllers/admin/products_controller.rb)
+ # resources :products
+ # end
+end
diff --git a/db/schema.rb b/db/schema.rb
new file mode 100644
index 0000000..35b6be2
--- /dev/null
+++ b/db/schema.rb
@@ -0,0 +1,12 @@
+# encoding: UTF-8
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# Note that this schema.rb definition is the authoritative source for your
+# database schema. If you need to create the application database on another
+# system, you should be using db:schema:load, not running all the migrations
+# from scratch. The latter is a flawed and unsustainable approach (the more migrations
+# you'll amass, the slower it'll run and the greater likelihood for issues).
+#
+# It's strongly recommended that you check this file into your version control system.
diff --git a/db/seeds.rb b/db/seeds.rb
new file mode 100644
index 0000000..4edb1e8
--- /dev/null
+++ b/db/seeds.rb
@@ -0,0 +1,7 @@
+# This file should contain all the record creation needed to seed the database with its default values.
+# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
+#
+# Examples:
+#
+# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
+# Mayor.create(name: 'Emanuel', city: cities.first)
diff --git a/lib/assets/.keep b/lib/assets/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/lib/tasks/.keep b/lib/tasks/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/public/404.html b/public/404.html
new file mode 100644
index 0000000..b612547
--- /dev/null
+++ b/public/404.html
@@ -0,0 +1,67 @@
+
+
+
+ The page you were looking for doesn't exist (404)
+
+
+
+
+
+
+
+
+
The page you were looking for doesn't exist.
+
You may have mistyped the address or the page may have moved.
+
+
If you are the application owner check the logs for more information.
+
+
+
diff --git a/public/422.html b/public/422.html
new file mode 100644
index 0000000..a21f82b
--- /dev/null
+++ b/public/422.html
@@ -0,0 +1,67 @@
+
+
+
+ The change you wanted was rejected (422)
+
+
+
+
+
+
+
+
+
The change you wanted was rejected.
+
Maybe you tried to change something you didn't have access to.
+
+
If you are the application owner check the logs for more information.
+
+
+
diff --git a/public/500.html b/public/500.html
new file mode 100644
index 0000000..061abc5
--- /dev/null
+++ b/public/500.html
@@ -0,0 +1,66 @@
+
+
+
+ We're sorry, but something went wrong (500)
+
+
+
+
+
+
+
+
+
We're sorry, but something went wrong.
+
+
If you are the application owner check the logs for more information.
+
+
+
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..e69de29
diff --git a/public/robots.txt b/public/robots.txt
new file mode 100644
index 0000000..3c9c7c0
--- /dev/null
+++ b/public/robots.txt
@@ -0,0 +1,5 @@
+# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
+#
+# To ban all spiders from the entire site uncomment the next two lines:
+# User-agent: *
+# Disallow: /
diff --git a/spec/controllers/carriers_controller_spec.rb b/spec/controllers/carriers_controller_spec.rb
new file mode 100644
index 0000000..eb65155
--- /dev/null
+++ b/spec/controllers/carriers_controller_spec.rb
@@ -0,0 +1,59 @@
+require 'rails_helper'
+
+RSpec.describe CarriersController, type: :controller do
+ describe "GET index" do
+ let(:query) do
+ {
+ origin: {
+ :country=>"US",
+ :state=>"CA",
+ :city=>"Beverly Hills",
+ :zip=>"90210"
+ },
+ destination: {
+ :country=>"US",
+ :state=>"WA",
+ :city=>"Seattle",
+ :zip=>"98103"},
+ packages: [
+ {
+ :weight=>100,
+ :height=>50,
+ :length=>20,
+ :width=>30
+ }
+ ]
+ }
+ end
+
+ context "shipping rates" do
+ it "generates UPS rates", :vcr do
+ get :index, query
+ expect(assigns(:ups_rates)).to be_an(Array)
+ end
+
+ it "generates USPS rates", :vcr do
+ get :index, query
+ expect(assigns(:usps_rates)).to be_an(Array)
+ end
+ end
+
+ context "missing shipping rates" do
+ it "both rates are missing" do
+ allow(Carrier).to receive(:get_rates).and_return([nil, nil])
+ get :index, query
+ expect(response.response_code).to eq 204
+ end
+ it "only USPS is missing" do
+ allow(Carrier).to receive(:get_rates).and_return([Array.new, nil])
+ get :index, query
+ expect(response.response_code).to eq 200
+ end
+ it "only UPS is missing" do
+ allow(Carrier).to receive(:get_rates).and_return([nil, Array.new])
+ get :index, query
+ expect(response.response_code).to eq 200
+ end
+ end
+ end
+end
diff --git a/spec/factories.rb b/spec/factories.rb
new file mode 100644
index 0000000..e69de29
diff --git a/spec/helpers/carriers_helper_spec.rb b/spec/helpers/carriers_helper_spec.rb
new file mode 100644
index 0000000..0a24eb5
--- /dev/null
+++ b/spec/helpers/carriers_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'rails_helper'
+
+# Specs in this file have access to a helper object that includes
+# the CarriersHelper. For example:
+#
+# describe CarriersHelper do
+# describe "string concat" do
+# it "concats two strings with spaces" do
+# expect(helper.concat_strings("this","that")).to eq("this that")
+# end
+# end
+# end
+RSpec.describe CarriersHelper, type: :helper do
+ # pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/models/carrier_spec.rb b/spec/models/carrier_spec.rb
new file mode 100644
index 0000000..a5ccb5b
--- /dev/null
+++ b/spec/models/carrier_spec.rb
@@ -0,0 +1,117 @@
+require 'rails_helper'
+
+RSpec.describe Carrier, type: :model do
+ describe ".get_rates" do
+ context "timeout" do
+ let(:query) do
+ {
+ origin: {
+ :country=>"US",
+ :state=>"CA",
+ :city=>"Beverly Hills",
+ :zip=>"90210"
+ },
+ destination: {
+ :country=>"US",
+ :state=>"WA",
+ :city=>"Seattle",
+ :zip=>"98103"},
+ packages: [
+ {
+ :weight=>100,
+ :height=>50,
+ :length=>20,
+ :width=>30
+ }
+ ]
+ }
+ end
+
+ it "UPS times out", :vcr do
+ allow(Carrier).to receive(:activate_ups).and_raise(Timeout::Error)
+ carrier = Carrier.get_rates(query)
+ expect(carrier[0]).to be_nil
+ expect(carrier[1]).not_to be_nil
+ end
+ it "USPS times out", :vcr do
+ allow(Carrier).to receive(:activate_usps).and_raise(Timeout::Error)
+ carrier = Carrier.get_rates(query)
+ expect(carrier[1]).to be_nil
+ expect(carrier[0]).not_to be_nil
+ end
+ end
+ end
+
+ describe ".activate_ups" do
+ it "sets up UPS credentials" do
+ response = Carrier.activate_ups
+ expect(response).to be_an_instance_of ActiveShipping::UPS
+ end
+ end
+
+ describe ".activate_usps" do
+ it "sets up USPS credentials" do
+ response = Carrier.activate_usps
+ expect(response).to be_an_instance_of ActiveShipping::USPS
+ end
+ end
+
+ describe ".create_origin" do
+ let(:origin_params) do
+ {
+ country: 'US',
+ state: 'WA',
+ city: 'Seattle',
+ zip: '98103'
+ }
+ end
+
+ it "creates a new Location object" do
+ expect(Carrier.create_origin(origin_params)).to be_an_instance_of ActiveShipping::Location
+ end
+ end
+
+ describe ".create_destination" do
+ let(:destination_params) do
+ {
+ country: 'US',
+ state: 'WA',
+ city: 'Seattle',
+ zip: '98103'
+ }
+ end
+
+ it "creates a new Location object" do
+ expect(Carrier.create_destination(destination_params)).to be_an_instance_of ActiveShipping::Location
+ end
+ end
+
+ describe ".create_packages" do
+ let(:package_params) do
+ [
+ {
+ weight: 100,
+ height: 50,
+ length: 20,
+ width: 30
+ },
+ {
+ weight: 200,
+ height: 30,
+ length: 10,
+ width: 22
+ },
+ ]
+ end
+
+ it "returns an array" do
+ expect(Carrier.create_packages(package_params)).to be_an Array
+ end
+
+ it "creates Package objects" do
+ expect(Carrier.create_packages(package_params)[0]).to be_an_instance_of ActiveShipping::Package
+ end
+
+ end
+
+end
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
new file mode 100644
index 0000000..8365558
--- /dev/null
+++ b/spec/rails_helper.rb
@@ -0,0 +1,64 @@
+# This file is copied to spec/ when you run 'rails generate rspec:install'
+ENV['RAILS_ENV'] ||= 'test'
+require File.expand_path('../../config/environment', __FILE__)
+# Prevent database truncation if the environment is production
+abort("The Rails environment is running in production mode!") if Rails.env.production?
+require 'spec_helper'
+require 'rspec/rails'
+# Add additional requires below this line. Rails is not loaded until this point!
+
+# Requires supporting ruby files with custom matchers and macros, etc, in
+# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
+# run as spec files by default. This means that files in spec/support that end
+# in _spec.rb will both be required and run as specs, causing the specs to be
+# run twice. It is recommended that you do not name files matching this glob to
+# end with _spec.rb. You can configure this pattern with the --pattern
+# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
+#
+# The following line is provided for convenience purposes. It has the downside
+# of increasing the boot-up time by auto-requiring all files in the support
+# directory. Alternatively, in the individual `*_spec.rb` files, manually
+# require only the support files necessary.
+#
+# Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
+
+# Checks for pending migration and applies them before tests are run.
+# If you are not using ActiveRecord, you can remove this line.
+ActiveRecord::Migration.maintain_test_schema!
+
+RSpec.configure do |config|
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
+
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
+ # examples within a transaction, remove the following line or assign false
+ # instead of true.
+ config.use_transactional_fixtures = true
+
+ # RSpec Rails can automatically mix in different behaviours to your tests
+ # based on their file location, for example enabling you to call `get` and
+ # `post` in specs under `spec/controllers`.
+ #
+ # You can disable this behaviour by removing the line below, and instead
+ # explicitly tag your specs with their type, e.g.:
+ #
+ # RSpec.describe UsersController, :type => :controller do
+ # # ...
+ # end
+ #
+ # The different available types are documented in the features, such as in
+ # https://relishapp.com/rspec/rspec-rails/docs
+ config.infer_spec_type_from_file_location!
+
+ # Filter lines from Rails gems in backtraces.
+ config.filter_rails_from_backtrace!
+ # arbitrary gems may also be filtered via:
+ # config.filter_gems_from_backtrace("gem name")
+end
+
+VCR.configure do |c|
+ c.cassette_library_dir = 'spec/vcr'
+ c.hook_into :webmock # or :fakeweb
+ c.allow_http_connections_when_no_cassette = true
+ c.configure_rspec_metadata!
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..d0e201b
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,104 @@
+require 'factory_girl'
+require 'simplecov'
+require 'vcr'
+
+SimpleCov.start do
+ add_filter '/spec'
+end
+
+# This file was generated by the `rails generate rspec:install` command. Conventionally, all
+# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
+# The generated `.rspec` file contains `--require spec_helper` which will cause
+# this file to always be loaded, without a need to explicitly require it in any
+# files.
+#
+# Given that it is always loaded, you are encouraged to keep this file as
+# light-weight as possible. Requiring heavyweight dependencies from this file
+# will add to the boot time of your test suite on EVERY test run, even for an
+# individual file that may not need all of that loaded. Instead, consider making
+# a separate helper file that requires the additional dependencies and performs
+# the additional setup, and require it from the spec files that actually need
+# it.
+#
+# The `.rspec` file also contains a few flags that are not defaults but that
+# users commonly want.
+#
+# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+RSpec.configure do |config|
+ config.include FactoryGirl::Syntax::Methods
+ # rspec-expectations config goes here. You can use an alternate
+ # assertion/expectation library such as wrong or the stdlib/minitest
+ # assertions if you prefer.
+ config.alias_example_to :fit, focused: true
+ config.filter_run focused: true
+ config.run_all_when_everything_filtered = true
+ config.expect_with :rspec do |expectations|
+ # This option will default to `true` in RSpec 4. It makes the `description`
+ # and `failure_message` of custom matchers include text for helper methods
+ # defined using `chain`, e.g.:
+ # be_bigger_than(2).and_smaller_than(4).description
+ # # => "be bigger than 2 and smaller than 4"
+ # ...rather than:
+ # # => "be bigger than 2"
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
+ end
+
+ # rspec-mocks config goes here. You can use an alternate test double
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
+ config.mock_with :rspec do |mocks|
+ # Prevents you from mocking or stubbing a method that does not exist on
+ # a real object. This is generally recommended, and will default to
+ # `true` in RSpec 4.
+ mocks.verify_partial_doubles = true
+ end
+
+# The settings below are suggested to provide a good initial experience
+# with RSpec, but feel free to customize to your heart's content.
+=begin
+ # These two settings work together to allow you to limit a spec run
+ # to individual examples or groups you care about by tagging them with
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
+ # get run.
+ config.filter_run :focus
+ config.run_all_when_everything_filtered = true
+
+ # Allows RSpec to persist some state between runs in order to support
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
+ # you configure your source control system to ignore this file.
+ config.example_status_persistence_file_path = "spec/examples.txt"
+
+ # Limits the available syntax to the non-monkey patched syntax that is
+ # recommended. For more details, see:
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
+ config.disable_monkey_patching!
+
+ # Many RSpec users commonly either run the entire suite or an individual
+ # file, and it's useful to allow more verbose output when running an
+ # individual spec file.
+ if config.files_to_run.one?
+ # Use the documentation formatter for detailed output,
+ # unless a formatter has already been configured
+ # (e.g. via a command-line flag).
+ config.default_formatter = 'doc'
+ end
+
+ # Print the 10 slowest examples and example groups at the
+ # end of the spec run, to help surface which specs are running
+ # particularly slow.
+ config.profile_examples = 10
+
+ # Run specs in random order to surface order dependencies. If you find an
+ # order dependency and want to debug it, you can fix the order by providing
+ # the seed, which is printed after each run.
+ # --seed 1234
+ config.order = :random
+
+ # Seed global randomization in this process using the `--seed` CLI option.
+ # Setting this allows you to use `--seed` to deterministically reproduce
+ # test failures related to randomization by passing the same `--seed` value
+ # as the one that triggered the failure.
+ Kernel.srand config.seed
+=end
+end
diff --git a/spec/vcr/Carrier/_get_rates/timeout/UPS_times_out.yml b/spec/vcr/Carrier/_get_rates/timeout/UPS_times_out.yml
new file mode 100644
index 0000000..77b2972
--- /dev/null
+++ b/spec/vcr/Carrier/_get_rates/timeout/UPS_times_out.yml
@@ -0,0 +1,56 @@
+---
+http_interactions:
+- request:
+ method: get
+ uri: http://production.shippingapis.com/ShippingAPI.dll?API=RateV4&XML=%3C?xml%20version=%221.0%22?%3E%0A%3CRateV4Request%20USERID=%22827ADADE7850%22%3E%0A%20%20%3CPackage%20ID=%220%22%3E%0A%20%20%20%20%3CService%3EALL%3C/Service%3E%0A%20%20%20%20%3CFirstClassMailType/%3E%0A%20%20%20%20%3CZipOrigination%3E90210%3C/ZipOrigination%3E%0A%20%20%20%20%3CZipDestination%3E98103%3C/ZipDestination%3E%0A%20%20%20%20%3CPounds%3E0%3C/Pounds%3E%0A%20%20%20%20%3COunces%3E3.5%3C/Ounces%3E%0A%20%20%20%20%3CContainer%3ERECTANGULAR%3C/Container%3E%0A%20%20%20%20%3CSize%3ELARGE%3C/Size%3E%0A%20%20%20%20%3CWidth%3E11.81%3C/Width%3E%0A%20%20%20%20%3CLength%3E19.69%3C/Length%3E%0A%20%20%20%20%3CHeight%3E7.87%3C/Height%3E%0A%20%20%20%20%3CGirth%3E39.37%3C/Girth%3E%0A%20%20%20%20%3CMachinable%3EFALSE%3C/Machinable%3E%0A%20%20%3C/Package%3E%0A%3C/RateV4Request%3E%0A
+ body:
+ encoding: US-ASCII
+ string: ''
+ headers:
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ X-Backside-Transport:
+ - OK OK
+ Cache-Control:
+ - private
+ Content-Type:
+ - text/xml
+ Server:
+ - Microsoft-IIS/7.5
+ X-Aspnet-Version:
+ - 2.0.50727
+ X-Powered-By:
+ - ASP.NET
+ Date:
+ - Fri, 22 Jan 2016 02:14:12 GMT
+ X-Client-Ip:
+ - 56.0.70.6
+ X-Global-Transaction-Id:
+ - '174400401'
+ Access-Control-Allow-Origin:
+ - "*"
+ Connection:
+ - Keep-Alive
+ Ntcoent-Length:
+ - '1217'
+ X-Frame-Options:
+ - SAMEORIGIN
+ Content-Length:
+ - '413'
+ body:
+ encoding: ASCII-8BIT
+ string: |-
+
+ 902109810303.5LARGEFALSE5Priority Mail Express 2-Day<sup>™</sup>25.75Priority Mail Express 2-Day<sup>™</sup> Hold For Pickup25.75Priority Mail 2-Day<sup>™</sup>25.95First-Class Mail<sup>®</sup> Parcel2.74USPS Retail Ground<sup>™</sup>6.89Media Mail Parcel2.72Library Mail Parcel2.59
+ http_version:
+ recorded_at: Fri, 22 Jan 2016 02:14:13 GMT
+recorded_with: VCR 3.0.1
diff --git a/spec/vcr/Carrier/_get_rates/timeout/USPS_times_out.yml b/spec/vcr/Carrier/_get_rates/timeout/USPS_times_out.yml
new file mode 100644
index 0000000..11bdc05
--- /dev/null
+++ b/spec/vcr/Carrier/_get_rates/timeout/USPS_times_out.yml
@@ -0,0 +1,103 @@
+---
+http_interactions:
+- request:
+ method: post
+ uri: https://onlinetools.ups.com/ups.app/xml/Rate
+ body:
+ encoding: UTF-8
+ string: |
+
+
+ CD02C929D1E30C85
+ jennaplusplus
+ sharktothorpec4
+
+
+
+
+ Rate
+ Shop
+
+
+ 01
+
+
+ 01
+
+
+
+
+ Beverly Hills
+ CA
+ 90210
+ US
+ true
+
+
+
+
+ Seattle
+ WA
+ 98103
+ US
+ true
+
+
+
+
+ 02
+
+
+
+ IN
+
+ 19.685
+ 11.811
+ 7.874
+
+
+
+ LBS
+
+ 0.22
+
+
+
+
+
+ headers:
+ Content-Type:
+ - application/x-www-form-urlencoded
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Fri, 22 Jan 2016 02:18:32 GMT
+ Server:
+ - Apache
+ X-Frame-Options:
+ - SAMEORIGIN
+ Pragma:
+ - no-cache
+ Content-Length:
+ - '7216'
+ X-Content-Type-Options:
+ - nosniff
+ Content-Type:
+ - application/xml
+ body:
+ encoding: UTF-8
+ string: |-
+
+ 1Success03
Your invoice may vary from the displayed reference ratesLBS
12.0USD16.17USD0.00USD16.17USD16.17USD0.00USD16.170.3LBS
12.012
Your invoice may vary from the displayed reference ratesLBS
12.0USD36.54USD0.00USD36.543USD36.54USD0.00USD36.540.3LBS
12.002
Your invoice may vary from the displayed reference ratesLBS
12.0USD54.42USD0.00USD54.422USD54.42USD0.00USD54.420.3LBS
12.013
Your invoice may vary from the displayed reference ratesLBS
12.0USD116.92USD0.00USD116.921USD116.92USD0.00USD116.920.3LBS
12.014
Your invoice may vary from the displayed reference ratesLBS
12.0USD162.76USD0.00USD162.7618:00 A.M.USD162.76USD0.00USD162.760.3LBS
12.001
Your invoice may vary from the displayed reference ratesLBS
12.0USD131.48USD0.00USD131.48110:30 A.M.USD131.48USD0.00USD131.480.3LBS
12.0
+ http_version:
+ recorded_at: Fri, 22 Jan 2016 02:18:33 GMT
+recorded_with: VCR 3.0.1
diff --git a/spec/vcr/CarriersController/GET_index/shipping_rates/generates_UPS_rates.yml b/spec/vcr/CarriersController/GET_index/shipping_rates/generates_UPS_rates.yml
new file mode 100644
index 0000000..f9b9a8f
--- /dev/null
+++ b/spec/vcr/CarriersController/GET_index/shipping_rates/generates_UPS_rates.yml
@@ -0,0 +1,156 @@
+---
+http_interactions:
+- request:
+ method: post
+ uri: https://onlinetools.ups.com/ups.app/xml/Rate
+ body:
+ encoding: UTF-8
+ string: |
+
+
+ CD02C929D1E30C85
+ jennaplusplus
+ sharktothorpec4
+
+
+
+
+ Rate
+ Shop
+
+
+ 01
+
+
+ 01
+
+
+
+
+ Beverly Hills
+ CA
+ 90210
+ US
+ true
+
+
+
+
+ Seattle
+ WA
+ 98103
+ US
+ true
+
+
+
+
+ 02
+
+
+
+ IN
+
+ 19.685
+ 11.811
+ 7.874
+
+
+
+ LBS
+
+ 0.22
+
+
+
+
+
+ headers:
+ Content-Type:
+ - application/x-www-form-urlencoded
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Thu, 21 Jan 2016 23:46:53 GMT
+ Server:
+ - Apache
+ X-Frame-Options:
+ - SAMEORIGIN
+ Pragma:
+ - no-cache
+ Content-Length:
+ - '7216'
+ X-Content-Type-Options:
+ - nosniff
+ Content-Type:
+ - application/xml
+ body:
+ encoding: UTF-8
+ string: |-
+
+ 1Success03
Your invoice may vary from the displayed reference ratesLBS
12.0USD16.17USD0.00USD16.17USD16.17USD0.00USD16.170.3LBS
12.012
Your invoice may vary from the displayed reference ratesLBS
12.0USD36.54USD0.00USD36.543USD36.54USD0.00USD36.540.3LBS
12.002
Your invoice may vary from the displayed reference ratesLBS
12.0USD54.42USD0.00USD54.422USD54.42USD0.00USD54.420.3LBS
12.013
Your invoice may vary from the displayed reference ratesLBS
12.0USD116.92USD0.00USD116.921USD116.92USD0.00USD116.920.3LBS
12.014
Your invoice may vary from the displayed reference ratesLBS
12.0USD162.76USD0.00USD162.7618:00 A.M.USD162.76USD0.00USD162.760.3LBS
12.001
Your invoice may vary from the displayed reference ratesLBS
12.0USD131.48USD0.00USD131.48110:30 A.M.USD131.48USD0.00USD131.480.3LBS
12.0
+ http_version:
+ recorded_at: Thu, 21 Jan 2016 23:46:54 GMT
+- request:
+ method: get
+ uri: http://production.shippingapis.com/ShippingAPI.dll?API=RateV4&XML=%3C?xml%20version=%221.0%22?%3E%0A%3CRateV4Request%20USERID=%22827ADADE7850%22%3E%0A%20%20%3CPackage%20ID=%220%22%3E%0A%20%20%20%20%3CService%3EALL%3C/Service%3E%0A%20%20%20%20%3CFirstClassMailType/%3E%0A%20%20%20%20%3CZipOrigination%3E90210%3C/ZipOrigination%3E%0A%20%20%20%20%3CZipDestination%3E98103%3C/ZipDestination%3E%0A%20%20%20%20%3CPounds%3E0%3C/Pounds%3E%0A%20%20%20%20%3COunces%3E3.5%3C/Ounces%3E%0A%20%20%20%20%3CContainer%3ERECTANGULAR%3C/Container%3E%0A%20%20%20%20%3CSize%3ELARGE%3C/Size%3E%0A%20%20%20%20%3CWidth%3E11.81%3C/Width%3E%0A%20%20%20%20%3CLength%3E19.69%3C/Length%3E%0A%20%20%20%20%3CHeight%3E7.87%3C/Height%3E%0A%20%20%20%20%3CGirth%3E39.37%3C/Girth%3E%0A%20%20%20%20%3CMachinable%3EFALSE%3C/Machinable%3E%0A%20%20%3C/Package%3E%0A%3C/RateV4Request%3E%0A
+ body:
+ encoding: US-ASCII
+ string: ''
+ headers:
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ X-Backside-Transport:
+ - OK OK
+ Cache-Control:
+ - private
+ Content-Type:
+ - text/xml
+ Server:
+ - Microsoft-IIS/7.5
+ X-Aspnet-Version:
+ - 2.0.50727
+ X-Powered-By:
+ - ASP.NET
+ Date:
+ - Thu, 21 Jan 2016 23:46:54 GMT
+ X-Client-Ip:
+ - 56.0.70.6
+ X-Global-Transaction-Id:
+ - '194461519'
+ Access-Control-Allow-Origin:
+ - "*"
+ Connection:
+ - Keep-Alive
+ Ntcoent-Length:
+ - '1217'
+ X-Frame-Options:
+ - SAMEORIGIN
+ Content-Length:
+ - '413'
+ body:
+ encoding: ASCII-8BIT
+ string: |-
+
+ 902109810303.5LARGEFALSE5Priority Mail Express 2-Day<sup>™</sup>25.75Priority Mail Express 2-Day<sup>™</sup> Hold For Pickup25.75Priority Mail 2-Day<sup>™</sup>25.95First-Class Mail<sup>®</sup> Parcel2.74USPS Retail Ground<sup>™</sup>6.89Media Mail Parcel2.72Library Mail Parcel2.59
+ http_version:
+ recorded_at: Thu, 21 Jan 2016 23:46:55 GMT
+recorded_with: VCR 3.0.1
diff --git a/spec/vcr/CarriersController/GET_index/shipping_rates/generates_USPS_rates.yml b/spec/vcr/CarriersController/GET_index/shipping_rates/generates_USPS_rates.yml
new file mode 100644
index 0000000..ec87690
--- /dev/null
+++ b/spec/vcr/CarriersController/GET_index/shipping_rates/generates_USPS_rates.yml
@@ -0,0 +1,156 @@
+---
+http_interactions:
+- request:
+ method: post
+ uri: https://onlinetools.ups.com/ups.app/xml/Rate
+ body:
+ encoding: UTF-8
+ string: |
+
+
+ CD02C929D1E30C85
+ jennaplusplus
+ sharktothorpec4
+
+
+
+
+ Rate
+ Shop
+
+
+ 01
+
+
+ 01
+
+
+
+
+ Beverly Hills
+ CA
+ 90210
+ US
+ true
+
+
+
+
+ Seattle
+ WA
+ 98103
+ US
+ true
+
+
+
+
+ 02
+
+
+
+ IN
+
+ 19.685
+ 11.811
+ 7.874
+
+
+
+ LBS
+
+ 0.22
+
+
+
+
+
+ headers:
+ Content-Type:
+ - application/x-www-form-urlencoded
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Fri, 22 Jan 2016 00:22:20 GMT
+ Server:
+ - Apache
+ X-Frame-Options:
+ - SAMEORIGIN
+ Pragma:
+ - no-cache
+ Content-Length:
+ - '7216'
+ X-Content-Type-Options:
+ - nosniff
+ Content-Type:
+ - application/xml
+ body:
+ encoding: UTF-8
+ string: |-
+
+ 1Success03
Your invoice may vary from the displayed reference ratesLBS
12.0USD16.17USD0.00USD16.17USD16.17USD0.00USD16.170.3LBS
12.012
Your invoice may vary from the displayed reference ratesLBS
12.0USD36.54USD0.00USD36.543USD36.54USD0.00USD36.540.3LBS
12.002
Your invoice may vary from the displayed reference ratesLBS
12.0USD54.42USD0.00USD54.422USD54.42USD0.00USD54.420.3LBS
12.013
Your invoice may vary from the displayed reference ratesLBS
12.0USD116.92USD0.00USD116.921USD116.92USD0.00USD116.920.3LBS
12.014
Your invoice may vary from the displayed reference ratesLBS
12.0USD162.76USD0.00USD162.7618:00 A.M.USD162.76USD0.00USD162.760.3LBS
12.001
Your invoice may vary from the displayed reference ratesLBS
12.0USD131.48USD0.00USD131.48110:30 A.M.USD131.48USD0.00USD131.480.3LBS
12.0
+ http_version:
+ recorded_at: Fri, 22 Jan 2016 00:22:20 GMT
+- request:
+ method: get
+ uri: http://production.shippingapis.com/ShippingAPI.dll?API=RateV4&XML=%3C?xml%20version=%221.0%22?%3E%0A%3CRateV4Request%20USERID=%22827ADADE7850%22%3E%0A%20%20%3CPackage%20ID=%220%22%3E%0A%20%20%20%20%3CService%3EALL%3C/Service%3E%0A%20%20%20%20%3CFirstClassMailType/%3E%0A%20%20%20%20%3CZipOrigination%3E90210%3C/ZipOrigination%3E%0A%20%20%20%20%3CZipDestination%3E98103%3C/ZipDestination%3E%0A%20%20%20%20%3CPounds%3E0%3C/Pounds%3E%0A%20%20%20%20%3COunces%3E3.5%3C/Ounces%3E%0A%20%20%20%20%3CContainer%3ERECTANGULAR%3C/Container%3E%0A%20%20%20%20%3CSize%3ELARGE%3C/Size%3E%0A%20%20%20%20%3CWidth%3E11.81%3C/Width%3E%0A%20%20%20%20%3CLength%3E19.69%3C/Length%3E%0A%20%20%20%20%3CHeight%3E7.87%3C/Height%3E%0A%20%20%20%20%3CGirth%3E39.37%3C/Girth%3E%0A%20%20%20%20%3CMachinable%3EFALSE%3C/Machinable%3E%0A%20%20%3C/Package%3E%0A%3C/RateV4Request%3E%0A
+ body:
+ encoding: US-ASCII
+ string: ''
+ headers:
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ X-Backside-Transport:
+ - OK OK
+ Cache-Control:
+ - private
+ Content-Type:
+ - text/xml
+ Server:
+ - Microsoft-IIS/7.5
+ X-Aspnet-Version:
+ - 2.0.50727
+ X-Powered-By:
+ - ASP.NET
+ Date:
+ - Fri, 22 Jan 2016 00:22:27 GMT
+ X-Client-Ip:
+ - 56.0.70.6
+ X-Global-Transaction-Id:
+ - '231410061'
+ Access-Control-Allow-Origin:
+ - "*"
+ Connection:
+ - Keep-Alive
+ Ntcoent-Length:
+ - '1217'
+ X-Frame-Options:
+ - SAMEORIGIN
+ Content-Length:
+ - '413'
+ body:
+ encoding: ASCII-8BIT
+ string: |-
+
+ 902109810303.5LARGEFALSE5Priority Mail Express 2-Day<sup>™</sup>25.75Priority Mail Express 2-Day<sup>™</sup> Hold For Pickup25.75Priority Mail 2-Day<sup>™</sup>25.95First-Class Mail<sup>®</sup> Parcel2.74USPS Retail Ground<sup>™</sup>6.89Media Mail Parcel2.72Library Mail Parcel2.59
+ http_version:
+ recorded_at: Fri, 22 Jan 2016 00:22:28 GMT
+recorded_with: VCR 3.0.1
diff --git a/vendor/assets/javascripts/.keep b/vendor/assets/javascripts/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/vendor/assets/stylesheets/.keep b/vendor/assets/stylesheets/.keep
new file mode 100644
index 0000000..e69de29