cardmagic-etsy 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +13 -0
- data/Gemfile +11 -0
- data/LICENSE +9 -0
- data/README.md +348 -0
- data/Rakefile +12 -0
- data/etsy.gemspec +34 -0
- data/lib/etsy.rb +223 -0
- data/lib/etsy/about.rb +15 -0
- data/lib/etsy/address.rb +47 -0
- data/lib/etsy/attribute_value.rb +46 -0
- data/lib/etsy/basic_client.rb +32 -0
- data/lib/etsy/category.rb +84 -0
- data/lib/etsy/country.rb +27 -0
- data/lib/etsy/favorite_listing.rb +26 -0
- data/lib/etsy/image.rb +44 -0
- data/lib/etsy/listing.rb +296 -0
- data/lib/etsy/model.rb +127 -0
- data/lib/etsy/payment_template.rb +33 -0
- data/lib/etsy/profile.rb +49 -0
- data/lib/etsy/receipt.rb +37 -0
- data/lib/etsy/request.rb +150 -0
- data/lib/etsy/response.rb +128 -0
- data/lib/etsy/section.rb +16 -0
- data/lib/etsy/secure_client.rb +131 -0
- data/lib/etsy/shipping_info.rb +27 -0
- data/lib/etsy/shipping_template.rb +41 -0
- data/lib/etsy/shop.rb +88 -0
- data/lib/etsy/transaction.rb +29 -0
- data/lib/etsy/user.rb +109 -0
- data/lib/etsy/variation/property_set.rb +71 -0
- data/lib/etsy/verification_request.rb +17 -0
- data/lib/etsy/version.rb +3 -0
- data/test/fixtures/about/getAbout.json +16 -0
- data/test/fixtures/address/getUserAddresses.json +12 -0
- data/test/fixtures/attribute_value/findAllListingPropertyValues.json +44 -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/favorite_listing/findAllFavoriteListings.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.includeImages.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/receipt/findAllShopReceipts.json +28 -0
- data/test/fixtures/section/getShopSection.json +18 -0
- data/test/fixtures/shipping_info/getShippingInfo.json +1 -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 +34 -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 +45 -0
- data/test/unit/etsy/address_test.rb +61 -0
- data/test/unit/etsy/attribute_value_test.rb +67 -0
- data/test/unit/etsy/basic_client_test.rb +30 -0
- data/test/unit/etsy/category_test.rb +106 -0
- data/test/unit/etsy/country_test.rb +64 -0
- data/test/unit/etsy/favorite_listing_test.rb +44 -0
- data/test/unit/etsy/image_test.rb +51 -0
- data/test/unit/etsy/listing_test.rb +268 -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/receipt_test.rb +107 -0
- data/test/unit/etsy/request_test.rb +190 -0
- data/test/unit/etsy/response_test.rb +175 -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_info_test.rb +24 -0
- data/test/unit/etsy/shipping_template_test.rb +24 -0
- data/test/unit/etsy/shop_about_test.rb +43 -0
- data/test/unit/etsy/shop_test.rb +116 -0
- data/test/unit/etsy/transaction_test.rb +61 -0
- data/test/unit/etsy/user_test.rb +250 -0
- data/test/unit/etsy/verification_request_test.rb +26 -0
- data/test/unit/etsy_test.rb +173 -0
- metadata +293 -0
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
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Etsy
|
2
|
+
class FavoriteListing
|
3
|
+
include Model
|
4
|
+
|
5
|
+
attributes :user_id, :listing_state, :listing_id, :create_date
|
6
|
+
|
7
|
+
#Create a new favorite listing
|
8
|
+
#
|
9
|
+
def self.create(user, listing, options = {})
|
10
|
+
options.merge!(:require_secure => true)
|
11
|
+
post("/users/#{user.id}/favorites/listings/#{listing.id}", options)
|
12
|
+
end
|
13
|
+
|
14
|
+
#Find all listings favorited by a user
|
15
|
+
#
|
16
|
+
def self.find_all_user_favorite_listings(user_id, options = {})
|
17
|
+
get_all("/users/#{user_id}/favorites/listings", options)
|
18
|
+
end
|
19
|
+
|
20
|
+
#Find a set of favorelistings associated with a listing_id
|
21
|
+
#
|
22
|
+
def self.find_all_listings_favored_by(listing_id, options = {})
|
23
|
+
get_all("/listings/#{listing_id}/favored-by", options)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/etsy/image.rb
ADDED
@@ -0,0 +1,44 @@
|
|
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 :height, :from => :full_height
|
21
|
+
attribute :width, :from => :full_width
|
22
|
+
attribute :full, :from => :url_fullxfull
|
23
|
+
|
24
|
+
# Fetch all images for a given listing.
|
25
|
+
#
|
26
|
+
def self.find_all_by_listing_id(listing_id, options = {})
|
27
|
+
get_all("/listings/#{listing_id}/images", options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.create(listing, image_path, options = {})
|
31
|
+
options.merge!(:require_secure => true)
|
32
|
+
options[:image] = File.new(image_path)
|
33
|
+
options[:multipart] = true
|
34
|
+
post("/listings/#{listing.id}/images", options)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Delete image
|
38
|
+
#
|
39
|
+
def self.destroy(listing, image, options = {})
|
40
|
+
options.merge!(:require_secure => true)
|
41
|
+
delete("/listings/#{listing.id}/images/#{image.id}", options)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/etsy/listing.rb
ADDED
@@ -0,0 +1,296 @@
|
|
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, :draft, :sold_out]
|
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
|
+
attribute :shop_section, :from => :shop_section_id
|
45
|
+
|
46
|
+
attributes :title, :description, :state, :url, :price, :quantity,
|
47
|
+
:tags, :materials, :hue, :saturation, :brightness, :is_black_and_white,
|
48
|
+
:featured_rank, :occasion, :num_favorers, :user_id,
|
49
|
+
:shipping_template_id, :who_made, :when_made,
|
50
|
+
:original_creation_tsz, :style, :category_path,
|
51
|
+
:taxonomy_id, :taxonomy_attributes
|
52
|
+
|
53
|
+
association :image, :from => 'Images'
|
54
|
+
|
55
|
+
def self.create(options = {})
|
56
|
+
options.merge!(:require_secure => true)
|
57
|
+
post("/listings", options)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.update(listing, options = {})
|
61
|
+
options.merge!(:require_secure => true)
|
62
|
+
put("/listings/#{listing.id}", options)
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.destroy(listing, options = {})
|
66
|
+
options.merge!(:require_secure => true)
|
67
|
+
delete("/listings/#{listing.id}", options)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Retrieve one or more listings by ID:
|
71
|
+
#
|
72
|
+
# Etsy::Listing.find(123)
|
73
|
+
#
|
74
|
+
# You can find multiple listings by passing an array of identifiers:
|
75
|
+
#
|
76
|
+
# Etsy::Listing.find([123, 456])
|
77
|
+
#
|
78
|
+
def self.find(*identifiers_and_options)
|
79
|
+
find_one_or_more('listings', identifiers_and_options)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Retrieve listings for a given shop.
|
83
|
+
# By default, pulls back the first 25 active listings.
|
84
|
+
# Defaults can be overridden using :limit, :offset, and :state
|
85
|
+
#
|
86
|
+
# Available states are :active, :expired, :inactive, :sold, and :featured, :draft, :sold_out
|
87
|
+
# where :featured is a subset of the others.
|
88
|
+
#
|
89
|
+
# options = {
|
90
|
+
# :state => :expired,
|
91
|
+
# :limit => 100,
|
92
|
+
# :offset => 100,
|
93
|
+
# :token => 'toke',
|
94
|
+
# :secret => 'secret'
|
95
|
+
# }
|
96
|
+
# Etsy::Listing.find_all_by_shop_id(123, options)
|
97
|
+
#
|
98
|
+
def self.find_all_by_shop_id(shop_id, options = {})
|
99
|
+
state = options.delete(:state) || :active
|
100
|
+
|
101
|
+
raise(ArgumentError, self.invalid_state_message(state)) unless valid?(state)
|
102
|
+
|
103
|
+
if state == :sold
|
104
|
+
sold_listings(shop_id, options)
|
105
|
+
else
|
106
|
+
get_all("/shops/#{shop_id}/listings/#{state}", options)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Retrieve active listings for a given category.
|
111
|
+
# By default, pulls back the first 25 active listings.
|
112
|
+
# Defaults can be overridden using :limit, :offset, and :state
|
113
|
+
#
|
114
|
+
# options = {
|
115
|
+
# :limit => 25,
|
116
|
+
# :offset => 100,
|
117
|
+
# :token => 'toke',
|
118
|
+
# :secret => 'secret'
|
119
|
+
# }
|
120
|
+
# Etsy::Listing.find_all_active_by_category("accessories", options)
|
121
|
+
#
|
122
|
+
def self.find_all_active_by_category(category, options = {})
|
123
|
+
options[:category] = category
|
124
|
+
get_all("/listings/active", options)
|
125
|
+
end
|
126
|
+
|
127
|
+
# The collection of images associated with this listing.
|
128
|
+
#
|
129
|
+
def images
|
130
|
+
@images ||= listing_images
|
131
|
+
end
|
132
|
+
|
133
|
+
# The primary image for this listing.
|
134
|
+
#
|
135
|
+
def image
|
136
|
+
images.first
|
137
|
+
end
|
138
|
+
|
139
|
+
# Listing category name
|
140
|
+
#
|
141
|
+
def category
|
142
|
+
path = category_path.join('/')
|
143
|
+
@category ||= Category.find(path)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Returns the taxonomy defined attributes for the listing
|
147
|
+
#
|
148
|
+
def taxonomy_attributes(options={})
|
149
|
+
options.merge!(:require_secure => true)
|
150
|
+
self.class.get_all("/listings/#{id}/attributes", oauth.merge(options))
|
151
|
+
end
|
152
|
+
|
153
|
+
def variations(options={})
|
154
|
+
options.merge!(:require_secure => true)
|
155
|
+
self.class.get_all("/listings/#{id}/variations", oauth.merge(options))
|
156
|
+
end
|
157
|
+
|
158
|
+
# If these are your desired variations:
|
159
|
+
# - Dimensions: 1 x 2 inches
|
160
|
+
# - Dimensions: 2 x 4 inches
|
161
|
+
#
|
162
|
+
# Then you first have to find the property ID of the property you want to vary. Eg:
|
163
|
+
# Etsy::Variation::PropertySet.find_property_by_name("Dimensions").fetch("property_id")
|
164
|
+
#
|
165
|
+
# Then you can decide which options you want to set for this property.
|
166
|
+
# Eg:
|
167
|
+
# Etsy::Variation::PropertySet.qualifying_properties_for_property("Dimension")
|
168
|
+
# => [{
|
169
|
+
# "param"=>"dimensions_scale",
|
170
|
+
# "description"=>"Sizing Scale",
|
171
|
+
# "options"=>{
|
172
|
+
# "Inches" => 344,
|
173
|
+
# "Centimeters" => 345,
|
174
|
+
# "Other" => 346
|
175
|
+
# }
|
176
|
+
# }]
|
177
|
+
#
|
178
|
+
# Put it all together for a call to add_variations:
|
179
|
+
|
180
|
+
# property_id = Etsy::Variation::PropertySet.find_property_by_name("Dimensions").fetch("property_id")
|
181
|
+
# scale = Etsy::Variation::PropertySet.qualifying_properties_for_property("Dimensions").detect {|qp| qp.fetch("description") == "Sizing Scale"}
|
182
|
+
# my_listing.add_variations(
|
183
|
+
# :variations => [
|
184
|
+
# {"property_id" => property_id, "value" => "1 x 2", "is_available" => true, "price" => 1.23},
|
185
|
+
# {"property_id" => property_id, "value" => "2 x 4", "is_available" => true, "price" => 2.34}
|
186
|
+
# ],
|
187
|
+
# scale.fetch("param") => scale.fetch("options").fetch("Inches")
|
188
|
+
# )
|
189
|
+
def add_variations(options)
|
190
|
+
options[:variations] = JSON.dump(options.delete(:variations))
|
191
|
+
options[:require_secure] = true
|
192
|
+
self.class.post("/listings/#{id}/variations", options)
|
193
|
+
end
|
194
|
+
|
195
|
+
def update_variations(options)
|
196
|
+
options[:variations] = JSON.dump(options.delete(:variations))
|
197
|
+
options[:require_secure] = true
|
198
|
+
self.class.put("/listings/#{id}/variations", options)
|
199
|
+
end
|
200
|
+
|
201
|
+
def black_and_white?
|
202
|
+
is_black_and_white
|
203
|
+
end
|
204
|
+
|
205
|
+
STATES.each do |method_name|
|
206
|
+
define_method "#{method_name}?" do
|
207
|
+
state == method_name.sub('_', '')
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Time that this listing was created
|
212
|
+
#
|
213
|
+
def created_at
|
214
|
+
Time.at(created)
|
215
|
+
end
|
216
|
+
|
217
|
+
# Time that this listing was last modified
|
218
|
+
#
|
219
|
+
def modified_at
|
220
|
+
Time.at(modified)
|
221
|
+
end
|
222
|
+
|
223
|
+
# Time that this listing is ending (will be removed from store)
|
224
|
+
#
|
225
|
+
def ending_at
|
226
|
+
Time.at(ending)
|
227
|
+
end
|
228
|
+
|
229
|
+
#Return a list of users who have favorited this listing
|
230
|
+
#
|
231
|
+
def admirers(options = {})
|
232
|
+
options = options.merge(:access_token => token, :access_secret => secret) if (token && secret)
|
233
|
+
favorite_listings = FavoriteListing.find_all_listings_favored_by(id, options)
|
234
|
+
user_ids = favorite_listings.map {|f| f.user_id }.uniq
|
235
|
+
(user_ids.size > 0) ? Array(Etsy::User.find(user_ids, options)) : []
|
236
|
+
end
|
237
|
+
|
238
|
+
def is_supply
|
239
|
+
!!@result.fetch("is_supply")
|
240
|
+
end
|
241
|
+
|
242
|
+
private
|
243
|
+
|
244
|
+
def self.valid?(state)
|
245
|
+
VALID_STATES.include?(state)
|
246
|
+
end
|
247
|
+
|
248
|
+
def self.invalid_state_message(state)
|
249
|
+
"The state '#{state}' is invalid. Must be one of #{VALID_STATES.join(', ')}"
|
250
|
+
end
|
251
|
+
|
252
|
+
def self.sold_listings(shop_id, options = {})
|
253
|
+
includes = options.delete(:includes)
|
254
|
+
|
255
|
+
transactions = Transaction.find_all_by_shop_id(shop_id, options)
|
256
|
+
listing_ids = transactions.map {|t| t.listing_id }.uniq
|
257
|
+
|
258
|
+
options = options.merge(:includes => includes) if includes
|
259
|
+
(listing_ids.size > 0) ? Array(find(listing_ids, options)) : []
|
260
|
+
end
|
261
|
+
|
262
|
+
#Find all listings favored by a user
|
263
|
+
#
|
264
|
+
def self.find_all_user_favorite_listings(user_id, options = {})
|
265
|
+
favorite_listings = FavoriteListing.find_all_user_favorite_listings(user_id, options)
|
266
|
+
listing_ids = favorite_listings.map {|f| f.listing_id }.uniq
|
267
|
+
(listing_ids.size > 0) ? Array(find(listing_ids, options)) : []
|
268
|
+
end
|
269
|
+
|
270
|
+
#Find all listings that have been bought by a user
|
271
|
+
#
|
272
|
+
def self.bought_listings(user_id, options = {})
|
273
|
+
includes = options.delete(:includes)
|
274
|
+
|
275
|
+
transactions = Transaction.find_all_by_buyer_id(user_id, options)
|
276
|
+
listing_ids = transactions.map {|t| t.listing_id }.uniq
|
277
|
+
|
278
|
+
options = options.merge(:includes => includes) if includes
|
279
|
+
(listing_ids.size > 0) ? Array(find(listing_ids, options)) : []
|
280
|
+
end
|
281
|
+
|
282
|
+
private
|
283
|
+
|
284
|
+
def oauth
|
285
|
+
oauth = (token && secret) ? {:access_token => token, :access_secret => secret} : {}
|
286
|
+
end
|
287
|
+
|
288
|
+
def listing_images
|
289
|
+
if result && result["Images"]
|
290
|
+
result["Images"].map { |hash| Image.new(hash) }
|
291
|
+
else
|
292
|
+
Image.find_all_by_listing_id(id, oauth)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
data/lib/etsy/model.rb
ADDED
@@ -0,0 +1,127 @@
|
|
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.total - 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 delete(endpoint, options={})
|
88
|
+
Request.delete(endpoint, options)
|
89
|
+
end
|
90
|
+
|
91
|
+
def find_one_or_more(endpoint, identifiers_and_options)
|
92
|
+
options = options_from(identifiers_and_options)
|
93
|
+
append = options.delete(:append_to_endpoint)
|
94
|
+
append = append.nil? ? "" : "/#{append}"
|
95
|
+
identifiers = identifiers_and_options
|
96
|
+
get("/#{endpoint}/#{identifiers.join(',')}#{append}", options)
|
97
|
+
end
|
98
|
+
|
99
|
+
def options_from(argument)
|
100
|
+
(argument.last.class == Hash) ? argument.pop : {}
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
def initialize(result = nil, token = nil, secret = nil)
|
106
|
+
@result = result
|
107
|
+
@token = token
|
108
|
+
@secret = secret
|
109
|
+
end
|
110
|
+
|
111
|
+
def token
|
112
|
+
@token
|
113
|
+
end
|
114
|
+
|
115
|
+
def secret
|
116
|
+
@secret
|
117
|
+
end
|
118
|
+
|
119
|
+
def result
|
120
|
+
@result
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.included(other)
|
124
|
+
other.extend ClassMethods
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|