bookingsync-api 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/Gemfile +2 -1
- data/Guardfile +3 -6
- data/README.md +11 -3
- data/bookingsync-api.gemspec +2 -2
- data/lib/bookingsync/api.rb +0 -2
- data/lib/bookingsync/api/client.rb +151 -54
- data/lib/bookingsync/api/client/amenities.rb +22 -0
- data/lib/bookingsync/api/client/billing_addresses.rb +22 -0
- data/lib/bookingsync/api/client/bookings.rb +7 -9
- data/lib/bookingsync/api/client/bookings_payments.rb +22 -0
- data/lib/bookingsync/api/client/clients.rb +43 -0
- data/lib/bookingsync/api/client/destinations.rb +22 -0
- data/lib/bookingsync/api/client/inquiries.rb +2 -2
- data/lib/bookingsync/api/client/payments.rb +53 -0
- data/lib/bookingsync/api/client/periods.rb +54 -0
- data/lib/bookingsync/api/client/photos.rb +22 -0
- data/lib/bookingsync/api/client/rates.rb +23 -0
- data/lib/bookingsync/api/client/rates_rules.rb +22 -0
- data/lib/bookingsync/api/client/rates_tables.rb +53 -0
- data/lib/bookingsync/api/client/rental_agreements.rb +50 -0
- data/lib/bookingsync/api/client/rentals.rb +39 -1
- data/lib/bookingsync/api/client/reviews.rb +31 -0
- data/lib/bookingsync/api/client/seasons.rb +53 -0
- data/lib/bookingsync/api/client/special_offers.rb +54 -0
- data/lib/bookingsync/api/relation.rb +87 -0
- data/lib/bookingsync/api/resource.rb +58 -0
- data/lib/bookingsync/api/response.rb +79 -0
- data/lib/bookingsync/api/serializer.rb +100 -0
- data/lib/bookingsync/api/version.rb +1 -1
- data/spec/bookingsync/api/client/amenities_spec.rb +12 -0
- data/spec/bookingsync/api/client/billing_addresses_spec.rb +12 -0
- data/spec/bookingsync/api/client/billings_payments_spec.rb +12 -0
- data/spec/bookingsync/api/client/bookings_spec.rb +10 -8
- data/spec/bookingsync/api/client/clients_spec.rb +55 -0
- data/spec/bookingsync/api/client/destinations_spec.rb +12 -0
- data/spec/bookingsync/api/client/inquiries_spec.rb +1 -1
- data/spec/bookingsync/api/client/payments_spec.rb +56 -0
- data/spec/bookingsync/api/client/periods_spec.rb +61 -0
- data/spec/bookingsync/api/client/photos_spec.rb +12 -0
- data/spec/bookingsync/api/client/rates_rules_spec.rb +13 -0
- data/spec/bookingsync/api/client/rates_spec.rb +12 -0
- data/spec/bookingsync/api/client/rates_tables_spec.rb +59 -0
- data/spec/bookingsync/api/client/rental_agreements_spec.rb +64 -0
- data/spec/bookingsync/api/client/rentals_spec.rb +56 -6
- data/spec/bookingsync/api/client/reviews_spec.rb +33 -0
- data/spec/bookingsync/api/client/seasons_spec.rb +61 -0
- data/spec/bookingsync/api/client/special_offers_spec.rb +63 -0
- data/spec/bookingsync/api/client_spec.rb +31 -10
- data/spec/bookingsync/api/relation_spec.rb +72 -0
- data/spec/bookingsync/api/resource_spec.rb +79 -0
- data/spec/bookingsync/api/response_spec.rb +66 -0
- data/spec/cassettes/BookingSync_API_Client_Amenities/_amenities/returns_amenities.yml +72 -0
- data/spec/cassettes/BookingSync_API_Client_BillingAddresses/_billing_addresses/returns_billing_addresses.yml +65 -0
- data/spec/cassettes/BookingSync_API_Client_Bookings/_bookings/pagination/with_a_block/yields_block_with_batch_of_bookings.yml +12 -12
- data/spec/cassettes/BookingSync_API_Client_Bookings/_bookings/pagination/with_auto_paginate_true/returns_all_bookings_joined_from_many_requests.yml +12 -12
- data/spec/cassettes/BookingSync_API_Client_Bookings/_bookings/pagination/with_per_page_setting/returns_limited_number_of_bookings.yml +3 -3
- data/spec/cassettes/BookingSync_API_Client_Bookings/_clients/returns_clients.yml +66 -0
- data/spec/cassettes/BookingSync_API_Client_Bookings/_create_booking/creates_a_booking.yml +1 -1
- data/spec/cassettes/BookingSync_API_Client_Bookings/_create_client/creates_a_new_client.yml +64 -0
- data/spec/cassettes/BookingSync_API_Client_Bookings/_edit_booking/updates_given_booking_by_ID.yml +18 -14
- data/spec/cassettes/BookingSync_API_Client_Bookings/_edit_client/updates_given_client_by_ID.yml +62 -0
- data/spec/cassettes/BookingSync_API_Client_BookingsPayments/_bookings_payments/returns_bookings_payments.yml +65 -0
- data/spec/cassettes/BookingSync_API_Client_Destinations/_destinations/returns_destinations.yml +64 -0
- data/spec/cassettes/BookingSync_API_Client_Inquiries/_create_inquiry/creates_a_new_inquiry.yml +1 -1
- data/spec/cassettes/BookingSync_API_Client_Inquiries/_inquiries/returns_inquiries.yml +1 -1
- data/spec/cassettes/BookingSync_API_Client_Payments/_cancel_payment/cancels_given_payment.yml +57 -0
- data/spec/cassettes/BookingSync_API_Client_Payments/_create_payment/creates_a_new_payment.yml +63 -0
- data/spec/cassettes/BookingSync_API_Client_Payments/_edit_payment/updates_given_payment_by_ID.yml +61 -0
- data/spec/cassettes/BookingSync_API_Client_Payments/_payments/returns_payments.yml +64 -0
- data/spec/cassettes/BookingSync_API_Client_Periods/_create_period/creates_a_new_period.yml +63 -0
- data/spec/cassettes/BookingSync_API_Client_Periods/_delete_period/deletes_given_period.yml +70 -0
- data/spec/cassettes/BookingSync_API_Client_Periods/_edit_period/updates_given_period_by_ID.yml +61 -0
- data/spec/cassettes/BookingSync_API_Client_Periods/_periods/returns_periods.yml +64 -0
- data/spec/cassettes/BookingSync_API_Client_Photos/_photos/returns_photos.yml +72 -0
- data/spec/cassettes/BookingSync_API_Client_Rates/_rates/returns_rates.yml +64 -0
- data/spec/cassettes/BookingSync_API_Client_RatesRules/_rates_rules/returns_rates_rules.yml +64 -0
- data/spec/cassettes/BookingSync_API_Client_RatesTables/_create_rates_table/creates_a_new_rates_table.yml +64 -0
- data/spec/cassettes/BookingSync_API_Client_RatesTables/_delete_rates_table/deletes_given_rates_table.yml +57 -0
- data/spec/cassettes/BookingSync_API_Client_RatesTables/_edit_rates_table/updates_given_rates_table_by_ID.yml +62 -0
- data/spec/cassettes/BookingSync_API_Client_RatesTables/_rates_tables/returns_rates_tables.yml +74 -0
- data/spec/cassettes/BookingSync_API_Client_RentalAgreements/_create_rental_agreement/creates_a_new_rental_agreement.yml +63 -0
- data/spec/cassettes/BookingSync_API_Client_RentalAgreements/_create_rental_agreement_for_booking/creates_a_new_rental_agreement.yml +63 -0
- data/spec/cassettes/BookingSync_API_Client_RentalAgreements/_create_rental_agreement_for_rental/creates_a_new_rental_agreement.yml +63 -0
- data/spec/cassettes/BookingSync_API_Client_RentalAgreements/_rental_agreements/returns_rental_agreements.yml +64 -0
- data/spec/cassettes/BookingSync_API_Client_Rentals/_cancel_rental/cancels_given_rental.yml +57 -0
- data/spec/cassettes/BookingSync_API_Client_Rentals/_create_rental/creates_a_new_rental.yml +64 -0
- data/spec/cassettes/BookingSync_API_Client_Rentals/_edit_rental/updates_given_rental_by_ID.yml +64 -0
- data/spec/cassettes/BookingSync_API_Client_Rentals/_rental/returns_a_single_rental.yml +67 -0
- data/spec/cassettes/BookingSync_API_Client_Rentals/_rentals/links/returns_associated_photos.yml +152 -0
- data/spec/cassettes/BookingSync_API_Client_Rentals/_rentals/links/returns_links_to_associated_resources.yml +91 -0
- data/spec/cassettes/BookingSync_API_Client_Rentals/_rentals/returns_rentals.yml +45 -20
- data/spec/cassettes/BookingSync_API_Client_Reviews/_create_review/creates_a_new_review.yml +64 -0
- data/spec/cassettes/BookingSync_API_Client_Reviews/_reviews/returns_reviews.yml +83 -0
- data/spec/cassettes/BookingSync_API_Client_Seasons/_create_season/creates_a_new_season.yml +64 -0
- data/spec/cassettes/BookingSync_API_Client_Seasons/_delete_season/deletes_given_season.yml +57 -0
- data/spec/cassettes/BookingSync_API_Client_Seasons/_edit_season/updates_given_season_by_ID.yml +62 -0
- data/spec/cassettes/BookingSync_API_Client_Seasons/_seasons/returns_seasons.yml +74 -0
- data/spec/cassettes/BookingSync_API_Client_SpecialOffers/_create_special_offer/creates_a_new_special_offer.yml +63 -0
- data/spec/cassettes/BookingSync_API_Client_SpecialOffers/_delete_special_offer/deletes_given_special_offer.yml +57 -0
- data/spec/cassettes/BookingSync_API_Client_SpecialOffers/_edit_special_offer/updates_given_special_offer_by_ID.yml +61 -0
- data/spec/cassettes/{BookingSync_API_Client_Rentals/_rentals/with_specified_fields_in_options/returns_rentals_with_filtered_fields.yml → BookingSync_API_Client_SpecialOffers/_special_offers/returns_special_offers.yml} +17 -10
- data/spec/spec_helper.rb +1 -0
- metadata +143 -7
- data/lib/bookingsync/ext/resource.rb +0 -9
@@ -6,7 +6,7 @@ module BookingSync::API
|
|
6
6
|
# Returns rentals for the account user is authenticated with.
|
7
7
|
# @param options [Hash] A customizable set of options.
|
8
8
|
# @option options [Array] fields: List of fields to be fetched.
|
9
|
-
# @return [Array<
|
9
|
+
# @return [Array<BookingSync::API::Resource>] Array of rentals.
|
10
10
|
#
|
11
11
|
# @example Get the list of rentals for the current account
|
12
12
|
# rentals = @api.rentals
|
@@ -17,6 +17,44 @@ module BookingSync::API
|
|
17
17
|
def rentals(options = {}, &block)
|
18
18
|
paginate :rentals, options, &block
|
19
19
|
end
|
20
|
+
|
21
|
+
# Create a new rental
|
22
|
+
#
|
23
|
+
# @param options [Hash] rental attributes
|
24
|
+
# @return [BookingSync::API::Resource] Newly created rental
|
25
|
+
def create_rental(options = {})
|
26
|
+
post(:rentals, rentals: [options]).pop
|
27
|
+
end
|
28
|
+
|
29
|
+
# Edit a rental
|
30
|
+
#
|
31
|
+
# @param rental [BookingSync::API::Resource|Integer] rental or ID of the rental
|
32
|
+
# to be updated
|
33
|
+
# @param options [Hash] rental attributes to be updated
|
34
|
+
# @return [BookingSync::API::Resource] Updated rental on success, exception is raised otherwise
|
35
|
+
# @example
|
36
|
+
# rental = @api.rentals.first
|
37
|
+
# @api.edit_rental(rental, { sleeps: 3 })
|
38
|
+
def edit_rental(rental, options = {})
|
39
|
+
put("rentals/#{rental}", rentals: [options]).pop
|
40
|
+
end
|
41
|
+
|
42
|
+
# Cancel a rental
|
43
|
+
#
|
44
|
+
# @param rental [BookingSync::API::Resource|Integer] rental or ID of the rental
|
45
|
+
# to be canceled
|
46
|
+
# @return [Array] An empty Array on success, exception is raised otherwise
|
47
|
+
def cancel_rental(rental, options = {})
|
48
|
+
delete "rentals/#{rental}"
|
49
|
+
end
|
50
|
+
|
51
|
+
# Get a single rental
|
52
|
+
#
|
53
|
+
# @param rental [BookingSync::API::Resource|Integer] Rental or ID of the rental
|
54
|
+
# @return [BookingSync::API::Resource]
|
55
|
+
def rental(rental)
|
56
|
+
get("rentals/#{rental}").pop
|
57
|
+
end
|
20
58
|
end
|
21
59
|
end
|
22
60
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module BookingSync::API
|
2
|
+
class Client
|
3
|
+
module Reviews
|
4
|
+
# List reviews
|
5
|
+
#
|
6
|
+
# Returns reviews for the account user is authenticated with.
|
7
|
+
# @param options [Hash] A customizable set of options.
|
8
|
+
# @option options [Array] fields: List of fields to be fetched.
|
9
|
+
# @return [Array<BookingSync::API::Resource>] Array of reviews.
|
10
|
+
#
|
11
|
+
# @example Get the list of reviews for the current account
|
12
|
+
# reviews = @api.reviews
|
13
|
+
# reviews.first.name # => "John Smith"
|
14
|
+
# @example Get the list of reviews only with name and comment for smaller response
|
15
|
+
# @api.reviews(fields: [:name, :comment])
|
16
|
+
# @see http://docs.api.bookingsync.com/reference/endpoints/reviews/#list-reviews
|
17
|
+
def reviews(options = {}, &block)
|
18
|
+
paginate :reviews, options, &block
|
19
|
+
end
|
20
|
+
|
21
|
+
# Create a new review
|
22
|
+
#
|
23
|
+
# @param booking_id [Integer] ID of the booking
|
24
|
+
# @param options [Hash] review attributes
|
25
|
+
# @return [BookingSync::API::Resource] Newly created review
|
26
|
+
def create_review(booking_id, options = {})
|
27
|
+
post(:reviews, booking_id: booking_id, reviews: [options]).pop
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module BookingSync::API
|
2
|
+
class Client
|
3
|
+
module Seasons
|
4
|
+
# List seasons
|
5
|
+
#
|
6
|
+
# Returns seasons for the account user is authenticated with.
|
7
|
+
# @param options [Hash] A customizable set of options.
|
8
|
+
# @option options [Array] fields: List of fields to be fetched.
|
9
|
+
# @return [Array<BookingSync::API::Resource>] Array of seasons.
|
10
|
+
#
|
11
|
+
# @example Get the list of seasons for the current account
|
12
|
+
# seasons = @api.seasons
|
13
|
+
# seasons.first.name # => "Season 2"
|
14
|
+
# @example Get the list of seasons only with name and ratio for smaller response
|
15
|
+
# @api.seasons(fields: [:name, :ratio])
|
16
|
+
# @see http://docs.api.bookingsync.com/reference/endpoints/seasons/#list-seasons
|
17
|
+
def seasons(options = {}, &block)
|
18
|
+
paginate :seasons, options, &block
|
19
|
+
end
|
20
|
+
|
21
|
+
# Create a new season
|
22
|
+
#
|
23
|
+
# @param rates_table_id [Integer] ID of the rates table
|
24
|
+
# @param options [Hash] season attributes
|
25
|
+
# @return [BookingSync::API::Resource] Newly created season
|
26
|
+
def create_season(rates_table_id, options = {})
|
27
|
+
post(:seasons, rates_table_id: rates_table_id, seasons: [options]).pop
|
28
|
+
end
|
29
|
+
|
30
|
+
# Edit a season
|
31
|
+
#
|
32
|
+
# @param season [BookingSync::API::Resource|Integer] season or ID of the season
|
33
|
+
# to be updated
|
34
|
+
# @param options [Hash] season attributes to be updated
|
35
|
+
# @return [BookingSync::API::Resource] Updated season on success, exception is raised otherwise
|
36
|
+
# @example
|
37
|
+
# season = @api.seasons.first
|
38
|
+
# @api.edit_season(season, { name: "Some season" })
|
39
|
+
def edit_season(season, options = {})
|
40
|
+
put("seasons/#{season}", seasons: [options]).pop
|
41
|
+
end
|
42
|
+
|
43
|
+
# Delete a season
|
44
|
+
#
|
45
|
+
# @param season [BookingSync::API::Resource|Integer] season or ID of the season
|
46
|
+
# to be deleted
|
47
|
+
# @return [Array] An empty Array on success, exception is raised otherwise
|
48
|
+
def delete_season(season, options = {})
|
49
|
+
delete "seasons/#{season}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module BookingSync::API
|
2
|
+
class Client
|
3
|
+
module SpecialOffers
|
4
|
+
# List special_offers
|
5
|
+
#
|
6
|
+
# Returns special_offers for the account user is authenticated with.
|
7
|
+
# @param options [Hash] A customizable set of options.
|
8
|
+
# @option options [Array] fields: List of fields to be fetched.
|
9
|
+
# @return [Array<BookingSync::API::Resource>] Array of special_offers.
|
10
|
+
#
|
11
|
+
# @example Get the list of special_offers for the current account
|
12
|
+
# special_offers = @api.special_offers
|
13
|
+
# special_offers.first.name # => "Spring discount"
|
14
|
+
# @example Get the list of special_offers only with name and rental_id for smaller response
|
15
|
+
# @api.special_offers(fields: [:name, :rental_id])
|
16
|
+
# @see http://docs.api.bookingsync.com/reference/endpoints/special_offers/#list-special_offers
|
17
|
+
def special_offers(options = {}, &block)
|
18
|
+
paginate :special_offers, options, &block
|
19
|
+
end
|
20
|
+
|
21
|
+
# Create a new special_offer
|
22
|
+
#
|
23
|
+
# @param rental_id [Integer] ID of the rental
|
24
|
+
# @param options [Hash] special_offer attributes
|
25
|
+
# @return [BookingSync::API::Resource] Newly created special offer
|
26
|
+
def create_special_offer(rental_id, options = {})
|
27
|
+
post(:special_offers, rental_id: rental_id, special_offers: [options]).pop
|
28
|
+
end
|
29
|
+
|
30
|
+
# Edit a special_offer
|
31
|
+
#
|
32
|
+
# @param special_offer [BookingSync::API::Resource|Integer] special offer or
|
33
|
+
# ID of the special offer to be updated
|
34
|
+
# @param options [Hash] special offer attributes to be updated
|
35
|
+
# @return [BookingSync::API::Resource] Updated special offer on success,
|
36
|
+
# exception is raised otherwise
|
37
|
+
# @example
|
38
|
+
# special_offer = @api.special_offers.first
|
39
|
+
# @api.edit_special_offer(special_offer, { name: "New offer" })
|
40
|
+
def edit_special_offer(special_offer, options = {})
|
41
|
+
put("special_offers/#{special_offer}", special_offers: [options]).pop
|
42
|
+
end
|
43
|
+
|
44
|
+
# Delete a special_offer
|
45
|
+
#
|
46
|
+
# @param special_offer [BookingSync::API::Resource|Integer] special offer or
|
47
|
+
# ID of the special offer to be deleted
|
48
|
+
# @return [Array] An empty Array on success, exception is raised otherwise
|
49
|
+
def delete_special_offer(special_offer, options = {})
|
50
|
+
delete "special_offers/#{special_offer}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module BookingSync::API
|
2
|
+
class Relation
|
3
|
+
attr_reader :client, :name, :href_template, :method
|
4
|
+
|
5
|
+
# Build a hash of Relations from the `links` key in JSON API response.
|
6
|
+
#
|
7
|
+
# @param client [BookingSync::API::Client] The client that made the HTTP
|
8
|
+
# request.
|
9
|
+
# @param links [Hash] Hash of relation_name => relation options.
|
10
|
+
# @return [Hash] Hash of relation_name => relation elements.
|
11
|
+
def self.from_links(client, links)
|
12
|
+
relations = {}
|
13
|
+
links.each do |name, options|
|
14
|
+
relations[name] = from_link(client, name, options)
|
15
|
+
end if links
|
16
|
+
relations
|
17
|
+
end
|
18
|
+
|
19
|
+
# Build a single Relation from the given options.
|
20
|
+
#
|
21
|
+
# @param client [BookingSync::API::Client] The client that made the HTTP
|
22
|
+
# request
|
23
|
+
#
|
24
|
+
# @param name [Symbol] Name of the Relation.
|
25
|
+
# @param options [Hash] A Hash containing the other Relation properties.
|
26
|
+
# @option options [String] href: The String URL of the next action's location.
|
27
|
+
# @option options [String] method: The optional String HTTP method.
|
28
|
+
# @return [BookingSync::API::Relation] New relation
|
29
|
+
def self.from_link(client, name, options)
|
30
|
+
case options
|
31
|
+
when Hash
|
32
|
+
new client, name, options[:href], options[:method]
|
33
|
+
when String
|
34
|
+
new client, name, options
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# A Relation represents an available next action for a resource.
|
39
|
+
#
|
40
|
+
# @param client [BookingSync::API::Client] The client that made the HTTP
|
41
|
+
# request.
|
42
|
+
# @param name [Symbol] The name of the relation.
|
43
|
+
# @param href [String] The String URL of the location of the next action.
|
44
|
+
# @param method [Symbol] The Symbol HTTP method. Default: :get
|
45
|
+
def initialize(client, name, href, method = nil)
|
46
|
+
@client = client
|
47
|
+
@name = name.to_sym
|
48
|
+
@href = href
|
49
|
+
@href_template = Addressable::Template.new(href.to_s)
|
50
|
+
@method = (method || :get).to_sym
|
51
|
+
@available_methods = Set.new methods || [@method]
|
52
|
+
end
|
53
|
+
|
54
|
+
# Make an API request with the curent Relation using GET.
|
55
|
+
#
|
56
|
+
# @param options [Hash] Options to configure the API request.
|
57
|
+
# @option options [Hash] headers: Hash of API headers to set.
|
58
|
+
# @option options [Hash] query: Hash of URL query params to set.
|
59
|
+
# @option options [Symbol] method: Symbol HTTP method.
|
60
|
+
# @return [BookingSync::API::Response] A response
|
61
|
+
def get(options = nil)
|
62
|
+
options ||= {}
|
63
|
+
options[:method] = :get
|
64
|
+
call options
|
65
|
+
end
|
66
|
+
|
67
|
+
def href(options = nil)
|
68
|
+
return @href if @href_template.nil?
|
69
|
+
@href_template.expand(options || {}).to_s
|
70
|
+
end
|
71
|
+
|
72
|
+
# Make an API request with the curent Relation.
|
73
|
+
#
|
74
|
+
# @param data [Hash|String] The Optional Hash or Resource body to be sent.
|
75
|
+
# :get or :head requests can have no body, so this can be the options Hash
|
76
|
+
# instead.
|
77
|
+
# @param options [Hash] A Hash of option to configure the API request.
|
78
|
+
# @option options [Hash] headers: A Hash of API headers to set.
|
79
|
+
# @option options [Hash] query: Hash of URL query params to set.
|
80
|
+
# @option options [Symbol] method: Symbol HTTP method.
|
81
|
+
# @return [BookingSync::API::Response]
|
82
|
+
def call(data = nil, options = nil)
|
83
|
+
m = options && options[:method]
|
84
|
+
@client.call m || @method, @href_template, data, options || {}
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "hashie"
|
2
|
+
|
3
|
+
module BookingSync::API
|
4
|
+
class Resource < Hash
|
5
|
+
include Hashie::Extensions::MethodAccess
|
6
|
+
attr_reader :_client, :_rels, :_links, :_resources_key
|
7
|
+
|
8
|
+
# Initialize a Resource with the given links and data.
|
9
|
+
#
|
10
|
+
# @param client [BookingSync::API::Client] The client that made the API request.
|
11
|
+
# @param data [Hash] Hash of key/value properties.
|
12
|
+
# @param links [Hash] Hash of link templates for this resource.
|
13
|
+
# @param resources_key [Symbol|String] Key in response body under which
|
14
|
+
def initialize(client, data = {}, links = {}, resources_key = nil)
|
15
|
+
@_links = links
|
16
|
+
@_client = client
|
17
|
+
@_resources_key = resources_key
|
18
|
+
data.each do |key, value|
|
19
|
+
self[key.to_sym] = process_value(value)
|
20
|
+
end
|
21
|
+
@_rels = Relation.from_links(client, links)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Process an individual value of this resource. Hashes get exploded
|
25
|
+
# into another Resource, and Arrays get their values processed too.
|
26
|
+
#
|
27
|
+
# @param value [Object] An Object value of a Resource's data.
|
28
|
+
# @return [Object] An Object to set as the value of a Resource key.
|
29
|
+
def process_value(value)
|
30
|
+
case value
|
31
|
+
when Hash then self.class.new(@_client, value, @_links)
|
32
|
+
when Array then value.map { |v| process_value(v) }
|
33
|
+
else value
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Make associations accessible
|
38
|
+
#
|
39
|
+
# @param method [Symbol] Name of association
|
40
|
+
# @param args [Array] Array of additional arguments
|
41
|
+
def method_missing(method, *args)
|
42
|
+
association_key = :"#{@_resources_key}.#{method}"
|
43
|
+
if self[:links] && self[:links].has_key?(method)
|
44
|
+
ids = self[:links][method]
|
45
|
+
return [] if !ids or ids.empty?
|
46
|
+
options = {uri: {association_key => ids}}
|
47
|
+
options.merge!(query: args.first) if args.first.is_a?(Hash)
|
48
|
+
@_rels[association_key].get(options).resources
|
49
|
+
else
|
50
|
+
super
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_s
|
55
|
+
id.to_s
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "addressable/template"
|
2
|
+
|
3
|
+
module BookingSync::API
|
4
|
+
class Response
|
5
|
+
SPECIAL_JSONAPI_FIELDS = %w(links linked meta)
|
6
|
+
attr_reader :client, :status, :headers, :data, :rels, :body
|
7
|
+
|
8
|
+
# Build a Response after a completed request.
|
9
|
+
#
|
10
|
+
# @param client [BookingSync::API::Client] The client that is
|
11
|
+
# managing the API connection.
|
12
|
+
# @param res [Faraday::Response] Faraday response object
|
13
|
+
def initialize(client, res)
|
14
|
+
@client = client
|
15
|
+
@status = res.status
|
16
|
+
@headers = res.headers
|
17
|
+
@env = res.env
|
18
|
+
@body = res.body
|
19
|
+
end
|
20
|
+
|
21
|
+
# Turn parsed contents from an API response into a Resource or
|
22
|
+
# collection of Resources.
|
23
|
+
#
|
24
|
+
# @param hash [Hash] A Hash of resources parsed from JSON.
|
25
|
+
# @return [Array] An Array of Resources.
|
26
|
+
def process_data(hash, links)
|
27
|
+
Array(hash).map do |hash|
|
28
|
+
Resource.new(client, hash, links, resources_key)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return name of the key in the response body hash
|
33
|
+
# where fetched resources are, like bookings or rentals
|
34
|
+
#
|
35
|
+
# @return [Symbol] Key name in the body hash
|
36
|
+
def resources_key
|
37
|
+
decoded_body.keys.delete_if { |k|
|
38
|
+
SPECIAL_JSONAPI_FIELDS.include?(k)
|
39
|
+
}.pop
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return an array of Resources from the response body
|
43
|
+
#
|
44
|
+
# @return [Array<BookingSync::API::Resource>]
|
45
|
+
def resources
|
46
|
+
@resources ||= process_data(decoded_body[resources_key], links)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Return an array of links templates from the response body,
|
50
|
+
# it's the contents of links hash
|
51
|
+
# {'links': {'rentals.photos':'https://www.bookingsync.com/api/v3/photos/{rentals.photos}'}}
|
52
|
+
#
|
53
|
+
# @return [Hash] Hash of links to associated resources
|
54
|
+
def links
|
55
|
+
@links ||= decoded_body[:links]
|
56
|
+
end
|
57
|
+
|
58
|
+
# Return link relations from 'Link' response header
|
59
|
+
#
|
60
|
+
# @return [Array] An array of Relations
|
61
|
+
def rels
|
62
|
+
@rels ||= process_rels
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def decoded_body
|
68
|
+
@decoded_body ||= @client.decode_body(body) || {}
|
69
|
+
end
|
70
|
+
|
71
|
+
def process_rels
|
72
|
+
links = ( @headers["Link"] || "" ).split(', ').map do |link|
|
73
|
+
href, name = link.match(/<(.*?)>; rel="(\w+)"/).captures
|
74
|
+
[name.to_sym, Relation.from_link(@client, name, :href => href)]
|
75
|
+
end
|
76
|
+
Hash[*links.flatten]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'time'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module BookingSync::API
|
6
|
+
class Serializer
|
7
|
+
# Public: Wraps a serialization format for Sawyer. Nested objects are
|
8
|
+
# prepared for serialization (such as changing Times to ISO 8601 Strings).
|
9
|
+
# Any serialization format that responds to #dump and #load will work.
|
10
|
+
def initialize(dump_method_name = nil, load_method_name = nil)
|
11
|
+
@format = JSON
|
12
|
+
@dump = @format.method(dump_method_name || :dump)
|
13
|
+
@load = @format.method(load_method_name || :load)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Public: Encodes an Object (usually a Hash or Array of Hashes).
|
17
|
+
#
|
18
|
+
# data - Object to be encoded.
|
19
|
+
#
|
20
|
+
# Returns an encoded String.
|
21
|
+
def encode(data)
|
22
|
+
@dump.call(encode_object(data))
|
23
|
+
end
|
24
|
+
|
25
|
+
alias dump encode
|
26
|
+
|
27
|
+
# Public: Decodes a String into an Object (usually a Hash or Array of
|
28
|
+
# Hashes).
|
29
|
+
#
|
30
|
+
# data - An encoded String.
|
31
|
+
#
|
32
|
+
# Returns a decoded Object.
|
33
|
+
def decode(data)
|
34
|
+
return nil if data.nil? || data.empty?
|
35
|
+
decode_object(@load.call(data))
|
36
|
+
end
|
37
|
+
|
38
|
+
alias load decode
|
39
|
+
|
40
|
+
def encode_object(data)
|
41
|
+
case data
|
42
|
+
when Hash then encode_hash(data)
|
43
|
+
when Array then data.map { |o| encode_object(o) }
|
44
|
+
else data
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def encode_hash(hash)
|
49
|
+
hash.keys.each do |key|
|
50
|
+
case value = hash[key]
|
51
|
+
when Date then hash[key] = value.to_time.utc.xmlschema
|
52
|
+
when Time then hash[key] = value.utc.xmlschema
|
53
|
+
when Hash then hash[key] = encode_hash(value)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
hash
|
57
|
+
end
|
58
|
+
|
59
|
+
def decode_object(data)
|
60
|
+
case data
|
61
|
+
when Hash then decode_hash(data)
|
62
|
+
when Array then data.map { |o| decode_object(o) }
|
63
|
+
else data
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def decode_hash(hash)
|
68
|
+
hash.keys.each do |key|
|
69
|
+
hash[key.to_sym] = decode_hash_value(key, hash.delete(key))
|
70
|
+
end
|
71
|
+
hash
|
72
|
+
end
|
73
|
+
|
74
|
+
def decode_hash_value(key, value)
|
75
|
+
if time_field?(key, value)
|
76
|
+
if value.is_a?(String)
|
77
|
+
begin
|
78
|
+
Time.parse(value)
|
79
|
+
rescue ArgumentError
|
80
|
+
value
|
81
|
+
end
|
82
|
+
elsif value.is_a?(Integer) || value.is_a?(Float)
|
83
|
+
Time.at(value)
|
84
|
+
else
|
85
|
+
value
|
86
|
+
end
|
87
|
+
elsif value.is_a?(Hash)
|
88
|
+
decode_hash(value)
|
89
|
+
elsif value.is_a?(Array)
|
90
|
+
value.map { |o| decode_hash_value(key, o) }
|
91
|
+
else
|
92
|
+
value
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def time_field?(key, value)
|
97
|
+
value && (key =~ /_(at|on)\z/ || key =~ /(\A|_)date\z/)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|