latompa-fleakr 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +350 -0
- data/Rakefile +41 -0
- data/lib/fleakr/api/file_parameter.rb +47 -0
- data/lib/fleakr/api/method_request.rb +66 -0
- data/lib/fleakr/api/option.rb +175 -0
- data/lib/fleakr/api/parameter.rb +35 -0
- data/lib/fleakr/api/parameter_list.rb +97 -0
- data/lib/fleakr/api/response.rb +35 -0
- data/lib/fleakr/api/upload_request.rb +75 -0
- data/lib/fleakr/api/value_parameter.rb +36 -0
- data/lib/fleakr/api.rb +8 -0
- data/lib/fleakr/core_ext/false_class.rb +7 -0
- data/lib/fleakr/core_ext/hash.rb +22 -0
- data/lib/fleakr/core_ext/true_class.rb +7 -0
- data/lib/fleakr/core_ext.rb +3 -0
- data/lib/fleakr/objects/authentication_token.rb +60 -0
- data/lib/fleakr/objects/comment.rb +49 -0
- data/lib/fleakr/objects/contact.rb +37 -0
- data/lib/fleakr/objects/error.rb +22 -0
- data/lib/fleakr/objects/group.rb +36 -0
- data/lib/fleakr/objects/image.rb +50 -0
- data/lib/fleakr/objects/photo.rb +148 -0
- data/lib/fleakr/objects/photo_context.rb +49 -0
- data/lib/fleakr/objects/search.rb +30 -0
- data/lib/fleakr/objects/set.rb +50 -0
- data/lib/fleakr/objects/tag.rb +56 -0
- data/lib/fleakr/objects/user.rb +95 -0
- data/lib/fleakr/objects.rb +12 -0
- data/lib/fleakr/support/attribute.rb +46 -0
- data/lib/fleakr/support/object.rb +110 -0
- data/lib/fleakr/support.rb +2 -0
- data/lib/fleakr/version.rb +13 -0
- data/lib/fleakr.rb +171 -0
- data/test/fixtures/auth.checkToken.xml +8 -0
- data/test/fixtures/auth.getFullToken.xml +8 -0
- data/test/fixtures/auth.getToken.xml +8 -0
- data/test/fixtures/contacts.getPublicList.xml +7 -0
- data/test/fixtures/groups.pools.getPhotos.xml +7 -0
- data/test/fixtures/people.findByEmail.xml +6 -0
- data/test/fixtures/people.findByUsername.xml +6 -0
- data/test/fixtures/people.getInfo.xml +18 -0
- data/test/fixtures/people.getPublicGroups.xml +7 -0
- data/test/fixtures/people.getPublicPhotos.xml +7 -0
- data/test/fixtures/photos.comments.getList.xml +7 -0
- data/test/fixtures/photos.getContext.xml +6 -0
- data/test/fixtures/photos.getInfo.xml +20 -0
- data/test/fixtures/photos.getSizes.xml +10 -0
- data/test/fixtures/photos.search.xml +7 -0
- data/test/fixtures/photosets.comments.getList.xml +7 -0
- data/test/fixtures/photosets.getList.xml +13 -0
- data/test/fixtures/photosets.getPhotos.xml +7 -0
- data/test/fixtures/tags.getListPhoto.xml +9 -0
- data/test/fixtures/tags.getListUser.xml +10 -0
- data/test/fixtures/tags.getRelated.xml +9 -0
- data/test/test_helper.rb +141 -0
- data/test/unit/fleakr/api/file_parameter_test.rb +63 -0
- data/test/unit/fleakr/api/method_request_test.rb +94 -0
- data/test/unit/fleakr/api/option_test.rb +179 -0
- data/test/unit/fleakr/api/parameter_list_test.rb +176 -0
- data/test/unit/fleakr/api/parameter_test.rb +34 -0
- data/test/unit/fleakr/api/response_test.rb +49 -0
- data/test/unit/fleakr/api/upload_request_test.rb +149 -0
- data/test/unit/fleakr/api/value_parameter_test.rb +41 -0
- data/test/unit/fleakr/core_ext/false_class_test.rb +13 -0
- data/test/unit/fleakr/core_ext/hash_test.rb +32 -0
- data/test/unit/fleakr/core_ext/true_class_test.rb +13 -0
- data/test/unit/fleakr/objects/authentication_token_test.rb +61 -0
- data/test/unit/fleakr/objects/comment_test.rb +66 -0
- data/test/unit/fleakr/objects/contact_test.rb +70 -0
- data/test/unit/fleakr/objects/error_test.rb +21 -0
- data/test/unit/fleakr/objects/group_test.rb +46 -0
- data/test/unit/fleakr/objects/image_test.rb +81 -0
- data/test/unit/fleakr/objects/photo_context_test.rb +80 -0
- data/test/unit/fleakr/objects/photo_test.rb +247 -0
- data/test/unit/fleakr/objects/search_test.rb +74 -0
- data/test/unit/fleakr/objects/set_test.rb +82 -0
- data/test/unit/fleakr/objects/tag_test.rb +98 -0
- data/test/unit/fleakr/objects/user_test.rb +91 -0
- data/test/unit/fleakr/support/attribute_test.rb +126 -0
- data/test/unit/fleakr/support/object_test.rb +129 -0
- data/test/unit/fleakr_test.rb +171 -0
- metadata +175 -0
data/lib/fleakr.rb
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
require 'uri'
|
5
|
+
require 'cgi'
|
6
|
+
require 'net/http'
|
7
|
+
require 'hpricot'
|
8
|
+
require 'forwardable'
|
9
|
+
|
10
|
+
# Require only what we need from ActiveSupport
|
11
|
+
require 'active_support/core_ext/array'
|
12
|
+
require 'active_support/core_ext/module'
|
13
|
+
require 'active_support/core_ext/blank'
|
14
|
+
require 'active_support/core_ext/time'
|
15
|
+
require 'active_support/inflector'
|
16
|
+
require 'active_support/core_ext/string'
|
17
|
+
|
18
|
+
require 'digest/md5'
|
19
|
+
require 'fileutils'
|
20
|
+
require 'loggable'
|
21
|
+
|
22
|
+
require 'fleakr/api'
|
23
|
+
require 'fleakr/core_ext'
|
24
|
+
require 'fleakr/support'
|
25
|
+
require 'fleakr/objects'
|
26
|
+
|
27
|
+
# = Fleakr: A small, yet powerful, gem to interface with Flickr photostreams
|
28
|
+
#
|
29
|
+
# == Quick Start
|
30
|
+
#
|
31
|
+
# Getting started is easy, just make sure you have a valid API key from Flickr and you can
|
32
|
+
# then start making any non-authenticated request to pull back data for yours and others'
|
33
|
+
# photostreams, sets, contacts, groups, etc...
|
34
|
+
#
|
35
|
+
# For now, all activity originates from a single user which you can find by username or
|
36
|
+
# email address.
|
37
|
+
#
|
38
|
+
# Example:
|
39
|
+
#
|
40
|
+
# require 'rubygems'
|
41
|
+
# require 'fleakr'
|
42
|
+
#
|
43
|
+
# # Our API key is ABC123 (http://www.flickr.com/services/api/keys/apply/)
|
44
|
+
# Fleakr.api_key = 'ABC123'
|
45
|
+
# user = Fleakr.user('bees')
|
46
|
+
# user = Fleakr.user('user@host.com')
|
47
|
+
# # Grab a list of sets
|
48
|
+
# user.sets
|
49
|
+
# # Grab a list of the user's public groups
|
50
|
+
# user.groups
|
51
|
+
#
|
52
|
+
# To see what other associations and attributes are available, see the Fleakr::Objects::User class
|
53
|
+
#
|
54
|
+
# == Authentication
|
55
|
+
#
|
56
|
+
# If you want to do something more than just retrieve public photos (like upload your own),
|
57
|
+
# you'll need to generate an authentication token to use across requests and sessions.
|
58
|
+
#
|
59
|
+
# Assuming you've already applied for a key, go back and make sure you have the right settings
|
60
|
+
# to get your auth token. Click on the 'Edit key details' link and ensure that:
|
61
|
+
#
|
62
|
+
# 1. Your application description and notes are up-to-date
|
63
|
+
# 1. The value for 'Authentication Type' is set to 'Mobile Application'
|
64
|
+
# 1. The value for 'Mobile Permissions' is set to either 'write' or 'delete'
|
65
|
+
#
|
66
|
+
# Once this is set, you'll see your Authentication URL on the key details page (it will look
|
67
|
+
# something like http://www.flickr.com/auth-534525246245). Paste this URL into your browser and
|
68
|
+
# confirm access to get your mini-token. Now you're ready to make authenticated requests:
|
69
|
+
#
|
70
|
+
# require 'rubygems'
|
71
|
+
# require 'fleakr'
|
72
|
+
#
|
73
|
+
# Fleakr.api_key = 'ABC123'
|
74
|
+
# Fleakr.shared_secret = 'sekrit' # Available with your key details on the Flickr site
|
75
|
+
# Fleakr.mini_token = '362-133-214'
|
76
|
+
#
|
77
|
+
# Fleakr.upload('/path/to/my/photo.jpg')
|
78
|
+
# Fleakr.token.value # => "34132412341235-12341234ef34"
|
79
|
+
#
|
80
|
+
# Once you use the mini-token once, it is no longer available. To use the generated auth_token
|
81
|
+
# for future requests, just set Fleakr.auth_token to the generated value.
|
82
|
+
#
|
83
|
+
module Fleakr
|
84
|
+
|
85
|
+
# Generic catch-all exception for any API errors
|
86
|
+
class ApiError < StandardError; end
|
87
|
+
|
88
|
+
mattr_accessor :api_key, :shared_secret, :mini_token, :auth_token, :frob
|
89
|
+
|
90
|
+
# Find a user based on some unique user data. This method will try to find
|
91
|
+
# the user based on username and will fall back to email if that fails. Example:
|
92
|
+
#
|
93
|
+
# Fleakr.api_key = 'ABC123'
|
94
|
+
# Fleakr.user('the decapitator') # => #<Fleakr::Objects::User:0x692648 @username="the decapitator", @id="21775151@N06">
|
95
|
+
# Fleakr.user('user@host.com') # => #<Fleakr::Objects::User:0x11f484c @username="bckspcr", @id="84481630@N00">
|
96
|
+
#
|
97
|
+
def self.user(user_data)
|
98
|
+
begin
|
99
|
+
Objects::User.find_by_username(user_data)
|
100
|
+
rescue ApiError
|
101
|
+
Objects::User.find_by_email(user_data)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Search all photos on the Flickr site. By default, this searches based on text, but you can pass
|
106
|
+
# different search parameters (passed as hash keys):
|
107
|
+
#
|
108
|
+
# [tags] The list of tags to search on (either as an array or comma-separated)
|
109
|
+
# [user_id] Scope the search to this user
|
110
|
+
# [group_id] Scope the search to this group
|
111
|
+
#
|
112
|
+
# If you're interested in User- and Group-scoped searches, you may want to use User#search and Group#search
|
113
|
+
# instead.
|
114
|
+
#
|
115
|
+
def self.search(params)
|
116
|
+
params = {:text => params} unless params.is_a?(Hash)
|
117
|
+
Objects::Search.new(params).results
|
118
|
+
end
|
119
|
+
|
120
|
+
# Upload one or more files to your Flickr account (requires authentication). Simply provide
|
121
|
+
# a filename or a pattern to upload one or more files:
|
122
|
+
#
|
123
|
+
# Fleakr.upload('/path/to/my/mug.jpg')
|
124
|
+
# Fleakr.upload('/User/Pictures/Party/*.jpg')
|
125
|
+
#
|
126
|
+
# Additionally, options can be supplied as part of the upload that will apply to all files
|
127
|
+
# that are matched by the pattern passed to <tt>glob</tt>. For a full list, see
|
128
|
+
# Fleakr::Objects::Photo.
|
129
|
+
#
|
130
|
+
def self.upload(glob, options = {})
|
131
|
+
Dir[glob].map {|file| Fleakr::Objects::Photo.upload(file, options) }
|
132
|
+
end
|
133
|
+
|
134
|
+
# Get all contacts for an authenticated account
|
135
|
+
# Pass in optional params
|
136
|
+
# [filter]=friends|family|both|neither
|
137
|
+
def self.contacts(params={})
|
138
|
+
Fleakr::Objects::Contact.find_all_contacts(params)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Get the authentication token needed for authenticated requests. Will either use
|
142
|
+
# a valid auth_token (if available) or a mini-token to generate the auth_token.
|
143
|
+
#
|
144
|
+
def self.token
|
145
|
+
@token ||= begin
|
146
|
+
if Fleakr.auth_token
|
147
|
+
Fleakr::Objects::AuthenticationToken.from_auth_token(Fleakr.auth_token)
|
148
|
+
elsif Fleakr.frob
|
149
|
+
Fleakr::Objects::AuthenticationToken.from_frob(Fleakr.frob)
|
150
|
+
elsif Fleakr.mini_token
|
151
|
+
Fleakr::Objects::AuthenticationToken.from_mini_token(Fleakr.mini_token)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Reset the cached token whenever setting a new value for the mini_token, auth_token, or frob
|
157
|
+
#
|
158
|
+
[:mini_token, :auth_token, :frob].each do |attribute|
|
159
|
+
class_eval <<-ACCESSOR
|
160
|
+
def self.#{attribute}=(#{attribute})
|
161
|
+
reset_token
|
162
|
+
@@#{attribute} = #{attribute}
|
163
|
+
end
|
164
|
+
ACCESSOR
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.reset_token # :nodoc: #
|
168
|
+
@token = nil
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<contacts page="1" pages="1" per_page="1000" perpage="1000" total="17">
|
4
|
+
<contact nsid="9302864@N42" username="blinky" iconserver="2263" iconfarm="3" ignored="0" />
|
5
|
+
<contact nsid="63204625@N20" username="inky" iconserver="53" iconfarm="1" ignored="0" />
|
6
|
+
</contacts>
|
7
|
+
</rsp>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<photos page="1" pages="796" perpage="100" total="79509">
|
4
|
+
<photo id="3101830908" owner="64008250@N00" secret="e85e249e72" server="3042" farm="4" title="Canal Gate" ispublic="1" isfriend="0" isfamily="0" ownername="oakraidr" dateadded="1229049777" />
|
5
|
+
<photo id="3100780049" owner="98821864@N00" secret="f46fbe211b" server="3274" farm="4" title="2alarm" ispublic="1" isfriend="0" isfamily="0" ownername="LooknFeel" dateadded="1229042651" />
|
6
|
+
</photos>
|
7
|
+
</rsp>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<person id="31066442@N69" nsid="31066442@N69" isadmin="0" ispro="1" iconserver="30" iconfarm="1">
|
4
|
+
<username>frootpantz</username>
|
5
|
+
<realname>Sir Froot Pantz</realname>
|
6
|
+
<mbox_sha1sum>e52ed1e5b91c763694995460e9796fc2adc02019</mbox_sha1sum>
|
7
|
+
<location>The Moon</location>
|
8
|
+
<photosurl>http://www.flickr.com/photos/frootpantz/</photosurl>
|
9
|
+
<profileurl>http://www.flickr.com/people/frootpantz/</profileurl>
|
10
|
+
<mobileurl>http://m.flickr.com/photostream.gne?id=34225</mobileurl>
|
11
|
+
<photos>
|
12
|
+
<firstdatetaken>2006-10-11 08:19:57</firstdatetaken>
|
13
|
+
<firstdate>1160612247</firstdate>
|
14
|
+
<count>3907</count>
|
15
|
+
<views>9002</views>
|
16
|
+
</photos>
|
17
|
+
</person>
|
18
|
+
</rsp>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<photos page="1" pages="1" perpage="100" total="76">
|
4
|
+
<photo id="2924549350" owner="21775151@N06" secret="cbc1804258" server="3250" farm="4" title="Photo #1" ispublic="1" isfriend="0" isfamily="0" />
|
5
|
+
<photo id="2923697303" owner="21775151@N06" secret="649aa95f29" server="3208" farm="4" title="Photo #2" ispublic="1" isfriend="0" isfamily="0" />
|
6
|
+
</photos>
|
7
|
+
</rsp>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<comments photo_id="1">
|
4
|
+
<comment id="1" author="10490170@N04" authorname="blip" datecreate="1239217523" permalink="http://www.flickr.com/photos/frootpantz/3422268412/#comment72157616515348062">comment one</comment>
|
5
|
+
<comment id="2" author="10490170@N02" authorname="bleep" datecreate="1239217222" permalink="http://www.flickr.com/photos/frootpantz/3422268413/#comment72157616515348063">comment two</comment>
|
6
|
+
</comments>
|
7
|
+
</rsp>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<count>5584</count>
|
4
|
+
<prevphoto id="12345" secret="abc234" server="3560" farm="4" title="Previous" url="/photos/frootpantz/12345/in/photostream/" thumb="http://farm4.static.flickr.com/3560/3369675369_d97d2b1345_s.jpg" media="photo" />
|
5
|
+
<nextphoto id="12343" secret="abc123" server="3562" farm="4" title="Next" url="/photos/frootpantz/12343/in/photostream/" thumb="http://farm4.static.flickr.com/3562/3370497926_ba89f4343a_s.jpg" media="photo" />
|
6
|
+
</rsp>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<photo id="1" secret="secret" server="3085" farm="4" dateuploaded="1230274722" isfavorite="0" license="0" rotation="0" originalsecret="sekrit" originalformat="jpg" media="photo">
|
4
|
+
<owner nsid="31066442@N69" username="frootpantz" realname="" location="" />
|
5
|
+
<title>Tree</title>
|
6
|
+
<description>A Tree</description>
|
7
|
+
<visibility ispublic="1" isfriend="0" isfamily="0" />
|
8
|
+
<dates posted="1230274722" taken="2008-12-25 18:26:55" takengranularity="0" lastupdate="1230276652" />
|
9
|
+
|
10
|
+
<editability cancomment="0" canaddmeta="0" />
|
11
|
+
<usage candownload="1" canblog="0" canprint="0" />
|
12
|
+
<comments>0</comments>
|
13
|
+
<notes />
|
14
|
+
<tags />
|
15
|
+
<urls>
|
16
|
+
<url type="photopage">http://www.flickr.com/photos/yes/1</url>
|
17
|
+
</urls>
|
18
|
+
|
19
|
+
</photo>
|
20
|
+
</rsp>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<sizes canblog="0" canprint="0" candownload="1">
|
4
|
+
<size label="Square" width="75" height="75" source="http://farm4.static.flickr.com/3093/2409912100_71e14ed08a_s.jpg" url="http://www.flickr.com/photos/the_decapitator/2409912100/sizes/sq/" media="photo" />
|
5
|
+
<size label="Thumbnail" width="100" height="67" source="http://farm4.static.flickr.com/3093/2409912100_71e14ed08a_t.jpg" url="http://www.flickr.com/photos/the_decapitator/2409912100/sizes/t/" media="photo" />
|
6
|
+
<size label="Small" width="240" height="160" source="http://farm4.static.flickr.com/3093/2409912100_71e14ed08a_m.jpg" url="http://www.flickr.com/photos/the_decapitator/2409912100/sizes/s/" media="photo" />
|
7
|
+
<size label="Medium" width="500" height="334" source="http://farm4.static.flickr.com/3093/2409912100_71e14ed08a.jpg" url="http://www.flickr.com/photos/the_decapitator/2409912100/sizes/m/" media="photo" />
|
8
|
+
<size label="Original" width="700" height="467" source="http://farm4.static.flickr.com/3093/2409912100_3305c4a108_o.jpg" url="http://www.flickr.com/photos/the_decapitator/2409912100/sizes/o/" media="photo" />
|
9
|
+
</sizes>
|
10
|
+
</rsp>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<photos page="1" pages="385" perpage="100" total="38424">
|
4
|
+
<photo id="3076020861" owner="31987693@N05" secret="b956549c07" server="3278" farm="4" title="Mona and Lisa" ispublic="1" isfriend="0" isfamily="0" />
|
5
|
+
<photo id="3075386827" owner="9377349@N05" secret="4e40291b2d" server="3151" farm="4" title="IMG_0055 1.JPG" ispublic="1" isfriend="0" isfamily="0" />
|
6
|
+
</photos>
|
7
|
+
</rsp>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<comments photo_id="1">
|
4
|
+
<comment id="1" author="10490170@N04" authorname="blip" datecreate="1239217523" permalink="http://www.flickr.com/photos/frootpantz/3422268412/#comment72157616515348062">comment one</comment>
|
5
|
+
<comment id="2" author="10490170@N02" authorname="bleep" datecreate="1239217222" permalink="http://www.flickr.com/photos/frootpantz/3422268413/#comment72157616515348063">comment two</comment>
|
6
|
+
</comments>
|
7
|
+
</rsp>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<photosets>
|
4
|
+
<photoset videos="0" primary="3044180117" farm="4" photos="138" id="72157609490909659" server="3012" secret="01cd1a741d">
|
5
|
+
<title>Second Set</title>
|
6
|
+
<description>This is the second set.</description>
|
7
|
+
</photoset>
|
8
|
+
<photoset videos="0" primary="2988511085" farm="4" photos="139" id="72157608538140671" server="3241" secret="a7b90926ba">
|
9
|
+
<title>First Set</title>
|
10
|
+
<description>This is the first set.</description>
|
11
|
+
</photoset>
|
12
|
+
</photosets>
|
13
|
+
</rsp>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<photoset id="72157609490909659" primary="3044180117" owner="31066442@N69" ownername="frootpantz" page="1" per_page="500" perpage="500" pages="1" total="138">
|
4
|
+
<photo id="3044163577" secret="fa27e5a824" server="3153" farm="4" title="Photo #1" isprimary="0" />
|
5
|
+
<photo id="3045001128" secret="a8c0e51b39" server="3204" farm="4" title="Photo #2" isprimary="0" />
|
6
|
+
</photoset>
|
7
|
+
</rsp>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<photo id="3411015045">
|
4
|
+
<tags>
|
5
|
+
<tag id="1" author="15498419@N05" authorname="stu72" raw="stu 72" machine_tag="0">stu72</tag>
|
6
|
+
<tag id="2" author="15498419@N05" authorname="stu72" raw="ellie" machine_tag="0">ellie</tag>
|
7
|
+
</tags>
|
8
|
+
</photo>
|
9
|
+
</rsp>
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
$:.reject! { |e| e.include? 'TextMate' }
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'shoulda'
|
6
|
+
require 'matchy'
|
7
|
+
require 'mocha'
|
8
|
+
|
9
|
+
require File.dirname(__FILE__) + '/../lib/fleakr'
|
10
|
+
|
11
|
+
class Test::Unit::TestCase
|
12
|
+
|
13
|
+
def self.should_autoload_when_accessing(*attributes)
|
14
|
+
options = attributes.extract_options!
|
15
|
+
attributes.each do |accessor_name|
|
16
|
+
should "load the additional user information when accessing the :#{accessor_name} attribute" do
|
17
|
+
klass = self.class.name.sub(/Test$/, '').constantize
|
18
|
+
|
19
|
+
object = klass.new
|
20
|
+
object.expects(options[:with]).with()
|
21
|
+
object.send(accessor_name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.should_have_a_value_for(attribute_test)
|
27
|
+
should "have a value for :#{attribute_test.keys.first}" do
|
28
|
+
@object.send(attribute_test.keys.first).should == attribute_test.values.first
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.should_search_by(key)
|
33
|
+
should "be able to perform a scoped search by :#{key}" do
|
34
|
+
photos = [stub()]
|
35
|
+
search = stub(:results => photos)
|
36
|
+
|
37
|
+
klass = self.class.name.sub(/Test$/, '').constantize
|
38
|
+
|
39
|
+
instance = klass.new
|
40
|
+
instance.stubs(:id).with().returns('1')
|
41
|
+
|
42
|
+
Fleakr::Objects::Search.expects(:new).with(:text => 'foo', key => '1').returns(search)
|
43
|
+
|
44
|
+
instance.search('foo').should == photos
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.should_have_many(*attributes)
|
49
|
+
class_name = self.name.demodulize.sub(/Test$/, '')
|
50
|
+
this_klass = "Fleakr::Objects::#{class_name}".constantize
|
51
|
+
|
52
|
+
options = attributes.extract_options!
|
53
|
+
finder_attribute = options[:using].nil? ? "#{class_name.downcase}_id" : options[:using]
|
54
|
+
|
55
|
+
attributes.each do |attribute|
|
56
|
+
target_klass = "Fleakr::Objects::#{attribute.to_s.singularize.classify}".constantize
|
57
|
+
should "be able to retrieve the #{class_name.downcase}'s #{attribute}" do
|
58
|
+
results = [stub()]
|
59
|
+
object = this_klass.new
|
60
|
+
object.stubs(:id).with().returns('1')
|
61
|
+
|
62
|
+
target_klass.expects("find_all_by_#{finder_attribute}".to_sym).with('1').returns(results)
|
63
|
+
object.send(attribute).should == results
|
64
|
+
end
|
65
|
+
|
66
|
+
should "memoize the results for the #{class_name.downcase}'s #{attribute}" do
|
67
|
+
object = this_klass.new
|
68
|
+
|
69
|
+
target_klass.expects("find_all_by_#{finder_attribute}".to_sym).once.returns([])
|
70
|
+
2.times { object.send(attribute) }
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.should_find_one(thing, options)
|
77
|
+
class_name = thing.to_s.singularize.camelcase
|
78
|
+
klass = "Fleakr::Objects::#{class_name}".constantize
|
79
|
+
object_type = class_name.downcase
|
80
|
+
|
81
|
+
condition_value = '1'
|
82
|
+
|
83
|
+
options[:with] = options[:by] if options[:with].nil?
|
84
|
+
params = {options[:with] => condition_value}
|
85
|
+
|
86
|
+
should "be able to find a #{thing} by #{options[:by]}" do
|
87
|
+
stub = stub()
|
88
|
+
response = mock_request_cycle :for => options[:call], :with => params
|
89
|
+
|
90
|
+
klass.expects(:new).with(response.body).returns(stub)
|
91
|
+
klass.send("find_by_#{options[:by]}".to_sym, condition_value).should == stub
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.should_find_all(thing, options)
|
96
|
+
class_name = thing.to_s.singularize.camelcase
|
97
|
+
klass = "Fleakr::Objects::#{class_name}".constantize
|
98
|
+
object_type = class_name.downcase
|
99
|
+
|
100
|
+
should "be able to find all #{thing} by #{options[:by]}" do
|
101
|
+
condition_value = '1'
|
102
|
+
finder_options = {(options[:using] || options[:by]) => condition_value}
|
103
|
+
|
104
|
+
response = mock_request_cycle :for => options[:call], :with => finder_options
|
105
|
+
|
106
|
+
stubs = []
|
107
|
+
elements = (response.body/options[:path]).map
|
108
|
+
|
109
|
+
|
110
|
+
elements.each do |element|
|
111
|
+
stub = stub()
|
112
|
+
stubs << stub
|
113
|
+
|
114
|
+
klass.expects(:new).with(element).returns(stub)
|
115
|
+
end
|
116
|
+
|
117
|
+
klass.send("find_all_by_#{options[:by]}".to_sym, condition_value).should == stubs
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
def read_fixture(method_call)
|
123
|
+
fixture_path = File.dirname(__FILE__) + '/fixtures'
|
124
|
+
File.read("#{fixture_path}/#{method_call}.xml")
|
125
|
+
end
|
126
|
+
|
127
|
+
def mock_request_cycle(options)
|
128
|
+
response = stub(:body => Hpricot.XML(read_fixture(options[:for])))
|
129
|
+
Fleakr::Api::MethodRequest.expects(:with_response!).with(options[:for], options[:with]).returns(response)
|
130
|
+
|
131
|
+
response
|
132
|
+
end
|
133
|
+
|
134
|
+
def create_temp_directory
|
135
|
+
tmp_dir = File.dirname(__FILE__) + '/tmp'
|
136
|
+
FileUtils.mkdir(tmp_dir)
|
137
|
+
|
138
|
+
tmp_dir
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../test_helper'
|
2
|
+
|
3
|
+
module Fleakr::Api
|
4
|
+
class FileParameterTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
context "An instance of the FileParameter class" do
|
7
|
+
|
8
|
+
setup do
|
9
|
+
@temp_dir = File.expand_path(create_temp_directory)
|
10
|
+
@filename = "#{@temp_dir}/image.jpg"
|
11
|
+
end
|
12
|
+
|
13
|
+
teardown do
|
14
|
+
FileUtils.rm_rf(@temp_dir)
|
15
|
+
end
|
16
|
+
|
17
|
+
should "know not to include itself in the parameter signature" do
|
18
|
+
parameter = FileParameter.new('photo', @filename)
|
19
|
+
parameter.include_in_signature?.should be(false)
|
20
|
+
end
|
21
|
+
|
22
|
+
{'jpg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif'}.each do |ext, mime_type|
|
23
|
+
should "know the correct MIME type for an extension of #{ext}" do
|
24
|
+
parameter = FileParameter.new('photo', "#{@temp_dir}/image.#{ext}")
|
25
|
+
parameter.mime_type.should == mime_type
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
should "retrieve the contents of the file when accessing the value" do
|
30
|
+
File.expects(:read).with(@filename).returns('bopbip')
|
31
|
+
|
32
|
+
parameter = FileParameter.new('photo', @filename)
|
33
|
+
parameter.value.should == 'bopbip'
|
34
|
+
end
|
35
|
+
|
36
|
+
should "cache the file contents after retrieving them" do
|
37
|
+
File.expects(:read).with(@filename).once.returns('bopbip')
|
38
|
+
|
39
|
+
parameter = FileParameter.new('photo', @filename)
|
40
|
+
2.times { parameter.value }
|
41
|
+
end
|
42
|
+
|
43
|
+
should "know how to generate a form representation of itself" do
|
44
|
+
filename = 'image.jpg'
|
45
|
+
mime_type = 'image/jpeg'
|
46
|
+
|
47
|
+
parameter = FileParameter.new('photo', filename)
|
48
|
+
parameter.stubs(:mime_type).with().returns(mime_type)
|
49
|
+
parameter.stubs(:value).with().returns('data')
|
50
|
+
|
51
|
+
expected =
|
52
|
+
"Content-Disposition: form-data; name=\"photo\"; filename=\"#{filename}\"\r\n" +
|
53
|
+
"Content-Type: image/jpeg\r\n" +
|
54
|
+
"\r\n" +
|
55
|
+
"data\r\n"
|
56
|
+
|
57
|
+
parameter.to_form.should == expected
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|