tomk32-flickr_fu 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/.gitignore +13 -0
  2. data/LICENSE +22 -0
  3. data/README +182 -0
  4. data/Rakefile +73 -0
  5. data/VERSION.yml +4 -0
  6. data/lib/flickr/auth.rb +76 -0
  7. data/lib/flickr/base.rb +151 -0
  8. data/lib/flickr/comment.rb +16 -0
  9. data/lib/flickr/contact.rb +16 -0
  10. data/lib/flickr/contacts.rb +55 -0
  11. data/lib/flickr/errors.rb +20 -0
  12. data/lib/flickr/geo.rb +42 -0
  13. data/lib/flickr/license.rb +24 -0
  14. data/lib/flickr/location.rb +15 -0
  15. data/lib/flickr/note.rb +16 -0
  16. data/lib/flickr/people.rb +54 -0
  17. data/lib/flickr/person.rb +82 -0
  18. data/lib/flickr/photo.rb +333 -0
  19. data/lib/flickr/photo_response.rb +37 -0
  20. data/lib/flickr/photos.rb +277 -0
  21. data/lib/flickr/photoset.rb +37 -0
  22. data/lib/flickr/photosets.rb +39 -0
  23. data/lib/flickr/size.rb +16 -0
  24. data/lib/flickr/status.rb +19 -0
  25. data/lib/flickr/test.rb +31 -0
  26. data/lib/flickr/token.rb +22 -0
  27. data/lib/flickr/uploader.rb +162 -0
  28. data/lib/flickr/urls.rb +44 -0
  29. data/lib/flickr_fu.rb +51 -0
  30. data/spec/fixtures/flickr/contacts/get_list-fail-99.xml +4 -0
  31. data/spec/fixtures/flickr/contacts/get_public_list-0.xml +7 -0
  32. data/spec/fixtures/flickr/photos/geo/get_location-0.xml +11 -0
  33. data/spec/fixtures/flickr/photos/geo/get_location-fail-2.xml +4 -0
  34. data/spec/fixtures/flickr/photos/get_info-0.xml +41 -0
  35. data/spec/fixtures/flickr/photos/get_info-1.xml +19 -0
  36. data/spec/fixtures/flickr/photos/get_sizes-0.xml +10 -0
  37. data/spec/fixtures/flickr/photos/get_sizes-1.xml +8 -0
  38. data/spec/fixtures/flickr/photos/licenses/get_info.xml +12 -0
  39. data/spec/fixtures/flickr/photosets/get_list-0.xml +13 -0
  40. data/spec/fixtures/flickr/photosets/get_photos-0.xml +7 -0
  41. data/spec/fixtures/flickr/test/echo-0.xml +5 -0
  42. data/spec/fixtures/flickr/test/null-fail-99.xml +4 -0
  43. data/spec/fixtures/flickr/urls/get_group-0.xml +4 -0
  44. data/spec/fixtures/flickr/urls/get_group-fail-1.xml +4 -0
  45. data/spec/fixtures/flickr/urls/get_user_photos-0.xml +4 -0
  46. data/spec/fixtures/flickr/urls/get_user_photos-fail-1.xml +4 -0
  47. data/spec/fixtures/flickr/urls/get_user_photos-fail-2.xml +4 -0
  48. data/spec/fixtures/flickr/urls/get_user_profile-0.xml +4 -0
  49. data/spec/fixtures/flickr/urls/get_user_profile-fail-1.xml +4 -0
  50. data/spec/fixtures/flickr/urls/get_user_profile-fail-2.xml +4 -0
  51. data/spec/fixtures/flickr/urls/lookup_group-0.xml +6 -0
  52. data/spec/fixtures/flickr/urls/lookup_group-fail-1.xml +4 -0
  53. data/spec/fixtures/flickr/urls/lookup_user-0.xml +6 -0
  54. data/spec/fixtures/flickr/videos/get_info-0.xml +31 -0
  55. data/spec/fixtures/flickr/videos/get_sizes-0.xml +13 -0
  56. data/spec/flickr/base_spec.rb +97 -0
  57. data/spec/flickr/contacts_spec.rb +47 -0
  58. data/spec/flickr/errors_spec.rb +21 -0
  59. data/spec/flickr/geo_spec.rb +20 -0
  60. data/spec/flickr/photo_spec.rb +140 -0
  61. data/spec/flickr/photos_spec.rb +50 -0
  62. data/spec/flickr/photosets_spec.rb +49 -0
  63. data/spec/flickr/test_spec.rb +34 -0
  64. data/spec/flickr/urls_spec.rb +99 -0
  65. data/spec/spec.opts +4 -0
  66. data/spec/spec_helper.rb +20 -0
  67. data/tomk32-flickr_fu.gemspec +121 -0
  68. metadata +151 -0
@@ -0,0 +1,24 @@
1
+ class Flickr::Photos::License
2
+ attr_accessor :id, :name, :url
3
+
4
+ # create a new instance of a flickr photo license.
5
+ #
6
+ # Params
7
+ # * attributes (Required)
8
+ # a hash of attributes used to set the initial values of the license object
9
+ def initialize(attributes)
10
+ attributes.each do |k,v|
11
+ send("#{k}=", v)
12
+ end
13
+ end
14
+
15
+ def == o
16
+ return false unless o.respond_to?(:id) && o.respond_to?(:name) && o.respond_to?(:url)
17
+ return true if id == o.id && name == o.name && url == o.url
18
+ false
19
+ end
20
+
21
+ def eql? o
22
+ return self == o
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ class Flickr::Photos::Location
2
+
3
+ attr_accessor :latitude, :longitude, :accuracy
4
+
5
+ # Create an instance of Flickr::Photos::Location
6
+ #
7
+ # Params
8
+ # * attributes (Required)
9
+ # a hash of attributes used to set the initial values of the Location object
10
+ def initialize(attributes)
11
+ attributes.each do |k,v|
12
+ send("#{k}=", v)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ # wrapping class to hold a flickr note
2
+ #
3
+ class Flickr::Photos::Note
4
+ attr_accessor :id, :note, :author, :author_name, :x, :y, :width, :height
5
+
6
+ # create a new instance of a flickr note.
7
+ #
8
+ # Params
9
+ # * attributes (Required)
10
+ # a hash of attributes used to set the initial values of the note object
11
+ def initialize(attributes)
12
+ attributes.each do |k,v|
13
+ send("#{k}=", v)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,54 @@
1
+ class Flickr::People < Flickr::Base
2
+ def initialize(flickr)
3
+ @flickr = flickr
4
+ end
5
+
6
+ # Get information about a user.
7
+ #
8
+ # Params
9
+ # * id (Required)
10
+ # the nsid of the user to get information for
11
+ #
12
+ def find_by_id(id)
13
+ rsp = @flickr.send_request('flickr.people.getInfo', {:user_id => id})
14
+
15
+ Person.new(@flickr, :nsid => rsp.person[:nsid],
16
+ :is_admin => (rsp.person[:isadmin] == "1" ? true : false),
17
+ :is_pro => (rsp.person[:ispro] == "1" ? true : false),
18
+ :icon_server => rsp.person[:iconserver],
19
+ :icon_farm => rsp.person[:iconfarm],
20
+ :username => rsp.person.username.to_s,
21
+ :realname => rsp.person.realname.to_s,
22
+ :mbox_sha1sum => rsp.person.mbox_sha1sum.to_s,
23
+ :location => rsp.person.location.to_s,
24
+ :photos_url => rsp.person.photosurl.to_s,
25
+ :profile_url => rsp.person.profileurl.to_s,
26
+ :photo_count => rsp.person.photos.count.to_s.to_i,
27
+ :photo_first_upload => (Time.at(rsp.person.photos.firstdate.to_s.to_i) rescue nil),
28
+ :photo_first_taken => (Time.parse(rsp.person.photos.firstdatetaken.to_s) rescue nil))
29
+ end
30
+
31
+ # Get information about a user.
32
+ #
33
+ # Params
34
+ # * username (Required)
35
+ # the username of the user to get information for
36
+ #
37
+ def find_by_username(username)
38
+ rsp = @flickr.send_request('flickr.people.findByUsername', {:username => username})
39
+
40
+ find_by_id(rsp.user[:nsid])
41
+ end
42
+
43
+ # Get information about a user.
44
+ #
45
+ # Params
46
+ # * email (Required)
47
+ # the email of the user to get information for
48
+ #
49
+ def find_by_email(email)
50
+ rsp = @flickr.send_request('flickr.people.findByEmail', {:find_email => email})
51
+
52
+ find_by_id(rsp.user[:nsid])
53
+ end
54
+ end
@@ -0,0 +1,82 @@
1
+ # wrapping class to hold an flickr photo
2
+ #
3
+ class Flickr::People::Person
4
+ attr_accessor :username, :nsid, :is_admin, :is_pro, :icon_server, :icon_farm, :realname, :mbox_sha1sum, :location, :photos_url, :profile_url, :photo_count, :photo_first_upload, :photo_first_taken
5
+
6
+ # create a new instance of a flickr person.
7
+ #
8
+ # Params
9
+ # * flickr (Required)
10
+ # the flickr object
11
+ # * attributes (Required)
12
+ # a hash of attributes used to set the initial values of the person object
13
+ def initialize(flickr, attributes)
14
+ @flickr = flickr
15
+ attributes.each do |k,v|
16
+ send("#{k}=", v)
17
+ end
18
+ end
19
+
20
+ def buddy_icon
21
+ @buddy_icon ||= if icon_server.to_i > 0
22
+ "http://farm#{icon_farm}.static.flickr.com/#{icon_server}/buddyicons/#{nsid}.jpg"
23
+ else
24
+ 'http://www.flickr.com/images/buddyicon.jpg'
25
+ end
26
+ end
27
+
28
+ # Get a list of public photos for the given user.
29
+ #
30
+ # Options
31
+ # * safe_search (Optional)
32
+ # Safe search setting:
33
+ # 1 for safe.
34
+ # 2 for moderate.
35
+ # 3 for restricted.
36
+ # (Please note: Un-authed calls can only see Safe content.)
37
+ # * per_page (Optional)
38
+ # Number of photos to return per page. If this argument is omitted, it defaults to 100. The maximum allowed value is 500.
39
+ # * page (Optional)
40
+ # The page of results to return. If this argument is omitted, it defaults to 1.
41
+ def public_photos(options = {})
42
+ options.merge!({:user_id => self.nsid, :extras => "license,date_upload,date_taken,owner_name,icon_server,original_format,last_update,geo,tags,machine_tags,o_dims,views,media"})
43
+
44
+ rsp = @flickr.send_request('flickr.people.getPublicPhotos', options)
45
+
46
+ returning Flickr::Photos::PhotoResponse.new(:page => rsp.photos[:page].to_i,
47
+ :pages => rsp.photos[:pages].to_i,
48
+ :per_page => rsp.photos[:perpage].to_i,
49
+ :total => rsp.photos[:total].to_i,
50
+ :photos => [],
51
+ :api => self,
52
+ :method => 'public_photos',
53
+ :options => options) do |photos|
54
+ rsp.photos.photo.each do |photo|
55
+ attributes = {:id => photo[:id],
56
+ :owner => photo[:owner],
57
+ :secret => photo[:secret],
58
+ :server => photo[:server],
59
+ :farm => photo[:farm],
60
+ :title => photo[:title],
61
+ :is_public => photo[:ispublic],
62
+ :is_friend => photo[:isfriend],
63
+ :is_family => photo[:isfamily],
64
+ :license_id => photo[:license].to_i,
65
+ :uploaded_at => (Time.at(photo[:dateupload].to_i) rescue nil),
66
+ :taken_at => (Time.parse(photo[:datetaken]) rescue nil),
67
+ :owner_name => photo[:ownername],
68
+ :icon_server => photo[:icon_server],
69
+ :original_format => photo[:originalformat],
70
+ :updated_at => (Time.at(photo[:lastupdate].to_i) rescue nil),
71
+ :geo => photo[:geo],
72
+ :tags => photo[:tags],
73
+ :machine_tags => photo[:machine_tags],
74
+ :o_dims => photo[:o_dims],
75
+ :views => photo[:views].to_i,
76
+ :media => photo[:media]}
77
+
78
+ photos << Flickr::Photos::Photo.new(@flickr, attributes)
79
+ end if rsp.photos.photo
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,333 @@
1
+ # wrapping class to hold an flickr photo
2
+ class Flickr::Photos::Photo
3
+ attr_accessor :id, :owner, :secret, :server, :farm, :title, :is_public, :is_friend, :is_family # standard attributes
4
+ attr_accessor :license_id, :uploaded_at, :taken_at, :owner_name, :icon_server, :original_format, :updated_at, :geo, :tags, :machine_tags, :o_dims, :views, :media # extra attributes
5
+ attr_accessor :info_added, :description, :original_secret, :owner_username, :owner_realname, :url_photopage, :notes # info attributes
6
+ attr_accessor :comments # comment attributes
7
+
8
+ # create a new instance of a flickr photo.
9
+ #
10
+ # Params
11
+ # * flickr (Required)
12
+ # the flickr object
13
+ # * attributes (Required)
14
+ # a hash of attributes used to set the initial values of the photo object
15
+ def initialize(flickr, attributes)
16
+ @flickr = flickr
17
+ attributes.each do |k,v|
18
+ send("#{k}=", v)
19
+ end
20
+ end
21
+
22
+ # Alias to image_url method
23
+ def url(size = :medium)
24
+ image_url(size)
25
+ end
26
+
27
+ # returns an instance of Flickr::Photos::Size for the required size
28
+ #
29
+ # Params
30
+ # * size (Optional)
31
+ # the size of the size instance to return. Optional sizes are:
32
+ # :square - square 75x75
33
+ # :thumbnail - 100 on longest side
34
+ # :small - 240 on longest side
35
+ # :medium - 500 on longest side
36
+ # :large - 1024 on longest side (only exists for very large original images)
37
+ # :original - original image, either a jpg, gif or png, depending on source format
38
+ # Examples
39
+ # Photo.photo_size(:square).source
40
+ # Photo.photo_size(:large).width
41
+ def photo_size(size = :medium)
42
+ size_hash.fetch(size.to_s, size_hash['medium'])
43
+ end
44
+
45
+ # retreive the url to the image stored on flickr
46
+ #
47
+ # == Params
48
+ # * size (Optional)
49
+ # the size of the image to return. Optional sizes are:
50
+ # :square - square 75x75
51
+ # :thumbnail - 100 on longest side
52
+ # :small - 240 on longest side
53
+ # :medium - 500 on longest side
54
+ # :large - 1024 on longest side (only exists for very large original images)
55
+ # :original - original image, either a jpg, gif or png, depending on source format
56
+ #
57
+ def image_url(size = :medium)
58
+ # It turns out that flickr always stores all the sizes of the picture even when getSizes call returns otherwise.
59
+ # Not calling getSizes is also very important for performance reasons.
60
+ # Retrieving 30 search results means calling the API 31 times if you call getSizes every time.
61
+ # Mind that you still need to call getSizes if you go out for the original image.
62
+ if size == :original
63
+ size_hash[size.to_s].source if size_hash.has_key? size.to_s
64
+ else
65
+ key = "_#{size_key(size.to_sym)}"
66
+ key = "" if key == "_"
67
+ "http://farm#{farm}.static.flickr.com/#{server}/#{id}_#{secret}#{key}.jpg"
68
+ end
69
+ end
70
+
71
+ def photopage_url
72
+ # Keeping the same convention as image_url (foo_url)
73
+ url_photopage
74
+ end
75
+
76
+ def video_url
77
+ if size_hash['video player']
78
+ size_hash['video player'].source
79
+ end
80
+ end
81
+
82
+ # save the current photo to the local computer
83
+ #
84
+ # == Params
85
+ # * filename (Required)
86
+ # name of the new file omiting the extention (ex. photo_1)
87
+ # * size (Optional)
88
+ # the size of the image to return. Optional sizes are:
89
+ # :small - square 75x75
90
+ # :thumbnail - 100 on longest side
91
+ # :small - 240 on longest side
92
+ # :medium - 500 on longest side
93
+ # :large - 1024 on longest side (only exists for very large original images)
94
+ # :original - original image, either a jpg, gif or png, depending on source format
95
+ #
96
+ def save_as(filename, size = :medium)
97
+ format = size.to_sym == :original ? (self.original_format || 'jpg') : 'jpg'
98
+ filename = "#{filename}.#{format}"
99
+
100
+ if File.exists?(filename) or not self.url(size)
101
+ false
102
+ else
103
+ f = File.new(filename, 'w+')
104
+ f.puts open(self.url(size)).read
105
+ f.close
106
+ f
107
+ end
108
+ end
109
+
110
+ # Add tags to a photo.
111
+ #
112
+ # Params
113
+ # * tags (Required)
114
+ # comma seperated list of tags
115
+ #
116
+ def add_tags(tags)
117
+ @flickr.send_request('flickr.photos.addTags', {:photo_id => self.id, :tags => tags}, :post)
118
+ true
119
+ end
120
+
121
+ # Add comment to a photo as the currently authenticated user.
122
+ #
123
+ # Params
124
+ # * message (Required)
125
+ # text of the comment
126
+ #
127
+ def add_comment(message)
128
+ @flickr.send_request('flickr.photos.comments.addComment', {:photo_id => self.id, :comment_text => message}, :post)
129
+ true
130
+ end
131
+
132
+ # Add a note to a photo. Coordinates and sizes are in pixels, based on the 500px image size shown on individual photo pages.
133
+ #
134
+ # Params
135
+ # * message (Required)
136
+ # The text of the note
137
+ # * x (Required)
138
+ # The left coordinate of the note
139
+ # * y (Required)
140
+ # The top coordinate of the note
141
+ # * w (Required)
142
+ # The width of the note
143
+ # * h (Required)
144
+ # The height of the note
145
+ #
146
+ def add_note(message, x, y, w, h)
147
+ @flickr.send_request('flickr.photos.notes.add', {:photo_id => self.id, :note_x => x, :note_y => y, :note_w => w, :note_h => h, :note_text => message}, :post)
148
+ true
149
+ end
150
+
151
+ # Rotate a photo.
152
+ #
153
+ # Params
154
+ # * degrees (Required)
155
+ # The amount of degrees by which to rotate the photo (clockwise) from it's current orientation. Valid values are 90, 180 and 270.
156
+ #
157
+ def rotate(degrees)
158
+ @flickr.send_request('flickr.photos.transform.rotate', {:photo_id => self.id, :degrees => degrees}, :post)
159
+ true
160
+ end
161
+
162
+ # return the license associated with the photo
163
+ #
164
+ def license
165
+ @flickr.photos.licenses[self.license_id]
166
+ end
167
+
168
+ # Returns the location of the photo (if available)
169
+ # or nil if photo is not geo-tagged.
170
+ def location
171
+ begin
172
+ @location ||= @flickr.photos.geo.get_location(self.id)
173
+ rescue Flickr::Error => e
174
+ if e.code == 2 # 2: Photo has no location information.
175
+ return nil
176
+ else
177
+ raise e
178
+ end
179
+ end
180
+ end
181
+
182
+ def location= location
183
+ if !location.nil?
184
+ @flickr.photos.geo.set_location(self.id, location.latitude, location.longitude, location.accuracy)
185
+ else
186
+ @flickr.photos.geo.remove_location(self.id)
187
+ end
188
+ @location = location
189
+ end
190
+
191
+ # Sets the license for a photo.
192
+ #
193
+ # Params
194
+ # * license_id (Required)
195
+ # The license to apply, or 0 (zero) to remove the current license.
196
+ def set_license(license_id)
197
+ @flickr.send_request('flickr.photos.licenses.setLicense', {:photo_id => self.id, :license_id => license_id}, :post)
198
+ true
199
+ end
200
+
201
+ def description # :nodoc:
202
+ attach_info
203
+ @description
204
+ end
205
+
206
+ def original_secret # :nodoc:
207
+ attach_info
208
+ @original_secret
209
+ end
210
+
211
+ def public?
212
+ is_public == "1"
213
+ end
214
+
215
+ def friend?
216
+ is_friend == "1"
217
+ end
218
+
219
+ def family?
220
+ is_family == "1"
221
+ end
222
+
223
+ def owner_username # :nodoc:
224
+ attach_info
225
+ @owner_username
226
+ end
227
+
228
+ def owner_realname # :nodoc:
229
+ attach_info
230
+ @owner_realname
231
+ end
232
+
233
+ def url_photopage # :nodoc:
234
+ attach_info
235
+ @url_photopage
236
+ end
237
+
238
+ def comments # :nodoc:
239
+ @comments ||= begin
240
+ if @comment_count == 0
241
+ self.comments = []
242
+ else
243
+ rsp = @flickr.send_request('flickr.photos.comments.getList', :photo_id => self.id)
244
+
245
+ self.comments = []
246
+
247
+ rsp.comments.comment.each do |comment|
248
+ self.comments << Flickr::Photos::Comment.new(:id => comment[:id],
249
+ :comment => comment.to_s,
250
+ :author => comment[:author],
251
+ :author_name => comment[:authorname],
252
+ :permalink => comment[:permalink],
253
+ :created_at => (Time.at(comment[:datecreate].to_i) rescue nil))
254
+ end
255
+ end
256
+
257
+ self.comments
258
+ end
259
+ end
260
+
261
+ def sizes # :nodoc:
262
+ @sizes ||= begin
263
+ rsp = @flickr.send_request('flickr.photos.getSizes', :photo_id => self.id)
264
+
265
+ _sizes = []
266
+ rsp.sizes.size.each do |size|
267
+ _sizes << Flickr::Photos::Size.new(:label => size[:label], :width => size[:width],
268
+ :height => size[:height], :source => size[:source], :url => size[:url])
269
+ end
270
+ _sizes
271
+ end
272
+ end
273
+
274
+ def notes # :nodoc:
275
+ attach_info
276
+ @notes
277
+ end
278
+
279
+ protected
280
+ def size_hash
281
+ @size_hash ||= begin
282
+ hash = {}
283
+ sizes.each do |size|
284
+ hash[size.label.downcase] = size
285
+ end
286
+ hash
287
+ end
288
+ end
289
+
290
+ private
291
+ attr_accessor :comment_count
292
+
293
+ # convert the size to the key used in the flickr url
294
+ def size_key(size)
295
+ case size.to_sym
296
+ when :square then 's'
297
+ when :thumb, :thumbnail then 't'
298
+ when :small then 'm'
299
+ when :medium then ''
300
+ when :large then 'b'
301
+ when :original then 'o'
302
+ else ''
303
+ end
304
+ end
305
+
306
+ # loads photo info when a field is requested that requires additional info
307
+ def attach_info
308
+ unless self.info_added
309
+ rsp = @flickr.send_request('flickr.photos.getInfo', :photo_id => self.id, :secret => self.secret)
310
+
311
+ self.info_added = true
312
+ self.description = rsp.photo.description.to_s.strip
313
+ self.original_secret = rsp.photo[:originalsecret]
314
+ self.owner_username = rsp.photo.owner[:username]
315
+ self.owner_realname = rsp.photo.owner[:realname]
316
+ self.url_photopage = rsp.photo.urls.url.to_s
317
+ self.comment_count = rsp.photo.comments.to_s.to_i
318
+
319
+ self.notes = []
320
+
321
+ rsp.photo.notes.note.each do |note|
322
+ self.notes << Flickr::Photos::Note.new(:id => note[:id],
323
+ :note => note.to_s,
324
+ :author => note[:author],
325
+ :author_name => note[:authorname],
326
+ :x => note[:x],
327
+ :y => note[:y],
328
+ :width => note[:w],
329
+ :height => note[:h])
330
+ end if rsp.photo.notes.note
331
+ end
332
+ end
333
+ end
@@ -0,0 +1,37 @@
1
+ # wrapping class to hold a photos response from the flickr api
2
+ #
3
+ class Flickr::Photos::PhotoResponse
4
+ attr_accessor :page, :pages, :per_page, :total, :photos, :api, :method, :options
5
+
6
+ # creates an object to hold the search response.
7
+ #
8
+ # Params
9
+ # * attributes (Required)
10
+ # a hash of attributes used to set the initial values of the response object
11
+ def initialize(attributes)
12
+ attributes.each do |k,v|
13
+ send("#{k}=", v)
14
+ end
15
+ end
16
+
17
+ # Add a Flickr::Photos::Photo object to the photos array. It does nothing if you pass a non photo object
18
+ def <<(photo)
19
+ self.photos ||= []
20
+ self.photos << photo if photo.is_a?(Flickr::Photos::Photo)
21
+ end
22
+
23
+ # gets the next page from flickr if there are anymore pages in the current photos object
24
+ def next_page
25
+ api.send(self.method, options.merge(:page => self.page.to_i + 1)) if self.page.to_i < self.pages.to_i
26
+ end
27
+
28
+ # gets the previous page from flickr if there is a previous page in the current photos object
29
+ def previous_page
30
+ api.send(self.method, options.merge(:page => self.page.to_i - 1)) if self.page.to_i > 1
31
+ end
32
+
33
+ # passes all unknown request to the photos array if it responds to the method
34
+ def method_missing(method, *args, &block)
35
+ self.photos.respond_to?(method) ? self.photos.send(method, *args, &block) : super
36
+ end
37
+ end