tailored-etsy 0.2.2
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 +8 -0
- data/.travis.yml +8 -0
- data/Gemfile +3 -0
- data/LICENSE +9 -0
- data/README.md +280 -0
- data/Rakefile +12 -0
- data/etsy.gemspec +28 -0
- data/lib/etsy.rb +172 -0
- data/lib/etsy/address.rb +47 -0
- data/lib/etsy/basic_client.rb +26 -0
- data/lib/etsy/category.rb +84 -0
- data/lib/etsy/country.rb +27 -0
- data/lib/etsy/image.rb +34 -0
- data/lib/etsy/listing.rb +178 -0
- data/lib/etsy/model.rb +123 -0
- data/lib/etsy/payment_template.rb +33 -0
- data/lib/etsy/profile.rb +49 -0
- data/lib/etsy/request.rb +148 -0
- data/lib/etsy/response.rb +112 -0
- data/lib/etsy/section.rb +16 -0
- data/lib/etsy/secure_client.rb +128 -0
- data/lib/etsy/shipping_template.rb +32 -0
- data/lib/etsy/shop.rb +83 -0
- data/lib/etsy/transaction.rb +18 -0
- data/lib/etsy/user.rb +91 -0
- data/lib/etsy/verification_request.rb +17 -0
- data/lib/etsy/version.rb +3 -0
- data/test/fixtures/address/getUserAddresses.json +12 -0
- data/test/fixtures/category/findAllSubCategoryChildren.json +78 -0
- data/test/fixtures/category/findAllTopCategory.json +347 -0
- data/test/fixtures/category/findAllTopCategory.single.json +18 -0
- data/test/fixtures/category/findAllTopCategoryChildren.json +308 -0
- data/test/fixtures/category/getCategory.multiple.json +28 -0
- data/test/fixtures/category/getCategory.single.json +18 -0
- data/test/fixtures/country/getCountry.json +1 -0
- data/test/fixtures/image/findAllListingImages.json +102 -0
- data/test/fixtures/listing/findAllListingActive.category.json +827 -0
- data/test/fixtures/listing/findAllShopListings.json +69 -0
- data/test/fixtures/listing/getListing.multiple.json +1 -0
- data/test/fixtures/listing/getListing.single.json +1 -0
- data/test/fixtures/payment_template/getPaymentTemplate.json +1 -0
- data/test/fixtures/profile/new.json +28 -0
- data/test/fixtures/section/getShopSection.json +18 -0
- data/test/fixtures/shipping_template/getShippingTemplate.json +1 -0
- data/test/fixtures/shop/findAllShop.json +1 -0
- data/test/fixtures/shop/findAllShop.single.json +1 -0
- data/test/fixtures/shop/getShop.multiple.json +1 -0
- data/test/fixtures/shop/getShop.single.json +33 -0
- data/test/fixtures/transaction/findAllShopTransactions.json +1 -0
- data/test/fixtures/user/getUser.multiple.json +29 -0
- data/test/fixtures/user/getUser.single.json +13 -0
- data/test/fixtures/user/getUser.single.private.json +18 -0
- data/test/fixtures/user/getUser.single.withProfile.json +38 -0
- data/test/fixtures/user/getUser.single.withShops.json +41 -0
- data/test/test_helper.rb +44 -0
- data/test/unit/etsy/address_test.rb +61 -0
- data/test/unit/etsy/basic_client_test.rb +28 -0
- data/test/unit/etsy/category_test.rb +106 -0
- data/test/unit/etsy/country_test.rb +64 -0
- data/test/unit/etsy/image_test.rb +43 -0
- data/test/unit/etsy/listing_test.rb +217 -0
- data/test/unit/etsy/model_test.rb +64 -0
- data/test/unit/etsy/payment_template_test.rb +68 -0
- data/test/unit/etsy/profile_test.rb +111 -0
- data/test/unit/etsy/request_test.rb +192 -0
- data/test/unit/etsy/response_test.rb +164 -0
- data/test/unit/etsy/section_test.rb +28 -0
- data/test/unit/etsy/secure_client_test.rb +132 -0
- data/test/unit/etsy/shipping_template_test.rb +24 -0
- data/test/unit/etsy/shop_test.rb +104 -0
- data/test/unit/etsy/transaction_test.rb +52 -0
- data/test/unit/etsy/user_test.rb +218 -0
- data/test/unit/etsy/verification_request_test.rb +26 -0
- data/test/unit/etsy_test.rb +114 -0
- metadata +269 -0
data/lib/etsy/address.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
module Etsy
|
2
|
+
|
3
|
+
# = Address
|
4
|
+
#
|
5
|
+
# Represents a single Etsy Address. Users may or may not have associated addresses.
|
6
|
+
#
|
7
|
+
# An address has the following attributes:
|
8
|
+
#
|
9
|
+
# [first_line] Street address
|
10
|
+
# [second_line] Additional street information.
|
11
|
+
# [city]
|
12
|
+
# [state]
|
13
|
+
# [country]
|
14
|
+
# [country_id] The Etsy country id
|
15
|
+
#
|
16
|
+
class Address
|
17
|
+
|
18
|
+
include Etsy::Model
|
19
|
+
|
20
|
+
attributes :name, :first_line, :second_line, :city, :state, :zip, :country_id
|
21
|
+
|
22
|
+
attribute :id, :from => :user_address_id
|
23
|
+
attribute :country, :from => :country_name
|
24
|
+
|
25
|
+
# Retrieve all of a user's addresses by user name or ID:
|
26
|
+
#
|
27
|
+
# Etsy::Address.find('reagent')
|
28
|
+
#
|
29
|
+
def self.find(*identifiers_and_options)
|
30
|
+
self.append_to_endpoint('addresses', identifiers_and_options)
|
31
|
+
self.find_one_or_more('users', identifiers_and_options)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def oauth
|
36
|
+
oauth = (token && secret) ? {:access_token => token, :access_secret => secret} : {}
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.append_to_endpoint(suffix, arguments)
|
40
|
+
if arguments.last.class == Hash
|
41
|
+
arguments.last[:append_to_endpoint] = suffix
|
42
|
+
else
|
43
|
+
arguments << {:append_to_endpoint => suffix}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Etsy
|
2
|
+
|
3
|
+
# = BasicClient
|
4
|
+
#
|
5
|
+
# Used for calling public API methods.
|
6
|
+
#
|
7
|
+
class BasicClient
|
8
|
+
|
9
|
+
# Create a new client that will connect to the specified host
|
10
|
+
#
|
11
|
+
def initialize(host)
|
12
|
+
@host = host
|
13
|
+
end
|
14
|
+
|
15
|
+
def client # :nodoc:
|
16
|
+
@client ||= Net::HTTP.new(@host)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Fetch a raw response from the specified endpoint
|
20
|
+
#
|
21
|
+
def get(endpoint)
|
22
|
+
client.get(endpoint)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Etsy
|
2
|
+
|
3
|
+
# = Category
|
4
|
+
#
|
5
|
+
# A category of listings for sale, formed from 1 to 3 tags.
|
6
|
+
#
|
7
|
+
# A category has the following attributes:
|
8
|
+
#
|
9
|
+
# [page_description] A short description of the category from the category's landing page
|
10
|
+
# [page_title] The title of the category's landing page
|
11
|
+
# [category_name] The category's string ID
|
12
|
+
# [short_name] A short display name for the category
|
13
|
+
# [long_name] A longer display name for the category
|
14
|
+
# [children_count] The number of subcategories below this one
|
15
|
+
#
|
16
|
+
class Category
|
17
|
+
|
18
|
+
include Etsy::Model
|
19
|
+
|
20
|
+
attribute :id, :from => :category_id
|
21
|
+
attribute :children_count, :from => :num_children
|
22
|
+
attributes :page_description, :page_title, :category_name, :short_name,
|
23
|
+
:long_name
|
24
|
+
|
25
|
+
# Retrieve one or more top-level categories by name:
|
26
|
+
#
|
27
|
+
# Etsy::Category.find('accessories')
|
28
|
+
#
|
29
|
+
# You can find multiple top-level categories by passing an array of identifiers:
|
30
|
+
#
|
31
|
+
# Etsy::Category.find(['accessories', 'art'])
|
32
|
+
#
|
33
|
+
def self.find_top(*identifiers_and_options)
|
34
|
+
self.find_one_or_more('categories', identifiers_and_options)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Retrieve a list of all subcategories of the specified category.
|
38
|
+
#
|
39
|
+
# Etsy::Category.find_all_subcategories('accessories')
|
40
|
+
#
|
41
|
+
# You can also find the subcategories of a subcategory.
|
42
|
+
#
|
43
|
+
# Etsy::Category.find_all_subcategories('accessories/apron')
|
44
|
+
#
|
45
|
+
# Etsy categories only go three levels deep, so this will return nil past the third level.
|
46
|
+
#
|
47
|
+
# Etsy::Category.find_all_subcategories('accessories/apron/women')
|
48
|
+
# => nil
|
49
|
+
#
|
50
|
+
def self.find_all_subcategories(category, options = {})
|
51
|
+
valid?(category) ? self.get_all("/taxonomy/categories/#{category}", options) : nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.find(tag)
|
55
|
+
get("/categories/#{tag}")
|
56
|
+
end
|
57
|
+
|
58
|
+
# Retrieve a list of all top-level categories.
|
59
|
+
#
|
60
|
+
# Etsy::Category.all
|
61
|
+
#
|
62
|
+
def self.all_top(options = {})
|
63
|
+
self.get_all("/taxonomy/categories", options)
|
64
|
+
end
|
65
|
+
|
66
|
+
# The collection of active listings associated with this category.
|
67
|
+
#
|
68
|
+
def active_listings
|
69
|
+
@active_listings ||= Listing.find_all_active_by_category(category_name)
|
70
|
+
end
|
71
|
+
|
72
|
+
# The collection of subcategories associated with this category.
|
73
|
+
#
|
74
|
+
def subcategories
|
75
|
+
@subcategories ||= Category.find_all_subcategories(category_name)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def self.valid?(parent_category)
|
81
|
+
parent_category.count("/") < 2
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/etsy/country.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Etsy
|
2
|
+
class Country
|
3
|
+
include Etsy::Model
|
4
|
+
|
5
|
+
attribute :id, :from => :country_id
|
6
|
+
attributes :iso_country_code, :world_bank_country_code
|
7
|
+
attributes :name, :slug, :lat, :lon
|
8
|
+
|
9
|
+
def self.find_all
|
10
|
+
get("/countries")
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.find(id)
|
14
|
+
get("/countries/#{id}")
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.find_by_alpha2(alpha2)
|
18
|
+
alpha2 = alpha2.upcase
|
19
|
+
find_all.detect { |country| country.iso_country_code == alpha2}
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.find_by_world_bank_country_code(world_bank_country_code)
|
23
|
+
world_bank_country_code = world_bank_country_code.upcase
|
24
|
+
find_all.detect { |country| country.world_bank_country_code == world_bank_country_code}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/etsy/image.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Etsy
|
2
|
+
|
3
|
+
# = Image
|
4
|
+
#
|
5
|
+
# Represents an image resource of an Etsy listing and contains multiple sizes.
|
6
|
+
# Sizes available are:
|
7
|
+
#
|
8
|
+
# [square] The square image thumbnail (75x75 pixels)
|
9
|
+
# [small] The small image thumbnail (170x135 pixels)
|
10
|
+
# [thumbnail] The thumbnail for the image, no more than 570px wide
|
11
|
+
# [full] The full image for this listing, no more than 1500px wide
|
12
|
+
#
|
13
|
+
class Image
|
14
|
+
|
15
|
+
include Etsy::Model
|
16
|
+
|
17
|
+
attribute :square, :from => :url_75x75
|
18
|
+
attribute :small, :from => :url_170x135
|
19
|
+
attribute :thumbnail, :from => :url_570xN
|
20
|
+
attribute :full, :from => :url_fullxfull
|
21
|
+
|
22
|
+
# Fetch all images for a given listing.
|
23
|
+
#
|
24
|
+
def self.find_all_by_listing_id(listing_id)
|
25
|
+
get_all("/listings/#{listing_id}/images")
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.create(listing, image_path, options = {})
|
29
|
+
options[:image] = File.new(image_path)
|
30
|
+
options[:multipart] = true
|
31
|
+
post("/listings/#{listing.id}/images", options)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/etsy/listing.rb
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
module Etsy
|
2
|
+
|
3
|
+
# = Listing
|
4
|
+
#
|
5
|
+
# Represents a single Etsy listing. Has the following attributes:
|
6
|
+
#
|
7
|
+
# [id] The unique identifier for this listing
|
8
|
+
# [title] The title of this listing
|
9
|
+
# [description] This listing's full description
|
10
|
+
# [view_count] The number of times this listing has been viewed
|
11
|
+
# [url] The full URL to this listing's detail page
|
12
|
+
# [price] The price of this listing item
|
13
|
+
# [currency] The currency that the seller is using for this listing item
|
14
|
+
# [quantity] The number of items available for sale
|
15
|
+
# [tags] An array of tags that the seller has used for this listing
|
16
|
+
# [materials] Any array of materials that was used in the production of this item
|
17
|
+
# [state] The current state of the item
|
18
|
+
# [hue] The hue of the listing's primary image (HSV color).
|
19
|
+
# [saturation] The saturation of the listing's primary image (HSV color).
|
20
|
+
# [brightness] The value of the listing's primary image (HSV color).
|
21
|
+
# [black_and_white?] True if the listing's primary image is in black & white.
|
22
|
+
#
|
23
|
+
# Additionally, the following queries on this item are available:
|
24
|
+
#
|
25
|
+
# [active?] Is this listing active?
|
26
|
+
# [removed?] Has this listing been removed?
|
27
|
+
# [sold_out?] Is this listing sold out?
|
28
|
+
# [expired?] Has this listing expired?
|
29
|
+
# [alchemy?] Is this listing an Alchemy item? (i.e. requested by an Etsy user)
|
30
|
+
#
|
31
|
+
class Listing
|
32
|
+
|
33
|
+
include Etsy::Model
|
34
|
+
|
35
|
+
STATES = %w(active removed sold_out expired alchemy)
|
36
|
+
VALID_STATES = [:active, :expired, :inactive, :sold, :featured]
|
37
|
+
|
38
|
+
attribute :id, :from => :listing_id
|
39
|
+
attribute :view_count, :from => :views
|
40
|
+
attribute :created, :from => :creation_tsz
|
41
|
+
attribute :modified, :from => :last_modified_tsz
|
42
|
+
attribute :currency, :from => :currency_code
|
43
|
+
attribute :ending, :from => :ending_tsz
|
44
|
+
|
45
|
+
attributes :title, :description, :state, :url, :price, :quantity,
|
46
|
+
:tags, :materials, :hue, :saturation, :brightness, :is_black_and_white
|
47
|
+
|
48
|
+
association :image, :from => 'Images'
|
49
|
+
|
50
|
+
def self.create(options = {})
|
51
|
+
options.merge!(:require_secure => true)
|
52
|
+
post("/listings", options)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.update(listing, options = {})
|
56
|
+
options.merge!(:require_secure => true)
|
57
|
+
put("/listings/#{listing.id}", options)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Retrieve one or more listings by ID:
|
61
|
+
#
|
62
|
+
# Etsy::Listing.find(123)
|
63
|
+
#
|
64
|
+
# You can find multiple listings by passing an array of identifiers:
|
65
|
+
#
|
66
|
+
# Etsy::Listing.find([123, 456])
|
67
|
+
#
|
68
|
+
def self.find(*identifiers_and_options)
|
69
|
+
find_one_or_more('listings', identifiers_and_options)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Retrieve listings for a given shop.
|
73
|
+
# By default, pulls back the first 25 active listings.
|
74
|
+
# Defaults can be overridden using :limit, :offset, and :state
|
75
|
+
#
|
76
|
+
# Available states are :active, :expired, :inactive, :sold, and :featured
|
77
|
+
# where :featured is a subset of the others.
|
78
|
+
#
|
79
|
+
# options = {
|
80
|
+
# :state => :expired,
|
81
|
+
# :limit => 100,
|
82
|
+
# :offset => 100,
|
83
|
+
# :token => 'toke',
|
84
|
+
# :secret => 'secret'
|
85
|
+
# }
|
86
|
+
# Etsy::Listing.find_all_by_shop_id(123, options)
|
87
|
+
#
|
88
|
+
def self.find_all_by_shop_id(shop_id, options = {})
|
89
|
+
state = options.delete(:state) || :active
|
90
|
+
|
91
|
+
raise(ArgumentError, self.invalid_state_message(state)) unless valid?(state)
|
92
|
+
|
93
|
+
if state == :sold
|
94
|
+
sold_listings(shop_id, options)
|
95
|
+
else
|
96
|
+
get_all("/shops/#{shop_id}/listings/#{state}", options)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Retrieve active listings for a given category.
|
101
|
+
# By default, pulls back the first 25 active listings.
|
102
|
+
# Defaults can be overridden using :limit, :offset, and :state
|
103
|
+
#
|
104
|
+
# options = {
|
105
|
+
# :limit => 25,
|
106
|
+
# :offset => 100,
|
107
|
+
# :token => 'toke',
|
108
|
+
# :secret => 'secret'
|
109
|
+
# }
|
110
|
+
# Etsy::Listing.find_all_active_by_category("accessories", options)
|
111
|
+
#
|
112
|
+
def self.find_all_active_by_category(category, options = {})
|
113
|
+
options[:category] = category
|
114
|
+
get_all("/listings/active", options)
|
115
|
+
end
|
116
|
+
|
117
|
+
# The collection of images associated with this listing.
|
118
|
+
#
|
119
|
+
def images
|
120
|
+
@images ||= Image.find_all_by_listing_id(id)
|
121
|
+
end
|
122
|
+
|
123
|
+
# The primary image for this listing.
|
124
|
+
#
|
125
|
+
def image
|
126
|
+
images.first
|
127
|
+
end
|
128
|
+
|
129
|
+
def black_and_white?
|
130
|
+
is_black_and_white
|
131
|
+
end
|
132
|
+
|
133
|
+
STATES.each do |method_name|
|
134
|
+
define_method "#{method_name}?" do
|
135
|
+
state == method_name.sub('_', '')
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Time that this listing was created
|
140
|
+
#
|
141
|
+
def created_at
|
142
|
+
Time.at(created)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Time that this listing was last modified
|
146
|
+
#
|
147
|
+
def modified_at
|
148
|
+
Time.at(modified)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Time that this listing is ending (will be removed from store)
|
152
|
+
#
|
153
|
+
def ending_at
|
154
|
+
Time.at(ending)
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
def self.valid?(state)
|
160
|
+
VALID_STATES.include?(state)
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.invalid_state_message(state)
|
164
|
+
"The state '#{state}' is invalid. Must be one of #{VALID_STATES.join(', ')}"
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.sold_listings(shop_id, options = {})
|
168
|
+
includes = options.delete(:includes)
|
169
|
+
|
170
|
+
transactions = Transaction.find_all_by_shop_id(shop_id, options)
|
171
|
+
listing_ids = transactions.map {|t| t.listing_id }.uniq
|
172
|
+
|
173
|
+
options = options.merge(:includes => includes) if includes
|
174
|
+
(listing_ids.size > 0) ? Array(find(listing_ids, options)) : []
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
end
|
data/lib/etsy/model.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
module Etsy
|
2
|
+
module Model # :nodoc:all
|
3
|
+
|
4
|
+
module ClassMethods
|
5
|
+
|
6
|
+
def attribute(name, options = {})
|
7
|
+
define_method name do
|
8
|
+
@result[options.fetch(:from, name).to_s]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def attributes(*names)
|
13
|
+
names.each {|name| attribute(name) }
|
14
|
+
end
|
15
|
+
|
16
|
+
# FIXME: not quite sure where I'm going with this yet. KO.
|
17
|
+
def association(name, options = {})
|
18
|
+
define_method "associated_#{name}" do
|
19
|
+
@result[options.fetch(:from, name).to_s]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def get(endpoint, options = {})
|
24
|
+
objects = get_all(endpoint, options)
|
25
|
+
if objects.length == 0
|
26
|
+
nil
|
27
|
+
elsif objects.length == 1
|
28
|
+
objects[0]
|
29
|
+
else
|
30
|
+
objects
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_all(endpoint, options={})
|
35
|
+
limit = options[:limit]
|
36
|
+
|
37
|
+
if limit
|
38
|
+
initial_offset = options.fetch(:offset, 0)
|
39
|
+
batch_size = options.fetch(:batch_size, 100)
|
40
|
+
|
41
|
+
result = []
|
42
|
+
|
43
|
+
if limit == :all
|
44
|
+
response = Request.get(endpoint, options.merge(:limit => batch_size, :offset => initial_offset))
|
45
|
+
result << response.result
|
46
|
+
limit = [response.count - batch_size - initial_offset, 0].max
|
47
|
+
initial_offset += batch_size
|
48
|
+
end
|
49
|
+
|
50
|
+
num_batches = limit / batch_size
|
51
|
+
|
52
|
+
num_batches.times do |batch|
|
53
|
+
total_offset = initial_offset + batch * batch_size
|
54
|
+
response = Request.get(endpoint, options.merge(:limit => batch_size, :offset => total_offset))
|
55
|
+
result << response.result
|
56
|
+
end
|
57
|
+
|
58
|
+
remainder = limit % batch_size
|
59
|
+
|
60
|
+
if remainder > 0
|
61
|
+
total_offset = initial_offset + num_batches * batch_size
|
62
|
+
response = Request.get(endpoint, options.merge(:limit => remainder, :offset => total_offset))
|
63
|
+
result << response.result
|
64
|
+
end
|
65
|
+
else
|
66
|
+
response = Request.get(endpoint, options)
|
67
|
+
result = response.result
|
68
|
+
end
|
69
|
+
|
70
|
+
[result].flatten.map do |data|
|
71
|
+
if options[:access_token] && options[:access_secret]
|
72
|
+
new(data, options[:access_token], options[:access_secret])
|
73
|
+
else
|
74
|
+
new(data)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def post(endpoint, options={})
|
80
|
+
Request.post(endpoint, options)
|
81
|
+
end
|
82
|
+
|
83
|
+
def put(endpoint, options={})
|
84
|
+
Request.put(endpoint, options)
|
85
|
+
end
|
86
|
+
|
87
|
+
def find_one_or_more(endpoint, identifiers_and_options)
|
88
|
+
options = options_from(identifiers_and_options)
|
89
|
+
append = options.delete(:append_to_endpoint)
|
90
|
+
append = append.nil? ? "" : "/#{append}"
|
91
|
+
identifiers = identifiers_and_options
|
92
|
+
get("/#{endpoint}/#{identifiers.join(',')}#{append}", options)
|
93
|
+
end
|
94
|
+
|
95
|
+
def options_from(argument)
|
96
|
+
(argument.last.class == Hash) ? argument.pop : {}
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
def initialize(result = nil, token = nil, secret = nil)
|
102
|
+
@result = result
|
103
|
+
@token = token
|
104
|
+
@secret = secret
|
105
|
+
end
|
106
|
+
|
107
|
+
def token
|
108
|
+
@token
|
109
|
+
end
|
110
|
+
|
111
|
+
def secret
|
112
|
+
@secret
|
113
|
+
end
|
114
|
+
|
115
|
+
def result
|
116
|
+
@result
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.included(other)
|
120
|
+
other.extend ClassMethods
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|