def build_us_rate_request(packages, origin_zip, destination_zip, options={})
      packages = Array(packages)
      request = XmlNode.new('RateV4Request', :USERID => @options[:login]) do |rate_request|
        packages.each_with_index do |p,id|
          rate_request << XmlNode.new('Package', :ID => id.to_s) do |package|
            package << XmlNode.new('Service', US_SERVICES[options[:service] || :all])
            package << XmlNode.new('ZipOrigination', strip_zip(origin_zip))
            package << XmlNode.new('ZipDestination', strip_zip(destination_zip))
            package << XmlNode.new('Pounds', 0)
            package << XmlNode.new('Ounces', "%0.1f" % [p.ounces,1].max)
            package << XmlNode.new('Container', CONTAINERS[p.options[:container]])
            package << XmlNode.new('Size', USPS.size_code_for(p))
            package << XmlNode.new('Width', "%0.2f" % p.inches(:width))
            package << XmlNode.new('Length', "%0.2f" % p.inches(:length))
            package << XmlNode.new('Height', "%0.2f" % p.inches(:height))
            package << XmlNode.new('Girth', "%0.2f" % p.inches(:girth))
            is_machinable = if p.options.has_key?(:machinable)
              p.options[:machinable] ? true : false
            else
              USPS.package_machinable?(p)
            end
            package << XmlNode.new('Machinable', is_machinable.to_s.upcase)
          end
        end
      end
      URI.encode(save_request(request.to_s))
    end
def build_us_rate_request(packages, origin_zip, destination_zip, options={})
      packages = Array(packages)
      request = XmlNode.new('RateV4Request', :USERID => @options[:login]) do |rate_request|
        packages.each_with_index do |p,id|
          rate_request << XmlNode.new('Package', :ID => id.to_s) do |package|
            package << XmlNode.new('Service', US_SERVICES[options[:service] || :all])
            package << XmlNode.new('ZipOrigination', strip_zip(origin_zip))
            package << XmlNode.new('ZipDestination', strip_zip(destination_zip))
            package << XmlNode.new('Pounds', 0)
            package << XmlNode.new('Ounces', "%0.1f" % [p.ounces,1].max)
            package << XmlNode.new('Container', CONTAINERS[p.options[:container]])
            package << XmlNode.new('Size', USPS.size_code_for(p))
            package << XmlNode.new('Width', "%0.2f" % p.inches(:width))
            package << XmlNode.new('Length', "%0.2f" % p.inches(:length))
            package << XmlNode.new('Height', "%0.2f" % p.inches(:height))
            package << XmlNode.new('Girth', "%0.2f" % p.inches(:girth))
            is_machinable = if p.options.has_key?(:machinable)
              p.options[:machinable] ? true : false
            else
              USPS.package_machinable?(p)
            end
            package << XmlNode.new('Machinable', is_machinable.to_s.upcase)
          end
        end
      end
      URI.encode(save_request(request.to_s))
    end
options[:service] --    One of [:first_class, :priority, :express, :bpm, :parcel,
                          :media, :library, :all]. defaults to :all.
 options[:container] --  One of [:envelope, :box]. defaults to neither (this field has
                          special meaning in the USPS API).
 options[:books] --      Either true or false. Packages of books or other printed matter
                          have a lower weight limit to be considered machinable.
 package.options[:machinable] -- Either true or false. Overrides the detection of
                                  "machinability" entirely.