suitcase 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/README.md +34 -0
- data/Rakefile +1 -0
- data/lib/suitcase/air/air.rb +86 -0
- data/lib/suitcase/airport_codes.rb +3 -0
- data/lib/suitcase/country_codes.rb +3 -0
- data/lib/suitcase/hotel/hotel.rb +49 -0
- data/lib/suitcase/version.rb +3 -0
- data/lib/suitcase.rb +7 -0
- data/spec/hotel_spec.rb +23 -0
- data/spec/spec_helper.rb +4 -0
- data/suitcase.gemspec +24 -0
- metadata +92 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
Suitcase
|
2
|
+
========
|
3
|
+
|
4
|
+
Suitcase is a Ruby library that utilizes the EAN (Expedia.com) API for locating available hotels, rental cars, and flights.
|
5
|
+
|
6
|
+
Installation
|
7
|
+
------------
|
8
|
+
|
9
|
+
Add the following line to your Gemfile:
|
10
|
+
|
11
|
+
`gem 'suitcase', :git => "http://github.com/thoughtfusion/suitcase.git"` then run `bundle install`. Or install the gem: `gem install suitcase`.
|
12
|
+
|
13
|
+
|
14
|
+
Usage
|
15
|
+
-----
|
16
|
+
|
17
|
+
First, include the module in your code:
|
18
|
+
|
19
|
+
include Suitcase
|
20
|
+
|
21
|
+
Find nearby hotels:
|
22
|
+
|
23
|
+
Hotel::API_KEY = "your_api_key_here"
|
24
|
+
Hotel.near('Boston, MA', 10) # Returns 10 closest hotels to Boston, MA
|
25
|
+
Hotel.near('Metropoliton Museum of Art') # Returns 50 closest hotels to the Met Museum in New York
|
26
|
+
|
27
|
+
Find available airline flights (not yet implemented):
|
28
|
+
|
29
|
+
Flight:API_KEY = "your_api_key_here"
|
30
|
+
Flight.available('June 23 2012', :from => "BOS", :to => "LHR") # Return all flights flying from Boston to London (Heathrow) on June 23, 2012
|
31
|
+
|
32
|
+
Contributing
|
33
|
+
------------
|
34
|
+
Please submit any useful pull requests through GitHub. If you find any bugs, please report them! Thanks.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'json'
|
3
|
+
require 'nokogiri'
|
4
|
+
require File.dirname(__FILE__) + '/../airport_codes'
|
5
|
+
|
6
|
+
module Suitcase
|
7
|
+
class Flight
|
8
|
+
attr_accessor :flights, :key, :origin, :destination, :departure, :arrival, :adults, :children, :seniors, :fare, :direct, :round_trip, :currency, :search_window, :results, :airline, :airline_code, :price, :segments, :outgoing
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
puts <<EOS
|
12
|
+
----------
|
13
|
+
FLIGHT:
|
14
|
+
airline: #{airline} (#{airline_code})
|
15
|
+
origin: #{origin}
|
16
|
+
destination: #{destination}
|
17
|
+
departure: #{departure}
|
18
|
+
arrival: #{arrival}
|
19
|
+
price: #{price} (#{currency})
|
20
|
+
key: #{key}
|
21
|
+
----------
|
22
|
+
EOS
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.available(data)
|
26
|
+
origin_city = data[:from]
|
27
|
+
destination_city = data[:to]
|
28
|
+
departure_date_time = data[:departs]
|
29
|
+
arrival_date_time = data[:arrives]
|
30
|
+
adult_passengers = data[:adults] ? data[:adults] : 0
|
31
|
+
child_passengers = data[:children] ? data[:children].inject("") { |result, element| result + "C" + (element < 10 ? "0" : "") + element.to_s + (data[:children].last == element ? "" : ",") } : "" # :children => [2, 9, 11] (ages of children) should yield "C02,C09,C11"
|
32
|
+
senior_passengers = data[:seniors] ? data[:seniors] : 0
|
33
|
+
fare_class = data[:fare] ? data[:fare] : "Y" # F: first class; Y: coach; B: business
|
34
|
+
direct_flight = data[:direct_only] ? data[:direct_only] : false
|
35
|
+
round_trip = data[:round_trip] ? data[:round_trip] : "O"
|
36
|
+
currency = data[:currency] ? data[:currency] : "USD"
|
37
|
+
search_window = data[:search_window] ? data[:search_window] : 2
|
38
|
+
number_of_results = data[:results] ? data[:results] : 50
|
39
|
+
xml_format = <<EOS
|
40
|
+
<AirSessionRequest method="getAirAvailability">
|
41
|
+
<AirAvailabilityQuery>
|
42
|
+
<originCityCode>#{origin_city}</originCityCode>
|
43
|
+
<destinationCityCode>#{destination_city}</destinationCityCode>
|
44
|
+
<departureDateTime>#{departure_date_time}</departureDateTime>
|
45
|
+
<returnDateTime>#{arrival_date_time}</returnDateTime>
|
46
|
+
<fareClass>#{fare_class}</fareClass>
|
47
|
+
<tripType>#{round_trip}</tripType>
|
48
|
+
<Passengers>
|
49
|
+
<adultPassengers>#{adult_passengers}</adultPassengers>
|
50
|
+
<seniorPassengers>#{senior_passengers}</seniorPassengers>
|
51
|
+
<childCodes>#{child_passengers}</childCodes>
|
52
|
+
</Passengers>
|
53
|
+
</AirAvailabilityQuery>
|
54
|
+
</AirSessionRequest>
|
55
|
+
EOS
|
56
|
+
uri = URI.escape("http://api.ean.com/ean-services/rs/air/200919/xmlinterface.jsp?cid=#{CID}&resType=air&intfc=ws&apiKey=#{API_KEY}&xml=#{xml_format}")
|
57
|
+
xml = Nokogiri::XML(open(uri))
|
58
|
+
segments = []
|
59
|
+
xml.xpath('//Segment').each do |segment|
|
60
|
+
f = Flight.new
|
61
|
+
f.key = segment.xpath("@key")
|
62
|
+
f.origin = segment.xpath("//originCity") + segment.xpath("//originStateProvince") + segment.xpath("//originCountry")
|
63
|
+
f.destination = segment.xpath("//destinationCity")
|
64
|
+
f.airline = segment.xpath("//airline")
|
65
|
+
f.airline_code = segment.xpath("//airlineCode")
|
66
|
+
f.departure = segment.xpath("//departureDateTime")
|
67
|
+
f.arrival = segment.xpath("//arrivalDateTime")
|
68
|
+
segments.push(f)
|
69
|
+
end
|
70
|
+
flights = []
|
71
|
+
xml.xpath("//AirAvailabilityReply").each do |aar|
|
72
|
+
f = Flight.new
|
73
|
+
f.segments = []
|
74
|
+
f.price = aar.xpath("//nativeTotalPrice")
|
75
|
+
f.currency = aar.xpath("//displayCurrencyCode")
|
76
|
+
aar.xpath("//FlightSegment").each do |subseg|
|
77
|
+
fn = segments.find { |x| x.key == subseg.xpath("//segmentKey") }
|
78
|
+
f.segments.push(fn)
|
79
|
+
f.segments.compact!
|
80
|
+
end
|
81
|
+
flights.push(f)
|
82
|
+
end
|
83
|
+
flights
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|