bookingsync-api 0.0.6 → 0.0.7
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.
- 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
|