suitcase 1.1.8 → 1.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +4 -0
- data/README.md +12 -9
- data/Rakefile +4 -2
- data/lib/suitcase/cache.rb +30 -0
- data/lib/suitcase/configuration.rb +32 -0
- data/lib/suitcase/helpers.rb +2 -2
- data/lib/suitcase/hotel/hotel.rb +22 -19
- data/lib/suitcase/hotel/payment_option.rb +14 -0
- data/lib/suitcase/hotel/reservation.rb +5 -0
- data/lib/suitcase/hotel/room.rb +43 -25
- data/lib/suitcase/version.rb +1 -1
- data/lib/suitcase.rb +5 -0
- data/spec/api_key.rb +1 -1
- data/spec/caching_spec.rb +19 -0
- data/spec/hotels_spec.rb +14 -10
- data/spec/payment_options_spec.rb +13 -0
- data/spec/rooms_spec.rb +42 -14
- data/suitcase.gemspec +1 -1
- metadata +22 -18
- data/features/hotels.feature +0 -28
- data/features/step_definitions/hotels_steps.rb +0 -21
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Suitcase
|
1
|
+
Suitcase 
|
2
2
|
========
|
3
3
|
|
4
4
|
Suitcase is a Ruby library that utilizes the EAN (Expedia.com) API for locating available hotels, rental cars, and flights.
|
@@ -6,24 +6,27 @@ Suitcase is a Ruby library that utilizes the EAN (Expedia.com) API for locating
|
|
6
6
|
Installation
|
7
7
|
------------
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
`gem 'suitcase', :git => "http://github.com/thoughtfusion/suitcase.git"` then run `bundle install`. Or install the gem: `gem install suitcase`.
|
12
|
-
|
9
|
+
Install the gem: `gem install suitcase`. Or, to get the latest bleeding edge add this to your project's Gemfile: `gem 'suitcase', :git => "http://github.com/thoughtfusion/suitcase.git"`.
|
13
10
|
|
14
11
|
Usage
|
15
12
|
-----
|
16
13
|
|
17
|
-
First,
|
14
|
+
First, configure the library:
|
18
15
|
|
19
|
-
|
16
|
+
Suitcase::Configuration.hotel_api_key = "..." # set the Hotel API key from developer.ean.com
|
17
|
+
Suitcase::Configuration.cid = "..." # set the CID from developer.ean.com
|
18
|
+
Suitcase::Configuration.cache = Hash.new # set the caching mechanism (see below)
|
20
19
|
|
21
20
|
Find nearby hotels:
|
22
21
|
|
23
|
-
|
24
|
-
hotels = Hotel.find(:location => 'Boston, MA', :results => 10) # Returns 10 closest hotels to Boston, MA
|
22
|
+
hotels = Suitcase::Hotel.find(:location => 'Boston, MA', :results => 10) # Returns 10 closest hotels to Boston, MA
|
25
23
|
room = hotels.first.rooms(arrival: "2/19/2012", departure: "2/26/2012", rooms: [{ children: 1, ages: [8] }, { children: 1, ages: [12] }] # Check the availability of two rooms at that hotel with 1 child in each room of ages 8 and 9
|
26
24
|
room.reserve!(info) # Not yet implemented
|
25
|
+
|
26
|
+
### Caching
|
27
|
+
|
28
|
+
You can setup a cache to store all API requests that do not contain secure information (i.e. anything but booking requests). A cache needs to be able store deeply nested Hashes and have a method called [] to access them. An example of setting the cache is given above.
|
29
|
+
|
27
30
|
Contributing
|
28
31
|
------------
|
29
32
|
Please submit any useful pull requests through GitHub. If you find any bugs, please report them with the issue tracker! Thanks.
|
data/Rakefile
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rspec/core/rake_task"
|
3
3
|
|
4
|
-
task :spec
|
5
|
-
|
4
|
+
task :default => :spec
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
7
|
+
t.rspec_opts = %w(-c --fail-fast --format d)
|
6
8
|
end
|
7
9
|
|
8
10
|
task :install_nodoc => [:build] do
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Suitcase
|
2
|
+
class Cache
|
3
|
+
def initialize(store)
|
4
|
+
@store = store
|
5
|
+
end
|
6
|
+
|
7
|
+
def save_query(action, params, response)
|
8
|
+
params.delete("apiKey")
|
9
|
+
params.delete("cid")
|
10
|
+
@store[action] ||= {}
|
11
|
+
@store[action][params] = response
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_query(action, params)
|
15
|
+
@store[action] ? @store[action][params] : nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def keys
|
19
|
+
@store.keys
|
20
|
+
end
|
21
|
+
|
22
|
+
def cached?(action, params)
|
23
|
+
@store[action] && @store[action][params]
|
24
|
+
end
|
25
|
+
|
26
|
+
def undefine_query(action, params)
|
27
|
+
@store[action].delete(params) if @store[action]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Suitcase
|
2
|
+
class Configuration
|
3
|
+
def self.cache=(store)
|
4
|
+
@@cache = Suitcase::Cache.new(store)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.cache
|
8
|
+
return @@cache if cache?
|
9
|
+
nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.cache?
|
13
|
+
defined? @@cache
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.hotel_api_key=(key)
|
17
|
+
@@hotel_api_key = key
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.hotel_api_key
|
21
|
+
@@hotel_api_key
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.hotel_cid=(cid)
|
25
|
+
@@hotel_cid = cid
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.hotel_cid
|
29
|
+
@@hotel_cid if defined? @@hotel_cid
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/suitcase/helpers.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Suitcase
|
2
2
|
module Helpers
|
3
3
|
def url(method, params, include_key=true, include_cid=true, secure=false, as_form=false)
|
4
|
-
params["apiKey"] =
|
5
|
-
params["cid"] =
|
4
|
+
params["apiKey"] = Configuration.hotel_api_key if include_key
|
5
|
+
params["cid"] = (Configuration.hotel_cid ||= 55505) if include_cid
|
6
6
|
url = "http#{secure ? "s" : ""}://api.ean.com/ean-services/rs/hotel/v3/#{method.to_s}#{as_form ? "" : "?"}"
|
7
7
|
url += params.map { |key, value| "#{key}=#{value}"}.join("&")
|
8
8
|
URI.parse(URI.escape(url))
|
data/lib/suitcase/hotel/hotel.rb
CHANGED
@@ -18,7 +18,7 @@ module Suitcase
|
|
18
18
|
wheelchair_accessible: 8,
|
19
19
|
kitchen: 9 }
|
20
20
|
|
21
|
-
attr_accessor :id, :name, :address, :city, :min_rate, :max_rate, :amenities, :country_code, :high_rate, :low_rate, :longitude, :latitude, :rating, :postal_code, :supplier_type, :images
|
21
|
+
attr_accessor :id, :name, :address, :city, :min_rate, :max_rate, :amenities, :country_code, :high_rate, :low_rate, :longitude, :latitude, :rating, :postal_code, :supplier_type, :images, :nightly_rate_total
|
22
22
|
|
23
23
|
def initialize(info)
|
24
24
|
info.each do |k, v|
|
@@ -35,8 +35,14 @@ module Suitcase
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def self.find_by_id(id)
|
38
|
-
|
39
|
-
|
38
|
+
params = { hotelId: id }
|
39
|
+
if Configuration.cache? and Configuration.cache.cached?(:info, params)
|
40
|
+
raw = Configuration.cache.get_query(:info, params)
|
41
|
+
else
|
42
|
+
url = url(:info, params)
|
43
|
+
raw = parse_response(url)
|
44
|
+
Configuration.cache.save_query(:info, params, raw) if Configuration.cache?
|
45
|
+
end
|
40
46
|
hotel_data = parse_information(raw)
|
41
47
|
Hotel.new(hotel_data)
|
42
48
|
end
|
@@ -74,7 +80,7 @@ module Suitcase
|
|
74
80
|
|
75
81
|
def self.images(parsed)
|
76
82
|
return parsed["HotelInformationResponse"]["HotelImages"]["HotelImage"].map { |image_data| Suitcase::Image.new(image_data) } if parsed["HotelInformationResponse"]
|
77
|
-
return Suitcase::Image.new(
|
83
|
+
return [Suitcase::Image.new("thumbnailURL" => "http://images.travelnow.com" + parsed["thumbNailUrl"])] if parsed["thumbNailUrl"]
|
78
84
|
end
|
79
85
|
|
80
86
|
# Bleghh. so ugly. #needsfixing
|
@@ -94,10 +100,15 @@ module Suitcase
|
|
94
100
|
hotels["HotelSummary"]
|
95
101
|
end
|
96
102
|
|
103
|
+
def thumbnail_url
|
104
|
+
first_image = images.find { |img| img.thumbnail_url != nil }
|
105
|
+
first_image.thumbnail_url if first_image
|
106
|
+
end
|
107
|
+
|
97
108
|
def rooms(info)
|
98
|
-
params = { rooms: [{
|
109
|
+
params = { rooms: [{adults: 1, children_ages: []}] }.merge(info)
|
99
110
|
params[:rooms].each_with_index do |room, n|
|
100
|
-
params["room#{n+1}"] =
|
111
|
+
params["room#{n+1}"] = room[:adults].to_s + "," + (room[:children_ages].join(",") if room[:children_ages])
|
101
112
|
end
|
102
113
|
params["arrivalDate"] = info[:arrival]
|
103
114
|
params["departureDate"] = info[:departure]
|
@@ -119,21 +130,13 @@ module Suitcase
|
|
119
130
|
room_data[:total_price] = raw_data["RateInfo"]["ChargeableRateInfo"]["@total"]
|
120
131
|
room_data[:nightly_rate_total] = raw_data["RateInfo"]["ChargeableRateInfo"]["@nightlyRateTotal"]
|
121
132
|
room_data[:average_nightly_rate] = raw_data["RateInfo"]["ChargeableRateInfo"]["@averageRate"]
|
133
|
+
room_data[:arrival] = info[:arrival]
|
134
|
+
room_data[:departure] = info[:departure]
|
135
|
+
room_data[:rate_key] = rate_key
|
136
|
+
room_data[:hotel_id] = hotel_id
|
137
|
+
room_data[:supplier_type] = supplier_type
|
122
138
|
Room.new(room_data)
|
123
139
|
end
|
124
|
-
RoomGroup.new(rate_key, hotel_id, supplier_type, rooms)
|
125
|
-
end
|
126
|
-
|
127
|
-
def payment_options
|
128
|
-
options = []
|
129
|
-
types_raw = JSON.parse Hotel.hit(url(:paymentInfo, true, true, {}))
|
130
|
-
types_raw["HotelPaymentResponse"].each do |raw|
|
131
|
-
types = raw[0] != "PaymentType" ? [] : raw[1]
|
132
|
-
types.each do |type|
|
133
|
-
options.push PaymentOption.new(type["code"], type["name"])
|
134
|
-
end
|
135
|
-
end
|
136
|
-
options
|
137
140
|
end
|
138
141
|
end
|
139
142
|
end
|
@@ -1,10 +1,24 @@
|
|
1
1
|
module Suitcase
|
2
2
|
class PaymentOption
|
3
3
|
attr_accessor :code, :name
|
4
|
+
extend Suitcase::Helpers
|
4
5
|
|
5
6
|
def initialize(code, name)
|
6
7
|
@code = code
|
7
8
|
@name = name
|
8
9
|
end
|
10
|
+
|
11
|
+
def self.find(info)
|
12
|
+
currency_code = info[:currency_code]
|
13
|
+
types_raw = parse_response(url(:paymentInfo, { "currencyCode" => currency_code }))
|
14
|
+
options = []
|
15
|
+
types_raw["HotelPaymentResponse"].each do |raw|
|
16
|
+
types = raw[0] != "PaymentType" ? [] : raw[1]
|
17
|
+
types.each do |type|
|
18
|
+
options.push PaymentOption.new(type["code"], type["name"])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
options
|
22
|
+
end
|
9
23
|
end
|
10
24
|
end
|
data/lib/suitcase/hotel/room.rb
CHANGED
@@ -1,36 +1,54 @@
|
|
1
1
|
module Suitcase
|
2
|
-
class
|
3
|
-
attr_accessor :rate_key, :hotel_id, :supplier_type, :
|
2
|
+
class Room
|
3
|
+
attr_accessor :rate_key, :hotel_id, :supplier_type, :rate_code, :room_type_code, :supplier_type, :tax_rate, :non_refundable, :occupancy, :quoted_occupancy, :min_guest_age, :total, :surcharge_total, :nightly_rate_total, :average_base_rate, :average_rate, :max_nightly_rate, :currency_code, :value_adds, :room_type_description, :price_breakdown, :total_price, :average_nightly_rate, :promo, :arrival, :departure
|
4
|
+
extend Suitcase::Helpers
|
4
5
|
|
5
|
-
def initialize(
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
@rooms = rooms
|
6
|
+
def initialize(info)
|
7
|
+
info.each do |k, v|
|
8
|
+
instance_variable_set("@" + k.to_s, v)
|
9
|
+
end
|
10
10
|
end
|
11
11
|
|
12
12
|
def reserve!(info)
|
13
|
-
params =
|
14
|
-
params["hotelId"] = @
|
15
|
-
params["arrivalDate"] =
|
16
|
-
params["departureDate"] =
|
17
|
-
params
|
18
|
-
params.delete(:departure)
|
19
|
-
params["supplierType"] = supplier_type
|
13
|
+
params = {}
|
14
|
+
params["hotelId"] = @hotel_id
|
15
|
+
params["arrivalDate"] = @arrival
|
16
|
+
params["departureDate"] = @departure
|
17
|
+
params["supplierType"] = @supplier_type
|
20
18
|
params["rateKey"] = @rate_key
|
21
|
-
params["rateTypeCode"] =
|
22
|
-
params["rateCode"] =
|
23
|
-
params
|
24
|
-
|
19
|
+
params["rateTypeCode"] = @room_type_code
|
20
|
+
params["rateCode"] = @rate_code
|
21
|
+
params["chargeableRate"] = chargeable_rate
|
22
|
+
params["email"] = info[:email]
|
23
|
+
params["firstName"] = info[:first_name]
|
24
|
+
params["lastName"] = info[:last_name]
|
25
|
+
params["homePhone"] = info[:home_phone]
|
26
|
+
params["workPhone"] = info[:work_phone] if info[:work_phone]
|
27
|
+
params["extension"] = info[:work_phone_extension] if info[:work_phone_extension]
|
28
|
+
params["faxPhone"] = info[:fax_phone] if info[:fax_phone]
|
29
|
+
params["companyName"] = info[:company_name] if info[:company_name]
|
30
|
+
params["emailIntineraryList"] = info[:additional_emails].join(",") if info[:additional_emails]
|
31
|
+
params["creditCardType"] = info[:payment_type].code
|
32
|
+
params["creditCardNumber"] = info[:credit_card_number]
|
33
|
+
params["creditCardIdentifier"] = info[:credit_card_verification_code]
|
34
|
+
expiration_date = Date._parse(info[:credit_card_expiration_date])
|
35
|
+
params["creditCardExpirationMonth"] = expiration_date.strftime("%m")
|
36
|
+
params["creditCardExpirationYear"] = expiration_date.strftime("%Y")
|
37
|
+
params["address1"] = info[:address1]
|
38
|
+
params["address2"] = info[:address2]
|
39
|
+
params["address3"] = info[:address3]
|
40
|
+
params["city"] = info[:city]
|
41
|
+
params["stateProvinceCode"] = info[:province]
|
42
|
+
params["countryCode"] = info[:country]
|
43
|
+
params["postalCode"] = info[:postal_code]
|
44
|
+
p url(:getReservation, params)
|
25
45
|
end
|
26
|
-
end
|
27
46
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
instance_variable_set("@" + k.to_s, v)
|
47
|
+
def chargeable_rate
|
48
|
+
if @supplier_type == "E"
|
49
|
+
@total
|
50
|
+
else false
|
51
|
+
@max_nightly_rate
|
34
52
|
end
|
35
53
|
end
|
36
54
|
end
|
data/lib/suitcase/version.rb
CHANGED
data/lib/suitcase.rb
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'net/http'
|
3
|
+
require 'date/format'
|
4
|
+
require 'time'
|
3
5
|
require 'suitcase/core_ext/string'
|
4
6
|
require 'suitcase/version'
|
7
|
+
require 'suitcase/configuration'
|
8
|
+
require 'suitcase/cache'
|
5
9
|
require 'suitcase/helpers'
|
10
|
+
require 'suitcase/hotel/reservation'
|
6
11
|
require 'suitcase/hotel/nightly_rate'
|
7
12
|
require 'suitcase/hotel/room'
|
8
13
|
require 'suitcase/hotel/payment_option'
|
data/spec/api_key.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
Suitcase::
|
1
|
+
Suitcase::Configuration.hotel_api_key = "t3d74e8t58k2nh55gyph3cje"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Suitcase do
|
4
|
+
before :all do
|
5
|
+
Suitcase::Configuration.cache = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should cache all non-secure queries" do
|
9
|
+
Suitcase::Hotel.find(id: 123904)
|
10
|
+
Suitcase::Configuration.cache.keys.count.should eq(1)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should retrieve from the cache if it's there" do
|
14
|
+
lambda do
|
15
|
+
Net::HTTP.stub!(:get_response).and_return nil # disable access to the API
|
16
|
+
Suitcase::Hotel.find(id: 123904)
|
17
|
+
end.should_not raise_error
|
18
|
+
end
|
19
|
+
end
|
data/spec/hotels_spec.rb
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Suitcase::Hotel do
|
4
|
-
|
5
|
-
@hotel
|
4
|
+
before :all do
|
5
|
+
@hotel = Suitcase::Hotel.find(id: 123904)
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
8
|
+
describe "::find" do
|
9
|
+
it "should locate a single Hotel if an id argument is passed" do
|
10
|
+
@hotel.should be_a(Suitcase::Hotel)
|
11
|
+
end
|
13
12
|
|
14
|
-
|
15
|
-
|
13
|
+
it "should locate an Array of Hotels if an id argument is not passed" do
|
14
|
+
hotels = Suitcase::Hotel.find(location: "London, UK")
|
15
|
+
hotels.should be_an(Array)
|
16
|
+
hotels.first.should be_a(Suitcase::Hotel)
|
17
|
+
end
|
16
18
|
end
|
17
19
|
|
18
20
|
subject { @hotel }
|
@@ -32,6 +34,8 @@ describe Suitcase::Hotel do
|
|
32
34
|
it { should respond_to :rating }
|
33
35
|
it { should respond_to :postal_code }
|
34
36
|
it { should respond_to :images }
|
37
|
+
it { should respond_to :thumbnail_url }
|
38
|
+
it { should respond_to :nightly_rate_total }
|
35
39
|
|
36
40
|
it "#images should return an Array of Suitcase::Image's" do
|
37
41
|
images = @hotel.images
|
@@ -50,6 +54,6 @@ describe Suitcase::Hotel do
|
|
50
54
|
@hotel.rooms(@info)
|
51
55
|
end
|
52
56
|
|
53
|
-
it { should be_an(
|
57
|
+
it { should be_an(Array) }
|
54
58
|
end
|
55
59
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Suitcase::PaymentOption do
|
4
|
+
before :all do
|
5
|
+
@info = { currency_code: "USD" }
|
6
|
+
end
|
7
|
+
|
8
|
+
it "::find should return an Array of PaymentOptions" do
|
9
|
+
options = Suitcase::PaymentOption.find(@info)
|
10
|
+
options.should be_an(Array)
|
11
|
+
options.find_all { |opt| opt.class == Suitcase::PaymentOption }.count.should eq(options.count) # It should be an Array of PaymentOption's
|
12
|
+
end
|
13
|
+
end
|
data/spec/rooms_spec.rb
CHANGED
@@ -2,25 +2,53 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Suitcase::Room do
|
4
4
|
before :all do
|
5
|
-
@room = Suitcase::Hotel.find(id: 123904).rooms(arrival: "6/23/2012", departure: "6/30/2012")
|
5
|
+
@room = Suitcase::Hotel.find(id: 123904).rooms(arrival: "6/23/2012", departure: "6/30/2012", rooms: [{ adults: 1, children: 0, children_ages: []}, { adults: 1, children: 0, children_ages: []}]).first
|
6
6
|
end
|
7
7
|
|
8
8
|
subject { @room }
|
9
9
|
it { should respond_to :reserve! }
|
10
|
-
it
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
it { should respond_to :arrival }
|
11
|
+
it { should respond_to :departure }
|
12
|
+
it { should respond_to :rate_code }
|
13
|
+
it { should respond_to :room_type_code }
|
14
|
+
it { should respond_to :supplier_type }
|
15
|
+
it { should respond_to :tax_rate }
|
16
|
+
it { should respond_to :non_refundable }
|
17
|
+
it { should respond_to :occupancy }
|
18
|
+
it { should respond_to :quoted_occupancy }
|
19
|
+
it { should respond_to :min_guest_age }
|
20
|
+
it { should respond_to :total }
|
21
|
+
it { should respond_to :surcharge_total }
|
22
|
+
it { should respond_to :nightly_rate_total }
|
23
|
+
it { should respond_to :average_base_rate }
|
24
|
+
it { should respond_to :average_rate }
|
25
|
+
it { should respond_to :max_nightly_rate }
|
26
|
+
it { should respond_to :currency_code }
|
27
|
+
it { should respond_to :value_adds }
|
28
|
+
it { should respond_to :room_type_description }
|
29
|
+
it { should respond_to :price_breakdown }
|
30
|
+
it { should respond_to :total_price }
|
31
|
+
it { should respond_to :average_nightly_rate }
|
32
|
+
it { should respond_to :promo }
|
33
|
+
it { should respond_to :rate_key }
|
34
|
+
it { should respond_to :hotel_id }
|
35
|
+
it { should respond_to :supplier_type }
|
19
36
|
|
20
|
-
|
37
|
+
describe "#reserve!" do
|
38
|
+
before :all do
|
39
|
+
@info = { email: "walter.john.nelson@gmail.com",
|
40
|
+
first_name: "Walter",
|
41
|
+
last_name: "Nelson",
|
42
|
+
home_phone: "3831039402",
|
43
|
+
credit_card_type: "AX", # American Express
|
44
|
+
credit_card_number: "2384975019283750293874", # not even sure if the length is right
|
45
|
+
credit_card_identifier: "341", # CVV
|
46
|
+
credit_card_expiration_date: "11/2012" }
|
47
|
+
end
|
21
48
|
|
22
|
-
|
23
|
-
|
24
|
-
|
49
|
+
it "should respond to a Hash of arguments" do
|
50
|
+
reservation = @room.reserve!(@info)
|
51
|
+
reservation.should be_a(Suitcase::Reservation)
|
52
|
+
end
|
25
53
|
end
|
26
54
|
end
|
data/suitcase.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
21
|
s.add_development_dependency "rspec"
|
22
|
-
s.add_development_dependency "cucumber"
|
23
22
|
s.add_development_dependency "rake"
|
23
|
+
s.add_development_dependency "factory_girl"
|
24
24
|
s.add_runtime_dependency "json"
|
25
25
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: suitcase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-01-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &19048700 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *19048700
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
27
|
-
requirement: &
|
26
|
+
name: rake
|
27
|
+
requirement: &19047520 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *19047520
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
38
|
-
requirement: &
|
37
|
+
name: factory_girl
|
38
|
+
requirement: &19063900 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *19063900
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: json
|
49
|
-
requirement: &
|
49
|
+
requirement: &19061720 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *19061720
|
58
58
|
description: Suitcase utilizes the EAN (Expedia.com) API for locating info about hotels,
|
59
59
|
rental cars, and flights.
|
60
60
|
email:
|
@@ -65,13 +65,14 @@ extra_rdoc_files: []
|
|
65
65
|
files:
|
66
66
|
- .gitignore
|
67
67
|
- .rspec
|
68
|
+
- .travis.yml
|
68
69
|
- Gemfile
|
69
70
|
- README.md
|
70
71
|
- Rakefile
|
71
|
-
- features/hotels.feature
|
72
|
-
- features/step_definitions/hotels_steps.rb
|
73
72
|
- lib/suitcase.rb
|
74
73
|
- lib/suitcase/airport_codes.rb
|
74
|
+
- lib/suitcase/cache.rb
|
75
|
+
- lib/suitcase/configuration.rb
|
75
76
|
- lib/suitcase/core_ext/string.rb
|
76
77
|
- lib/suitcase/country_codes.rb
|
77
78
|
- lib/suitcase/helpers.rb
|
@@ -79,12 +80,15 @@ files:
|
|
79
80
|
- lib/suitcase/hotel/image.rb
|
80
81
|
- lib/suitcase/hotel/nightly_rate.rb
|
81
82
|
- lib/suitcase/hotel/payment_option.rb
|
83
|
+
- lib/suitcase/hotel/reservation.rb
|
82
84
|
- lib/suitcase/hotel/room.rb
|
83
85
|
- lib/suitcase/version.rb
|
84
86
|
- spec/api_key.rb
|
87
|
+
- spec/caching_spec.rb
|
85
88
|
- spec/helpers_spec.rb
|
86
89
|
- spec/hotels_spec.rb
|
87
90
|
- spec/images_spec.rb
|
91
|
+
- spec/payment_options_spec.rb
|
88
92
|
- spec/rooms_spec.rb
|
89
93
|
- spec/spec_helper.rb
|
90
94
|
- suitcase.gemspec
|
@@ -102,7 +106,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
102
106
|
version: '0'
|
103
107
|
segments:
|
104
108
|
- 0
|
105
|
-
hash:
|
109
|
+
hash: 548987978234078689
|
106
110
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
111
|
none: false
|
108
112
|
requirements:
|
@@ -111,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
115
|
version: '0'
|
112
116
|
segments:
|
113
117
|
- 0
|
114
|
-
hash:
|
118
|
+
hash: 548987978234078689
|
115
119
|
requirements: []
|
116
120
|
rubyforge_project: suitcase
|
117
121
|
rubygems_version: 1.8.13
|
@@ -119,11 +123,11 @@ signing_key:
|
|
119
123
|
specification_version: 3
|
120
124
|
summary: Locates available hotels, rental cars, and flights
|
121
125
|
test_files:
|
122
|
-
- features/hotels.feature
|
123
|
-
- features/step_definitions/hotels_steps.rb
|
124
126
|
- spec/api_key.rb
|
127
|
+
- spec/caching_spec.rb
|
125
128
|
- spec/helpers_spec.rb
|
126
129
|
- spec/hotels_spec.rb
|
127
130
|
- spec/images_spec.rb
|
131
|
+
- spec/payment_options_spec.rb
|
128
132
|
- spec/rooms_spec.rb
|
129
133
|
- spec/spec_helper.rb
|
data/features/hotels.feature
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
Feature: Hotels
|
2
|
-
As a developer
|
3
|
-
In order to use the EAN API in my application
|
4
|
-
I need to be able to manipulate hotel information
|
5
|
-
|
6
|
-
Scenario Outline: Listing available hotels
|
7
|
-
Given I have an API key
|
8
|
-
When I submit a request to find <number_of_results> hotels in <location>
|
9
|
-
Then I want to receive <number_of_results> hotels with their respective information
|
10
|
-
|
11
|
-
Examples:
|
12
|
-
|
13
|
-
| number_of_results | location |
|
14
|
-
| 10 | Boston, USA |
|
15
|
-
| 8 | Dublin, Ireland |
|
16
|
-
| 1 | London, UK |
|
17
|
-
|
18
|
-
Scenario Outline: Requesting more information about a given hotel
|
19
|
-
Given I have an API key
|
20
|
-
When I submit a request to find more information about a hotel with id <id>
|
21
|
-
Then I want to receive more information about that hotel
|
22
|
-
|
23
|
-
Examples:
|
24
|
-
|
25
|
-
| id |
|
26
|
-
| 252897 |
|
27
|
-
| 273655 |
|
28
|
-
| 174272 |
|
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'suitcase'
|
2
|
-
|
3
|
-
Given /^I have an API key$/ do
|
4
|
-
Suitcase::Hotel::API_KEY = "3kx2vhr7sjrgmsyddb2cg47j"
|
5
|
-
end
|
6
|
-
|
7
|
-
When /^I submit a request to find (\d+) hotels in (.+)$/ do |results, location|
|
8
|
-
@hotels = Suitcase::Hotel.find(:near => location, :results => results.to_i)
|
9
|
-
end
|
10
|
-
|
11
|
-
Then /^I want to receive (\d+) hotels with their respective information$/ do |results|
|
12
|
-
@hotels.count.should eq(results.to_i)
|
13
|
-
end
|
14
|
-
|
15
|
-
When /^I submit a request to find more information about a hotel with id (\d+)$/ do |id|
|
16
|
-
@hotel = Suitcase::Hotel.find_by_id(id)
|
17
|
-
end
|
18
|
-
|
19
|
-
Then /^I want to receive more information about that hotel$/ do
|
20
|
-
@hotel.should_not be_nil
|
21
|
-
end
|