hotel_beds 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.tm_properties +5 -0
- data/INTERNALS.md +9 -0
- data/README.md +20 -2
- data/lib/hotel_beds/hotel_search/envelope.rb +16 -14
- data/lib/hotel_beds/hotel_search/operation.rb +5 -5
- data/lib/hotel_beds/hotel_search/request.rb +6 -5
- data/lib/hotel_beds/hotel_search/response.rb +31 -26
- data/lib/hotel_beds/hotel_search/room_grouper.rb +64 -0
- data/lib/hotel_beds/model.rb +1 -0
- data/lib/hotel_beds/model/available_room.rb +13 -3
- data/lib/hotel_beds/model/hotel.rb +3 -3
- data/lib/hotel_beds/model/search_result.rb +19 -0
- data/lib/hotel_beds/version.rb +1 -1
- data/spec/features/grouped_hotel_search_spec.rb +67 -0
- data/spec/features/hotel_search_spec.rb +11 -6
- data/spec/lib/hotel_beds/hotel_search/room_grouper_spec.rb +45 -0
- metadata +10 -3
- data/lib/hotel_beds/model/hotel_room.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4e1d67927848975b80e7a3dc3cd80654105e485
|
4
|
+
data.tar.gz: 65aadd0fb3f316987e34d5aa83dbe4c3d50319a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a795daa686af484ce5bede7955a7133dddeece24b065f4da8c0d372c03671c9e3f3d311ed52b872bccda910524b5d4a8295d9320fcb5e14619ea2d6c45c5a6c
|
7
|
+
data.tar.gz: 5ba1daeadd74a320a985378997bd8f0cc9f670fd5f78051404dc0adf4fee4b8a29af12293d6e3ce66af91f6e9c56a68a21f66850fdd98f7d72e9354630d503fa
|
data/.tm_properties
ADDED
data/INTERNALS.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Grouping results
|
2
|
+
|
3
|
+
The process we use to group results is as follows:
|
4
|
+
|
5
|
+
1) Group the available rooms (AR) by occupants (OK)
|
6
|
+
2) Expand the rooms (AR) in the array to illustrate the availability of each room (limit to a max of 5, as we don't support searches of more than 5 rooms)
|
7
|
+
3) Group the count of each requested room (RC) by occupants (OK)
|
8
|
+
4) For each group, determine all combinations of the available rooms (AR) for the given count (RC), this gives us the search results per room group (RSRG)
|
9
|
+
5) Find all combinations of the search results per room group, giving us unique search results (SR)
|
data/README.md
CHANGED
@@ -18,7 +18,7 @@ Manually, via command line:
|
|
18
18
|
|
19
19
|
# create the connection to HotelBeds
|
20
20
|
client = HotelBeds::Client.new(endpoint: :test, username: "user", password: "pass")
|
21
|
-
|
21
|
+
|
22
22
|
# perform the search
|
23
23
|
search = client.perform_hotel_search({
|
24
24
|
check_in_date: Date.today,
|
@@ -26,7 +26,7 @@ Manually, via command line:
|
|
26
26
|
rooms: [{ adult_count: 2 }],
|
27
27
|
destination: "SYD"
|
28
28
|
})
|
29
|
-
|
29
|
+
|
30
30
|
# inspect the response
|
31
31
|
puts search.response.hotels
|
32
32
|
# => [<HotelBeds::Model::Hotel>, <HotelBeds::Model::Hotel>]
|
@@ -35,6 +35,24 @@ Manually, via command line:
|
|
35
35
|
puts search.response.current_page
|
36
36
|
# => 1
|
37
37
|
|
38
|
+
### Options
|
39
|
+
|
40
|
+
The HotelBeds API will return individual rooms, rather than being grouped by what you searched for (e.g. 2 rooms, 1 with 2 adults, 1 with 1 adult and 1 child). To fix this issue, you can enable result grouping by adding `group_results: true` to the `perform_hotel_search` call.
|
41
|
+
|
42
|
+
Example:
|
43
|
+
|
44
|
+
# perform the search
|
45
|
+
search = client.perform_hotel_search({
|
46
|
+
check_in_date: Date.today,
|
47
|
+
check_out_date: Date.today + 1,
|
48
|
+
rooms: [
|
49
|
+
{ adult_count: 2 },
|
50
|
+
{ adult_count: 1, child_count: 1, child_ages: [7] }
|
51
|
+
],
|
52
|
+
destination: "SYD",
|
53
|
+
group_results: true
|
54
|
+
})
|
55
|
+
|
38
56
|
## Contributing
|
39
57
|
|
40
58
|
1. [Fork it](https://github.com/platformq/hotel_beds/fork)
|
@@ -12,7 +12,7 @@ module HotelBeds
|
|
12
12
|
OccupancyList: occupancy_list
|
13
13
|
}.merge(Hash(destination)).merge(Hash(hotels)).merge(Hash(extra_params))
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
private
|
17
17
|
def extra_params
|
18
18
|
{ ExtraParamList: {
|
@@ -27,7 +27,7 @@ module HotelBeds
|
|
27
27
|
}]
|
28
28
|
} }
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def pagination_data
|
32
32
|
{ :@pageNumber => Integer(page_number) }
|
33
33
|
end
|
@@ -52,7 +52,7 @@ module HotelBeds
|
|
52
52
|
} }
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
def hotels
|
57
57
|
if Array(__getobj__.hotels).any?
|
58
58
|
{ HotelCodeList: {
|
@@ -61,20 +61,22 @@ module HotelBeds
|
|
61
61
|
} }
|
62
62
|
end
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
def occupancy_list
|
66
|
-
Array(rooms).map
|
67
|
-
|
68
|
-
|
69
|
-
|
66
|
+
{ HotelOccupancy: Array(rooms).map { |room|
|
67
|
+
guest_list = if room.child_count > 0
|
68
|
+
{ GuestList: { Customer: Array(room.child_ages).map { |age|
|
69
|
+
{ :@type => "CH", :Age => Integer(age) }
|
70
|
+
} } }
|
71
|
+
end
|
72
|
+
{
|
73
|
+
RoomCount: 1,
|
74
|
+
Occupancy: (guest_list || Hash.new).merge({
|
70
75
|
AdultCount: Integer(room.adult_count),
|
71
76
|
ChildCount: Integer(room.child_count)
|
72
|
-
}
|
73
|
-
|
74
|
-
|
75
|
-
}
|
76
|
-
} }
|
77
|
-
end
|
77
|
+
})
|
78
|
+
}
|
79
|
+
} }
|
78
80
|
end
|
79
81
|
end
|
80
82
|
end
|
@@ -7,14 +7,14 @@ module HotelBeds
|
|
7
7
|
class Operation
|
8
8
|
attr_accessor :request, :response, :errors
|
9
9
|
private :request=, :response=, :errors=
|
10
|
-
|
10
|
+
|
11
11
|
def initialize(*args)
|
12
12
|
self.request = Request.new(*args)
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def perform(connection:)
|
16
16
|
if request.valid?
|
17
|
-
self.response = Response.new(retrieve(connection))
|
17
|
+
self.response = Response.new(request, retrieve(connection))
|
18
18
|
self.errors = response.errors
|
19
19
|
else
|
20
20
|
self.errors = request.errors
|
@@ -22,11 +22,11 @@ module HotelBeds
|
|
22
22
|
freeze
|
23
23
|
self
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
private
|
27
27
|
def retrieve(connection)
|
28
28
|
connection.call({
|
29
|
-
method: :getHotelValuedAvail,
|
29
|
+
method: :getHotelValuedAvail,
|
30
30
|
namespace: :HotelValuedAvailRQ,
|
31
31
|
data: Envelope.new(request).attributes
|
32
32
|
})
|
@@ -3,14 +3,14 @@ require "hotel_beds/model"
|
|
3
3
|
module HotelBeds
|
4
4
|
module HotelSearch
|
5
5
|
class Request
|
6
|
-
class Room
|
6
|
+
class Room
|
7
7
|
include HotelBeds::Model
|
8
|
-
|
8
|
+
|
9
9
|
# attributes
|
10
10
|
attribute :adult_count, Integer, default: 0
|
11
11
|
attribute :child_count, Integer, default: 0
|
12
12
|
attribute :child_ages, Array[Integer], default: Array.new
|
13
|
-
|
13
|
+
|
14
14
|
# validation
|
15
15
|
validates :adult_count, :child_count, numericality: {
|
16
16
|
greater_than_or_equal_to: 0,
|
@@ -23,7 +23,7 @@ module HotelBeds
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
include HotelBeds::Model
|
28
28
|
|
29
29
|
# attributes
|
@@ -34,7 +34,8 @@ module HotelBeds
|
|
34
34
|
attribute :destination, String
|
35
35
|
attribute :hotels, Array[Integer]
|
36
36
|
attribute :rooms, Array[Room]
|
37
|
-
|
37
|
+
attribute :group_results, Virtus::Attribute::Boolean, default: false
|
38
|
+
|
38
39
|
# validation
|
39
40
|
validates :language, :destination, length: { is: 3 }
|
40
41
|
validates :check_in_date, :check_out_date, presence: true
|
@@ -1,13 +1,16 @@
|
|
1
1
|
require "active_model/errors"
|
2
2
|
require "hotel_beds/model/hotel"
|
3
|
+
require "hotel_beds/model/available_room"
|
4
|
+
require_relative "room_grouper"
|
3
5
|
|
4
6
|
module HotelBeds
|
5
7
|
module HotelSearch
|
6
8
|
class Response
|
7
|
-
attr_accessor :headers, :body, :errors
|
8
|
-
private :headers=, :body=, :errors=
|
9
|
-
|
10
|
-
def initialize(response)
|
9
|
+
attr_accessor :request, :headers, :body, :errors
|
10
|
+
private :request=, :headers=, :body=, :errors=
|
11
|
+
|
12
|
+
def initialize(request, response)
|
13
|
+
self.request = request
|
11
14
|
self.headers = response.header
|
12
15
|
self.body = Nokogiri::XML(response.body.fetch(:get_hotel_valued_avail))
|
13
16
|
self.errors = ActiveModel::Errors.new(self).tap do |errors|
|
@@ -28,11 +31,11 @@ module HotelBeds
|
|
28
31
|
end
|
29
32
|
freeze
|
30
33
|
end
|
31
|
-
|
34
|
+
|
32
35
|
def inspect
|
33
36
|
"<#{self.class.name} errors=#{errors.inspect} headers=#{headers.inspect} body=#{body.to_s}>"
|
34
37
|
end
|
35
|
-
|
38
|
+
|
36
39
|
def current_page
|
37
40
|
if data = pagination_data
|
38
41
|
Integer(data.attr("currentPage"))
|
@@ -40,7 +43,7 @@ module HotelBeds
|
|
40
43
|
0
|
41
44
|
end
|
42
45
|
end
|
43
|
-
|
46
|
+
|
44
47
|
def total_pages
|
45
48
|
if data = pagination_data
|
46
49
|
Integer(data.attr("totalPages"))
|
@@ -48,7 +51,7 @@ module HotelBeds
|
|
48
51
|
0
|
49
52
|
end
|
50
53
|
end
|
51
|
-
|
54
|
+
|
52
55
|
def hotels
|
53
56
|
body.css("ServiceHotel").lazy.map do |hotel|
|
54
57
|
HotelBeds::Model::Hotel.new({
|
@@ -57,37 +60,39 @@ module HotelBeds
|
|
57
60
|
images: hotel.css("HotelInfo ImageList Image Url").map(&:content),
|
58
61
|
latitude: hotel.at_css("HotelInfo Position").attr("latitude"),
|
59
62
|
longitude: hotel.at_css("HotelInfo Position").attr("longitude"),
|
60
|
-
results:
|
63
|
+
results: generate_results(hotel.css("AvailableRoom"))
|
61
64
|
})
|
62
65
|
end
|
63
66
|
end
|
64
|
-
|
67
|
+
|
65
68
|
private
|
66
69
|
def pagination_data
|
67
70
|
body.at_css("PaginationData")
|
68
71
|
end
|
69
|
-
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
72
|
+
|
73
|
+
def generate_results(rooms)
|
74
|
+
parsed_rooms = parse_available_rooms(rooms)
|
75
|
+
if request.group_results?
|
76
|
+
parsed_rooms = RoomGrouper.new(request.rooms, parsed_rooms).results
|
77
|
+
end
|
78
|
+
parsed_rooms.map do |rooms|
|
79
|
+
HotelBeds::Model::SearchResult.new(rooms: Array(rooms))
|
77
80
|
end
|
78
81
|
end
|
79
82
|
|
80
|
-
def
|
83
|
+
def parse_available_rooms(rooms)
|
81
84
|
Array(rooms).map do |room|
|
82
|
-
{
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
85
|
+
HotelBeds::Model::AvailableRoom.new({
|
86
|
+
id: room.at_css("HotelRoom").attr("SHRUI"),
|
87
|
+
adult_count: room.at_css("HotelOccupancy AdultCount").content,
|
88
|
+
child_count: room.at_css("HotelOccupancy ChildCount").content,
|
89
|
+
number_available: room.at_css("HotelRoom").attr("availCount"),
|
90
|
+
description: room.at_css("HotelRoom RoomType").content,
|
91
|
+
board: room.at_css("HotelRoom Board").content,
|
88
92
|
currency: body.at_css("Currency").attr("code"),
|
93
|
+
price: ((room.at_css("HotelRoom") > "Price") > "Amount").first.content,
|
89
94
|
rates: parse_price_list(room.css("Price PriceList Price"))
|
90
|
-
}
|
95
|
+
})
|
91
96
|
end
|
92
97
|
end
|
93
98
|
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "hotel_beds/model/search_result"
|
2
|
+
|
3
|
+
# see INTERNALS.md for comment symbols
|
4
|
+
module HotelBeds
|
5
|
+
module HotelSearch
|
6
|
+
class RoomGrouper < Struct.new(:requested_rooms, :response_rooms)
|
7
|
+
def results
|
8
|
+
if requested_rooms.size == 1
|
9
|
+
response_rooms.map { |room| [room] }
|
10
|
+
else
|
11
|
+
combined_available_rooms
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
# returns an array of room combinations for all rooms
|
17
|
+
def combined_available_rooms
|
18
|
+
room_groups = combine_available_rooms_by_occupants.values
|
19
|
+
head, *rest = room_groups
|
20
|
+
head.product(*rest).map { |rooms| rooms.flatten.sort_by(&:id) }.uniq
|
21
|
+
end
|
22
|
+
|
23
|
+
# returns a hash of OK => RSRG
|
24
|
+
def combine_available_rooms_by_occupants
|
25
|
+
group_requested_room_count_by_occupants.to_a.inject(Hash.new) do |result, (key, count)|
|
26
|
+
result[key] = group_rooms_by_occupants.fetch(key).combination(count).to_a
|
27
|
+
result
|
28
|
+
end
|
29
|
+
rescue KeyError => e
|
30
|
+
Hash.new
|
31
|
+
end
|
32
|
+
|
33
|
+
# returns a hash of OK => RC
|
34
|
+
def group_requested_room_count_by_occupants
|
35
|
+
requested_rooms.inject(Hash.new) do |result, room|
|
36
|
+
key = occupant_key(room)
|
37
|
+
result[key] ||= 0
|
38
|
+
result[key] += 1
|
39
|
+
result
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# returns a hash of OK => AR
|
44
|
+
def group_rooms_by_occupants
|
45
|
+
@frozen_rooms ||= response_rooms.inject(Hash.new) do |result, room|
|
46
|
+
key = occupant_key(room)
|
47
|
+
result[key] ||= Array.new
|
48
|
+
1.upto([room.number_available, 5].min) do |i|
|
49
|
+
result[key].push(room)
|
50
|
+
end
|
51
|
+
result
|
52
|
+
end.freeze
|
53
|
+
end
|
54
|
+
|
55
|
+
# returns an OK for a given room
|
56
|
+
def occupant_key(room)
|
57
|
+
{
|
58
|
+
adult_count: room.adult_count,
|
59
|
+
child_count: room.child_count
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/hotel_beds/model.rb
CHANGED
@@ -1,15 +1,25 @@
|
|
1
1
|
require "hotel_beds/model"
|
2
|
-
require_relative "hotel_room"
|
3
2
|
|
4
3
|
module HotelBeds
|
5
4
|
module Model
|
6
5
|
class AvailableRoom
|
7
6
|
include HotelBeds::Model
|
8
|
-
|
7
|
+
|
9
8
|
# attributes
|
10
|
-
attribute :
|
9
|
+
attribute :id, Integer
|
11
10
|
attribute :adult_count, Integer
|
12
11
|
attribute :child_count, Integer
|
12
|
+
attribute :description, String
|
13
|
+
attribute :board, String
|
14
|
+
attribute :price, BigDecimal
|
15
|
+
attribute :currency, String
|
16
|
+
attribute :number_available, Integer
|
17
|
+
attribute :rates, Hash[Date => BigDecimal]
|
18
|
+
|
19
|
+
# compare based on id
|
20
|
+
def <=>(other)
|
21
|
+
id == other.id && !id.nil?
|
22
|
+
end
|
13
23
|
end
|
14
24
|
end
|
15
25
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require "hotel_beds/model"
|
2
|
-
require_relative "
|
2
|
+
require_relative "search_result"
|
3
3
|
|
4
4
|
module HotelBeds
|
5
5
|
module Model
|
@@ -13,7 +13,7 @@ module HotelBeds
|
|
13
13
|
attribute :stars, Integer
|
14
14
|
attribute :longitude, BigDecimal
|
15
15
|
attribute :latitude, BigDecimal
|
16
|
-
attribute :results, Array[
|
16
|
+
attribute :results, Array[SearchResult]
|
17
17
|
end
|
18
18
|
end
|
19
|
-
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "hotel_beds/model"
|
2
|
+
require_relative "available_room"
|
3
|
+
|
4
|
+
module HotelBeds
|
5
|
+
module Model
|
6
|
+
class SearchResult
|
7
|
+
include HotelBeds::Model
|
8
|
+
|
9
|
+
# attributes
|
10
|
+
attribute :rooms, Array[AvailableRoom]
|
11
|
+
attribute :currency, String
|
12
|
+
|
13
|
+
# results are purely based upon their combination of rooms
|
14
|
+
def <=>(other)
|
15
|
+
rooms.map(&:id).sort == other.rooms.map(&:id).sort
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/hotel_beds/version.rb
CHANGED
@@ -0,0 +1,67 @@
|
|
1
|
+
require "hotel_beds"
|
2
|
+
|
3
|
+
RSpec.describe "performing a grouped hotel search" do
|
4
|
+
describe "#response" do
|
5
|
+
before(:all) do
|
6
|
+
@client = HotelBeds::Client.new({
|
7
|
+
endpoint: :test,
|
8
|
+
username: ENV.fetch("HOTEL_BEDS_USERNAME"),
|
9
|
+
password: ENV.fetch("HOTEL_BEDS_PASSWORD"),
|
10
|
+
proxy: ENV.fetch("HOTEL_BEDS_PROXY", nil)
|
11
|
+
})
|
12
|
+
@check_in_date = Date.today + 28 + rand(10)
|
13
|
+
@check_out_date = @check_in_date + rand(3) + rand(2) + 1
|
14
|
+
@operation = @client.perform_hotel_search({
|
15
|
+
check_in_date: @check_in_date,
|
16
|
+
check_out_date: @check_out_date,
|
17
|
+
rooms: [
|
18
|
+
{ adult_count: 2 },
|
19
|
+
{ adult_count: 1, child_count: 1, child_ages: [rand(17)] }
|
20
|
+
],
|
21
|
+
destination: "SYD",
|
22
|
+
group_results: true
|
23
|
+
})
|
24
|
+
if @operation.errors.any?
|
25
|
+
raise StandardError, @operation.errors.full_messages.join("\n")
|
26
|
+
end
|
27
|
+
@response = @operation.response
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:check_in_date) { @check_in_date }
|
31
|
+
let(:check_out_date) { @check_out_date }
|
32
|
+
let(:response) { @response }
|
33
|
+
|
34
|
+
describe "#errors" do
|
35
|
+
subject { response.errors }
|
36
|
+
|
37
|
+
it "should be empty" do
|
38
|
+
expect(subject).to be_empty
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#hotels" do
|
43
|
+
subject { response.hotels }
|
44
|
+
|
45
|
+
it "should have room counts to match the searched room count" do
|
46
|
+
room_counts = subject.map { |h| h.results.map { |r| r.rooms.size } }
|
47
|
+
expect(room_counts.to_a.flatten.uniq).to eq([response.request.rooms.size])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#current_page" do
|
52
|
+
subject { response.current_page }
|
53
|
+
|
54
|
+
it "should return '1'" do
|
55
|
+
expect(subject).to eq(1)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#total_pages" do
|
60
|
+
subject { response.total_pages }
|
61
|
+
|
62
|
+
it "should be greater or equal to current page" do
|
63
|
+
expect(subject).to be >= response.current_page
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -25,12 +25,12 @@ RSpec.describe "performing a hotel search" do
|
|
25
25
|
|
26
26
|
describe "#errors" do
|
27
27
|
subject { response.errors }
|
28
|
-
|
28
|
+
|
29
29
|
it "should be empty" do
|
30
30
|
expect(subject).to be_empty
|
31
31
|
end
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
describe "#hotels" do
|
35
35
|
subject { response.hotels }
|
36
36
|
|
@@ -39,18 +39,23 @@ RSpec.describe "performing a hotel search" do
|
|
39
39
|
expect(subject.to_a).to_not be_empty
|
40
40
|
expect(subject.first).to be_kind_of(HotelBeds::Model::Hotel)
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
it "should parse the rates correctly" do
|
44
44
|
room = subject.first.results.first.rooms.first
|
45
45
|
expect(room.price).to eq(room.rates.values.inject(:+))
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
it "should have the same number of rates as nights requested" do
|
49
49
|
room = subject.first.results.first.rooms.first
|
50
50
|
expect(room.rates.size).to eq(check_out_date - check_in_date)
|
51
51
|
end
|
52
|
+
|
53
|
+
it "should only have one room per result" do
|
54
|
+
room_counts = subject.map { |h| h.results.map { |r| r.rooms.size } }
|
55
|
+
expect(room_counts.to_a.flatten.uniq).to eq([1])
|
56
|
+
end
|
52
57
|
end
|
53
|
-
|
58
|
+
|
54
59
|
describe "#current_page" do
|
55
60
|
subject { response.current_page }
|
56
61
|
|
@@ -58,7 +63,7 @@ RSpec.describe "performing a hotel search" do
|
|
58
63
|
expect(subject).to eq(1)
|
59
64
|
end
|
60
65
|
end
|
61
|
-
|
66
|
+
|
62
67
|
describe "#total_pages" do
|
63
68
|
subject { response.total_pages }
|
64
69
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "hotel_beds/hotel_search/room_grouper"
|
2
|
+
|
3
|
+
RSpec.describe HotelBeds::HotelSearch::RoomGrouper do
|
4
|
+
subject { described_class.new(requested_rooms, response_rooms).results }
|
5
|
+
|
6
|
+
context "when asking for 2 rooms (2 adults & 1 adult, 1 child)" do
|
7
|
+
let(:requested_rooms) do
|
8
|
+
[
|
9
|
+
double(:requested_room, adult_count: 2, child_count: 0),
|
10
|
+
double(:requested_room, adult_count: 1, child_count: 1)
|
11
|
+
]
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:response_rooms) do
|
15
|
+
[
|
16
|
+
double(:response_room_1, id: "room_1", adult_count: 2, child_count: 0, number_available: 1),
|
17
|
+
double(:response_room_2, id: "room_2", adult_count: 2, child_count: 0, number_available: 1),
|
18
|
+
double(:response_room_3, id: "room_3", adult_count: 1, child_count: 1, number_available: 2),
|
19
|
+
double(:response_room_4, id: "room_4", adult_count: 1, child_count: 1, number_available: 1),
|
20
|
+
double(:response_room_5, id: "room_5", adult_count: 2, child_count: 0, number_available: 2)
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return 6 results" do
|
25
|
+
expect(subject.size).to eq(6)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when asking for 1 rooms (1 adult, 1 child)" do
|
30
|
+
let(:requested_rooms) do
|
31
|
+
[double(:requested_room, adult_count: 1, child_count: 1)]
|
32
|
+
end
|
33
|
+
|
34
|
+
let(:response_rooms) do
|
35
|
+
[
|
36
|
+
double(:response_room_1, id: "room_1", adult_count: 1, child_count: 1, number_available: 2),
|
37
|
+
double(:response_room_2, id: "room_2", adult_count: 1, child_count: 1, number_available: 1)
|
38
|
+
]
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should return 2 results" do
|
42
|
+
expect(subject.size).to eq(2)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hotel_beds
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Townsend
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: savon
|
@@ -162,8 +162,10 @@ files:
|
|
162
162
|
- ".rspec"
|
163
163
|
- ".ruby-gemset"
|
164
164
|
- ".ruby-version"
|
165
|
+
- ".tm_properties"
|
165
166
|
- Gemfile
|
166
167
|
- Guardfile
|
168
|
+
- INTERNALS.md
|
167
169
|
- LICENSE.txt
|
168
170
|
- README.md
|
169
171
|
- Rakefile
|
@@ -176,16 +178,19 @@ files:
|
|
176
178
|
- lib/hotel_beds/hotel_search/operation.rb
|
177
179
|
- lib/hotel_beds/hotel_search/request.rb
|
178
180
|
- lib/hotel_beds/hotel_search/response.rb
|
181
|
+
- lib/hotel_beds/hotel_search/room_grouper.rb
|
179
182
|
- lib/hotel_beds/model.rb
|
180
183
|
- lib/hotel_beds/model/available_room.rb
|
181
184
|
- lib/hotel_beds/model/hotel.rb
|
182
|
-
- lib/hotel_beds/model/
|
185
|
+
- lib/hotel_beds/model/search_result.rb
|
183
186
|
- lib/hotel_beds/version.rb
|
187
|
+
- spec/features/grouped_hotel_search_spec.rb
|
184
188
|
- spec/features/hotel_search_spec.rb
|
185
189
|
- spec/lib/hotel_beds/client_spec.rb
|
186
190
|
- spec/lib/hotel_beds/configuration_spec.rb
|
187
191
|
- spec/lib/hotel_beds/connection_spec.rb
|
188
192
|
- spec/lib/hotel_beds/hotel_search/request_spec.rb
|
193
|
+
- spec/lib/hotel_beds/hotel_search/room_grouper_spec.rb
|
189
194
|
- spec/lib/hotel_beds/version_spec.rb
|
190
195
|
- spec/spec_helper.rb
|
191
196
|
homepage: https://www.hotelsindex.com/open-source
|
@@ -213,10 +218,12 @@ signing_key:
|
|
213
218
|
specification_version: 4
|
214
219
|
summary: Interfaces with the HotelBeds SOAP API to book hotel rooms
|
215
220
|
test_files:
|
221
|
+
- spec/features/grouped_hotel_search_spec.rb
|
216
222
|
- spec/features/hotel_search_spec.rb
|
217
223
|
- spec/lib/hotel_beds/client_spec.rb
|
218
224
|
- spec/lib/hotel_beds/configuration_spec.rb
|
219
225
|
- spec/lib/hotel_beds/connection_spec.rb
|
220
226
|
- spec/lib/hotel_beds/hotel_search/request_spec.rb
|
227
|
+
- spec/lib/hotel_beds/hotel_search/room_grouper_spec.rb
|
221
228
|
- spec/lib/hotel_beds/version_spec.rb
|
222
229
|
- spec/spec_helper.rb
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require "hotel_beds/model"
|
2
|
-
|
3
|
-
module HotelBeds
|
4
|
-
module Model
|
5
|
-
class HotelRoom
|
6
|
-
include HotelBeds::Model
|
7
|
-
|
8
|
-
# attributes
|
9
|
-
attribute :id, Integer
|
10
|
-
attribute :description, String
|
11
|
-
attribute :board, String
|
12
|
-
attribute :price, BigDecimal
|
13
|
-
attribute :currency, String
|
14
|
-
attribute :number_available, Integer
|
15
|
-
attribute :rates, Hash[Date => BigDecimal]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|