suitcase 1.2.12 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -2,4 +2,3 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
- spec/keys.rb
data/README.md CHANGED
@@ -6,30 +6,73 @@ Ruby library that utilizes the EAN (Expedia.com) API for locating available hote
6
6
  Installation
7
7
  ------------
8
8
 
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"`.
9
+ Suitcase is a Ruby gem, meaning it can be installed via a simple `gem install suitcase`. It can also be added to a project's `Gemfile` with the following line: `gem 'suitcase'` (or `gem 'suitcase', git: "git://github.com/thoughtfusion/suitcase.git", branch: "development"` for the latest updates).
10
10
 
11
11
  Usage
12
12
  -----
13
13
 
14
+ ### Hotels
15
+
14
16
  First, configure the library:
15
17
 
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)
18
+ ```ruby
19
+ Suitcase.configure do |config|
20
+ config.hotel_api_key = "..." # set the Hotel API key from developer.ean.com
21
+ config.hotel_cid = "..." # set the CID from developer.ean.com
22
+ config.cache = Hash.new # set the caching mechanism (see below)
23
+ end
24
+ ```
19
25
 
20
- Find nearby hotels:
26
+ Full example:
27
+ ```ruby
28
+ # Find Hotels in Boston
29
+ hotels = Suitcase::Hotel.find(location: "Boston, MA")
30
+ # Pick a specific hotel
31
+ hotel = hotels[1]
32
+ # Get the rooms for a specific date
33
+ rooms = hotel.rooms(arrival: "7/1/2013", departure: "7/8/2013", rooms: [{ adults: 1, children_ages: [2, 3] }, { adults: 1, children_ages: [4] }])
34
+ # Find a payment option that is compatible with USD
35
+ payment_option = Suitcase::PaymentOption.find(currency_code: "USD")
36
+ # Pick a specific room
37
+ room = rooms.first
38
+ # Set the bed type on each of the rooms to be ordered
39
+ room.rooms.each { |r| r[:bed_type] = room.bed_types.first }
40
+ # Reserve the room, with the reservation_hash described on 'User flow'
41
+ room.reserve!(reservation_hash)
42
+ ```
21
43
 
22
- hotels = Suitcase::Hotel.find(:location => 'Boston, MA', :results => 10) # Returns 10 closest hotels to Boston, MA
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
24
- room.reserve!(info) # See wiki page "User flow" for options
44
+ #### Caching requests
25
45
 
26
- ### Caching
46
+ 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. Check the `examples/hash_adapter.rb` for a trivial example of the required methods. A Redis adapter should be coming soon.
27
47
 
28
- #### Requests
29
48
 
30
- 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. Check the `examples/hash_adapter.rb` for a trivial example of the required methods. A Redis adapter should be coming soon.
49
+ ### Car rentals
50
+
51
+ Add the required configuration options:
52
+
53
+ ```ruby
54
+ # Or add to your existing configure block
55
+ Suitcase.configure do |config|
56
+ config.hotwire_api_key = "..." # set the Hotwire API key
57
+ config.hotwire_linkshare_id = "..." # optionally set the Hotwire linkshare ID
58
+ end
59
+ ```
31
60
 
61
+ Example usage:
62
+
63
+ ```ruby
64
+ # Find all rental cars from the specified dates/times at LAX
65
+ rentals = Suitcase::CarRental.find(destination: "LAX", start_date: "7/14/2012", end_date: "7/21/2012", pickup_time: "6:30", dropoff_time: "11:30")
66
+ # => [#<Suitcase::CarRental ...>, ...]
67
+ ```
32
68
 
33
69
  Contributing
34
70
  ------------
71
+
72
+ ### Running the specs
73
+
74
+ To set up for the specs, you need to edit the file `spec/keys.rb` with the proper information. Currently, testing reservations is unsupported. You can run the specs with the default rake task by running `rake` from the command line.
75
+
76
+ ### Pull requests/issues
77
+
35
78
  Please submit any useful pull requests through GitHub. If you find any bugs, please report them with the issue tracker! Thanks.
@@ -0,0 +1,29 @@
1
+ class RedisAdapter
2
+ def initialize
3
+ uri = URI.parse(ENV["REDIS_URI"])
4
+ @redis = Redis.new(:host => uri.host,
5
+ :port => uri.port,
6
+ :password => uri.password)
7
+ end
8
+
9
+ def [](key)
10
+ stored = @redis.hgetall("ean_cache:#{key}")
11
+ stored.inject({}) {|mem, (k, v)|
12
+ mem[JSON.parse(k)] = JSON.parse(v)
13
+ mem
14
+ }
15
+ end
16
+
17
+ def []=(key, value)
18
+ value.each_pair do |params, response|
19
+ @redis.hset("ean_cache:#{key}", params.to_json, response.to_json)
20
+ end
21
+ end
22
+
23
+ def keys
24
+ @redis.keys("ean_cache:*").collect {|key|
25
+ key.match(/ean_cache:(.*)/)[1] rescue nil
26
+ }.compact!
27
+ end
28
+ end
29
+
@@ -11,12 +11,16 @@ module Suitcase
11
11
  params.delete(param)
12
12
  end
13
13
  params.delete("currencyCode") unless action == :paymentInfo
14
+
15
+ string_params = keys_to_strings(params)
16
+
14
17
  @store[action] ||= {}
15
- @store[action][params] = response
18
+ @store[action] = @store[action].merge(string_params => response)
16
19
  end
17
20
 
18
21
  def get_query(action, params)
19
- @store[action] ? @store[action][params] : nil
22
+ string_params = keys_to_strings(params)
23
+ @store[action] ? @store[action][string_params] : nil
20
24
  end
21
25
 
22
26
  def keys
@@ -24,11 +28,22 @@ module Suitcase
24
28
  end
25
29
 
26
30
  def cached?(action, params)
27
- @store[action] && @store[action][params]
31
+ string_params = keys_to_strings(params)
32
+ @store[action] && @store[action][string_params]
28
33
  end
29
34
 
30
35
  def undefine_query(action, params)
31
- @store[action].delete(params) if @store[action]
36
+ string_params = keys_to_strings(params)
37
+ @store[action].delete(string_params) if @store[action]
38
+ end
39
+
40
+ private
41
+
42
+ def keys_to_strings(hash)
43
+ hash.inject({}) {|memo, (k, v)|
44
+ memo[k.to_s] = v
45
+ memo
46
+ }
32
47
  end
33
48
  end
34
49
  end
@@ -0,0 +1,51 @@
1
+ module Suitcase
2
+ class CarRental
3
+ attr_accessor :seating, :type_name, :type_code, :possible_features, :possible_models
4
+
5
+ def initialize(data)
6
+ @seating = data["CarTypeSeating"]
7
+ @type_name = data["CarTypeName"]
8
+ @type_code = data["CarTypeCode"]
9
+ @possible_features = data["PossibleFeatures"].split(", ")
10
+ @possible_models = data["PossibleModels"].split(", ")
11
+ end
12
+
13
+ class << self
14
+ def find(info)
15
+ parsed = parse_json(build_url(info))
16
+ parse_errors(parsed)
17
+ parsed["MetaData"]["CarMetaData"]["CarTypes"].map { |data| CarRental.new(data) }
18
+ end
19
+
20
+ def build_url(info)
21
+ base_url = "http://api.hotwire.com/v1/search/car"
22
+ info["apikey"] = Configuration.hotwire_api_key
23
+ info["format"] = "JSON"
24
+ if Configuration.use_hotwire_linkshare_id?
25
+ info["linkshareid"] = Configuration.hotwire_linkshare_id
26
+ end
27
+ info["dest"] = info.delete(:destination)
28
+ info["startdate"] = info.delete(:start_date)
29
+ info["enddate"] = info.delete(:end_date)
30
+ info["pickuptime"] = info.delete(:pickup_time)
31
+ info["dropofftime"] = info.delete(:dropoff_time)
32
+ base_url += "?" + parameterize(info)
33
+ URI.parse(URI.escape(base_url))
34
+ end
35
+
36
+ def parameterize(info)
37
+ info.map { |key, value| "#{key}=#{value}" }.join("&")
38
+ end
39
+
40
+ def parse_json(uri)
41
+ response = Net::HTTP.get_response(uri)
42
+ raise "Data not valid." if response.code != "200"
43
+ JSON.parse(response.body)
44
+ end
45
+
46
+ def parse_errors(parsed)
47
+ parsed["Errors"].each { |e| raise e } if parsed["Errors"] && !parsed["Errors"].empty?
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,4 +1,8 @@
1
1
  module Suitcase
2
+ def self.configure(&block)
3
+ block.call(Configuration)
4
+ end
5
+
2
6
  class Configuration
3
7
  def self.cache=(store)
4
8
  @@cache = Suitcase::Cache.new(store)
@@ -27,5 +31,41 @@ module Suitcase
27
31
  def self.hotel_cid
28
32
  @@hotel_cid if defined? @@hotel_cid
29
33
  end
34
+
35
+ def self.hotel_shared_secret=(secret)
36
+ @@hotel_shared_secret = secret
37
+ end
38
+
39
+ def self.hotel_shared_secret
40
+ @@hotel_shared_secret if defined? @@hotel_shared_secret
41
+ end
42
+
43
+ def self.use_signature_auth=(choice)
44
+ @@use_signature_authentication = choice
45
+ end
46
+
47
+ def self.use_signature_auth?
48
+ defined? @@use_signature_auth
49
+ end
50
+
51
+ def self.hotwire_api_key=(api_key)
52
+ @@hotwire_api_key = api_key
53
+ end
54
+
55
+ def self.hotwire_api_key
56
+ @@hotwire_api_key if defined? @@hotwire_api_key
57
+ end
58
+
59
+ def self.hotwire_linkshare_id=(id)
60
+ @@hotwire_linkshare_id = id
61
+ end
62
+
63
+ def self.hotwire_linkshare_id
64
+ @@hotwire_linkshare_id if use_hotwire_lnikshare_id?
65
+ end
66
+
67
+ def self.use_hotwire_linkshare_id?
68
+ defined? @@hotwire_linkshare_id
69
+ end
30
70
  end
31
71
  end
@@ -0,0 +1,131 @@
1
+ module Suitcase
2
+ # Internal: Various methods for doing things that many files need to in the
3
+ # library.
4
+ #
5
+ # Examples
6
+ #
7
+ # parameterize(something: "else", another: "thing")
8
+ # # => "something=else&another=thing"
9
+ module Helpers
10
+ # Internal: Defaults for the builder options to Helpers#url.
11
+ URL_DEFAULTS = {
12
+ include_key: true,
13
+ include_cid: true,
14
+ secure: false,
15
+ as_form: false,
16
+ session: Session.new
17
+ }
18
+
19
+ # Internal: Parameterize a Hash.
20
+ #
21
+ # hash - The Hash to be parameterized.
22
+ #
23
+ # Examples
24
+ #
25
+ # parameterize(something: "else", another: "thing")
26
+ # # => "something=else&another=thing"
27
+ #
28
+ # Returns a parameterized String.
29
+ def parameterize(hash)
30
+ hash.map { |key, value| "#{key}=#{value}" }.join "&"
31
+ end
32
+
33
+ # Internal: Build an API URL.
34
+ #
35
+ # builder - A Hash with the following required keys:
36
+ # :method - The API method to be put in the URL.
37
+ # :params - The params to be put in the URL.
38
+ # And the following optional ones:
39
+ # :include_key - Whether to include the API key or not.
40
+ # :include_cid - Whether to include the API cid or not.
41
+ # :secure - Whether or not for the request to be sent over
42
+ # HTTPS.
43
+ # :as_form - Whether or not to include the parameters in the
44
+ # URL.
45
+ # :session - The Session associated with the request.
46
+ #
47
+ # Examples
48
+ #
49
+ # url(secure: true, as_form: true, method: "myMethod", params: {})
50
+ # # => #<URI::HTTPS URL:https://book.api.ean.com/.../rs/hotel/v3/myMethod>
51
+ def url(builder)
52
+ builder = URL_DEFAULTS.merge(builder)
53
+ builder[:session] ||= URL_DEFAULTS[:session]
54
+ method, params = builder[:method], builder[:params]
55
+ params["apiKey"] = Configuration.hotel_api_key if builder[:include_key]
56
+ params["cid"] = (Configuration.hotel_cid ||= 55505) if builder[:include_cid]
57
+ params["sig"] = generate_signature if Configuration.use_signature_auth?
58
+
59
+ url = main_url(builder[:secure]) + method.to_s + (builder[:as_form] ? "" : "?")
60
+
61
+ params.merge!(build_session_params(builder[:session]))
62
+ url += parameterize(params) unless builder[:as_form]
63
+ URI.parse(URI.escape(url))
64
+ end
65
+
66
+ # Internal: Get the root URL for the Hotels API.
67
+ #
68
+ # secure - Whether or not the URL should be HTTPS or not.
69
+ #
70
+ # Returns the URL.
71
+ def main_url(secure)
72
+ url = "http#{secure ? "s" : ""}://#{secure ? "book." : ""}"
73
+ url += "api.ean.com/ean-services/rs/hotel/v3/"
74
+ url
75
+ end
76
+
77
+ # Internal: Parse the JSON response at the given URL.
78
+ #
79
+ # uri - The URI to parse the JSON from.
80
+ #
81
+ # Returns the parsed JSON.
82
+ def parse_response(uri)
83
+ JSON.parse(Net::HTTP.get_response(uri).body)
84
+ end
85
+
86
+ # Internal: Get the base URL based on a Hash of info.
87
+ #
88
+ # info - A Hash with only one required key:
89
+ # :booking - Whether or not it is a booking request.
90
+ #
91
+ # Returns the base URL.
92
+ def base_url(info)
93
+ main_url(info[:booking])
94
+ end
95
+
96
+ # Internal: Build a Hash of params from a Session.
97
+ #
98
+ # session - The Session to generate params from.
99
+ #
100
+ # Returns the Hash of params.
101
+ def build_session_params(session)
102
+ session_info = {}
103
+ session_info["customerSessionId"] = session.id if session.id
104
+ session_info["customerIpAddress"] = session.ip_address if session.ip_address
105
+ session_info["locale"] = session.locale if session.locale
106
+ session_info["currencyCode"] = session.currency_code if session.currency_code
107
+ session_info["customerUserAgent"] = session.user_agent if session.user_agent
108
+ session_info
109
+ end
110
+
111
+ # Internal: Update the Session's ID with the parsed JSON.
112
+ #
113
+ # parsed - The parsed JSON to fetch the ID from.
114
+ # session - The Session to update.
115
+ #
116
+ # Returns nothing.
117
+ def update_session(parsed, session)
118
+ session ||= Suitcase::Session.new
119
+ session.id = parsed[parsed.keys.first]["customerSessionId"] if parsed[parsed.keys.first]
120
+ end
121
+
122
+ # Internal: Generate a digital signature to authenticate with.
123
+ #
124
+ # Returns the generated signature.
125
+ def generate_signature
126
+ Digest::MD5.hexdigest(Configuration.hotel_api_key +
127
+ Configuration.hotel_shared_secret +
128
+ Time.now.to_i.to_s)
129
+ end
130
+ end
131
+ end
@@ -145,6 +145,7 @@ module Suitcase
145
145
  parsed_info[:location_description] = summary["locationDescription"]
146
146
  parsed_info[:number_of_rooms] = parsed["HotelInformationResponse"]["HotelDetails"]["numberOfRooms"] if parsed["HotelInformationResponse"]
147
147
  parsed_info[:number_of_floors] = parsed["HotelInformationResponse"]["HotelDetails"]["numberOfFloors"] if parsed["HotelInformationResponse"]
148
+ parsed_info[:short_description] = summary["shortDescription"]
148
149
  parsed_info
149
150
  end
150
151
 
@@ -1,3 +1,3 @@
1
1
  module Suitcase
2
- VERSION = "1.2.12"
2
+ VERSION = "1.3.0"
3
3
  end
data/lib/suitcase.rb CHANGED
@@ -1,15 +1,19 @@
1
1
  require 'patron'
2
2
  require 'json'
3
3
  require 'net/http'
4
+ require 'digest/md5'
4
5
  require 'date/format'
5
6
  require 'time'
6
- require 'suitcase/session'
7
- require 'suitcase/core_ext/string'
7
+
8
8
  require 'suitcase/version'
9
+
10
+ require 'suitcase/core_ext/string'
11
+
12
+ require 'suitcase/session'
9
13
  require 'suitcase/configuration'
10
- # require 'suitcase/session_cache'
11
14
  require 'suitcase/cache'
12
- require 'suitcase/helpers'
15
+
16
+ require 'suitcase/hotel/helpers'
13
17
  require 'suitcase/hotel/location'
14
18
  require 'suitcase/hotel/amenity'
15
19
  require 'suitcase/hotel/reservation'
@@ -18,3 +22,5 @@ require 'suitcase/hotel/room'
18
22
  require 'suitcase/hotel/payment_option'
19
23
  require 'suitcase/hotel/hotel'
20
24
  require 'suitcase/hotel/image'
25
+
26
+ require 'suitcase/car_rental'
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Suitcase::CarRental do
4
+ before :each do
5
+ @rentals = Suitcase::CarRental.find(destination: "Seattle", start_date: "07/04/2012", end_date: "07/11/2012", pickup_time: "07:30", dropoff_time: "07:30")
6
+ end
7
+
8
+ describe '.find' do
9
+ it 'returns an Array of CarRentals' do
10
+ @rentals.class.should eq Array
11
+ @rentals.first.class.should eq Suitcase::CarRental
12
+ end
13
+ end
14
+
15
+ subject { @rentals.first }
16
+
17
+ [:seating, :type_name, :type_code, :possible_features, :possible_models].each do |method|
18
+ it { should respond_to method }
19
+ end
20
+ end
data/spec/helpers_spec.rb CHANGED
@@ -5,10 +5,22 @@ describe Suitcase::Helpers do
5
5
  class Dummy; extend Suitcase::Helpers; end
6
6
  end
7
7
 
8
- it "#url should return a URI with the correct base URL" do
9
- returned = Dummy.url(:method => "action", :params => {})
10
- returned.should be_a(URI)
11
- returned.host.should match(/api.ean.com/)
8
+ describe "#url" do
9
+ it "should return a URI with the correct base URL" do
10
+ returned = Dummy.url(:method => "action", :params => {})
11
+ returned.should be_a(URI)
12
+ returned.host.should match(/api.ean.com/)
13
+ end
14
+
15
+ context "when using digital signature authentication" do
16
+ it "should add a 'sig' parameter" do
17
+ Suitcase::Configuration.stub(:use_signature_auth?) { true }
18
+ Dummy.stub(:generate_signature) { "test" }
19
+
20
+ returned = Dummy.url(:method => "action", :params => {})
21
+ returned.query.should match(/sig=test/)
22
+ end
23
+ end
12
24
  end
13
25
 
14
26
  it "#parse_response should raise an exception when passed an invalid URI" do
@@ -16,4 +28,13 @@ describe Suitcase::Helpers do
16
28
  Dummy.parse_response(URI.parse "http://google.com")
17
29
  end.should raise_error
18
30
  end
31
+
32
+ it "#generate_signature should return the encrypted api key, shared secret, and timestamp" do
33
+ Suitcase::Configuration.stub(:hotel_api_key) { "abc" }
34
+ Suitcase::Configuration.stub(:hotel_shared_secret) { "123" }
35
+ Time.stub(:now) { "10" }
36
+
37
+ returned = Dummy.generate_signature
38
+ returned.should == Digest::MD5.hexdigest("abc12310")
39
+ end
19
40
  end
data/spec/keys.rb ADDED
@@ -0,0 +1,36 @@
1
+ # Suitcase::Configuration.hotel_api_key = "your_api_key_here"
2
+ # Suitcase::Configuration.hotel_cid = "your_cid_here"
3
+ # Suitcase::Configuration.hotel_shared_secret = "your_shared_secret_here"
4
+ # Suitcase::Configuration.use_signature_auth = true
5
+
6
+ # Or configure with a block:
7
+
8
+ Suitcase.configure do |config|
9
+ config.hotel_api_key = "your_api_key_here"
10
+ config.hotel_cid = "your_cid_here"
11
+ # config.hotel_shared_secret = "none"
12
+ # config.use_signature_auth = false
13
+ end
14
+
15
+ module Keys
16
+ SUITCASE_PAYMENT_OPTION = Suitcase::PaymentOption.find(currency_code: "USD")[0]
17
+ CREDIT_CARD_NUMBER_TESTING = "1234123412341234"
18
+ CREDIT_CARD_CVV_TESTING = "123"
19
+ CREDIT_CARD_EXPIRATION_DATE_TESTING = "3/14"
20
+
21
+ VALID_RESERVATION_INFO = {
22
+ email: "testemail@gmail.com",
23
+ first_name: "Test",
24
+ last_name: "User",
25
+ home_phone: "1231231234",
26
+ payment_option: SUITCASE_PAYMENT_OPTION,
27
+ credit_card_number: CREDIT_CARD_NUMBER_TESTING,
28
+ credit_card_verification_code: "123",
29
+ credit_card_expiration_date: CREDIT_CARD_EXPIRATION_DATE_TESTING,
30
+ address1: "1 Some Place",
31
+ city: "Boston",
32
+ province: "MA",
33
+ country: "US",
34
+ postal_code: "01234",
35
+ }
36
+ 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.2.12
4
+ version: 1.3.0
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: 2012-01-23 00:00:00.000000000 Z
12
+ date: 2012-04-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &10689360 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *10689360
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: rake
27
- requirement: &10688280 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *10688280
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: factory_girl
38
- requirement: &10703800 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *10703800
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: pry
49
- requirement: &10702920 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,10 +69,15 @@ dependencies:
54
69
  version: '0'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *10702920
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: json
60
- requirement: &10702140 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ! '>='
@@ -65,10 +85,15 @@ dependencies:
65
85
  version: '0'
66
86
  type: :runtime
67
87
  prerelease: false
68
- version_requirements: *10702140
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
69
94
  - !ruby/object:Gem::Dependency
70
95
  name: patron
71
- requirement: &10701540 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
72
97
  none: false
73
98
  requirements:
74
99
  - - ! '>='
@@ -76,7 +101,12 @@ dependencies:
76
101
  version: '0'
77
102
  type: :runtime
78
103
  prerelease: false
79
- version_requirements: *10701540
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
80
110
  description: Ruby library that utilizes the EAN (Expedia.com) API for locating available
81
111
  hotels (and maybe rental cars and flights someday, too).
82
112
  email:
@@ -92,14 +122,16 @@ files:
92
122
  - README.md
93
123
  - Rakefile
94
124
  - examples/hash_adapter.rb
125
+ - examples/redis_adapter.rb
95
126
  - lib/suitcase.rb
96
127
  - lib/suitcase/airport_codes.rb
97
128
  - lib/suitcase/cache.rb
129
+ - lib/suitcase/car_rental.rb
98
130
  - lib/suitcase/configuration.rb
99
131
  - lib/suitcase/core_ext/string.rb
100
132
  - lib/suitcase/country_codes.rb
101
- - lib/suitcase/helpers.rb
102
133
  - lib/suitcase/hotel/amenity.rb
134
+ - lib/suitcase/hotel/helpers.rb
103
135
  - lib/suitcase/hotel/hotel.rb
104
136
  - lib/suitcase/hotel/image.rb
105
137
  - lib/suitcase/hotel/location.rb
@@ -110,10 +142,12 @@ files:
110
142
  - lib/suitcase/session.rb
111
143
  - lib/suitcase/version.rb
112
144
  - spec/caching_spec.rb
145
+ - spec/car_rental_spec.rb
113
146
  - spec/helpers_spec.rb
114
147
  - spec/hotel_location_spec.rb
115
148
  - spec/hotels_spec.rb
116
149
  - spec/images_spec.rb
150
+ - spec/keys.rb
117
151
  - spec/payment_options_spec.rb
118
152
  - spec/reservation_spec.rb
119
153
  - spec/rooms_spec.rb
@@ -132,30 +166,26 @@ required_ruby_version: !ruby/object:Gem::Requirement
132
166
  - - ! '>='
133
167
  - !ruby/object:Gem::Version
134
168
  version: '0'
135
- segments:
136
- - 0
137
- hash: 1832860835282660065
138
169
  required_rubygems_version: !ruby/object:Gem::Requirement
139
170
  none: false
140
171
  requirements:
141
172
  - - ! '>='
142
173
  - !ruby/object:Gem::Version
143
174
  version: '0'
144
- segments:
145
- - 0
146
- hash: 1832860835282660065
147
175
  requirements: []
148
176
  rubyforge_project: suitcase
149
- rubygems_version: 1.8.11
177
+ rubygems_version: 1.8.21
150
178
  signing_key:
151
179
  specification_version: 3
152
180
  summary: Locates available hotels with the Expedia API
153
181
  test_files:
154
182
  - spec/caching_spec.rb
183
+ - spec/car_rental_spec.rb
155
184
  - spec/helpers_spec.rb
156
185
  - spec/hotel_location_spec.rb
157
186
  - spec/hotels_spec.rb
158
187
  - spec/images_spec.rb
188
+ - spec/keys.rb
159
189
  - spec/payment_options_spec.rb
160
190
  - spec/reservation_spec.rb
161
191
  - spec/rooms_spec.rb
@@ -1,44 +0,0 @@
1
- module Suitcase
2
- module Helpers
3
- def url(builder)
4
- builder[:include_key] ||= true
5
- builder[:include_cid] ||= true
6
- builder[:secure] ||= false
7
- builder[:as_form] ||= false
8
- builder[:session] ||= Suitcase::Session.new
9
- method, params, include_key, include_cid = builder[:method], builder[:params], builder[:include_key], builder[:include_cid]
10
- params["apiKey"] = Configuration.hotel_api_key if include_key
11
- params["cid"] = (Configuration.hotel_cid ||= 55505) if include_cid
12
- url = main_url(builder[:secure]) + method.to_s + (builder[:as_form] ? "" : "?")
13
- session_info = {}
14
- session_info["customerSessionId"] = builder[:session].id if builder[:session].id
15
- session_info["customerIpAddress"] = builder[:session].ip_address if builder[:session].ip_address
16
- session_info["locale"] = builder[:session].locale if builder[:session].locale
17
- session_info["currencyCode"] = builder[:session].currency_code if builder[:session].currency_code
18
- session_info["customerUserAgent"] = builder[:session].user_agent if builder[:session].user_agent
19
- url += params.merge(session_info).map { |key, value| "#{key}=#{value}"}.join("&") unless builder[:as_form]
20
- URI.parse(URI.escape(url))
21
- end
22
-
23
- def main_url(secure)
24
- "http#{secure ? "s" : ""}://#{secure ? "book." : ""}api.ean.com/ean-services/rs/hotel/v3/"
25
- end
26
-
27
- def parse_response(uri)
28
- JSON.parse(Net::HTTP.get_response(uri).body)
29
- end
30
-
31
- def base_url(info)
32
- if info[:booking]
33
- URI.parse main_url(true)
34
- else
35
- URI.parse main_url(false)
36
- end
37
- end
38
-
39
- def update_session(parsed, session)
40
- session ||= Suitcase::Session.new
41
- session.id = parsed[parsed.keys.first]["customerSessionId"] if parsed[parsed.keys.first]
42
- end
43
- end
44
- end