suitcase 1.2.12 → 1.3.0

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/.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