fleakr 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -119,7 +119,61 @@ Other sizes are available (:square, :thumbnail, :small, :medium, :large, :origin
119
119
  are accessed in the same way:
120
120
 
121
121
  >> photo.original.url
122
- => "http://farm4.static.flickr.com/3250/2924549350_1cf67c2d47_o.jpg"
122
+ => "http://farm4.static.flickr.com/3250/2924549350_1cf67c2d47_o.jpg"
123
+
124
+ === Tags
125
+
126
+ Tags are available for users and photos. Retrieving them is easy:
127
+
128
+ >> user = Fleakr.user('the decapitator')
129
+ >> user.tags
130
+ => [#<Fleakr::Objects::Tag:0x190d5fc @value="ad">,
131
+ #<Fleakr::Objects::Tag:0x1908a20 @value="ads">, ...
132
+ >> user.photos.first.tags
133
+ => [#<Fleakr::Objects::Tag:0x17b1b18 @machine_flag="0", @author_id="21775151@N06", ...
134
+
135
+ All tags have values, but for tags associated with photos there is some additional information:
136
+
137
+ >> tag = user.photos.first.tags.first
138
+ >> tag.id
139
+ => "21729829-3263659141-427098"
140
+ >> tag.raw
141
+ => "decapitator"
142
+ >> tag.value
143
+ => "decapitator"
144
+ >> tag.to_s
145
+ => "decapitator"
146
+ >> tag.machine?
147
+ => false
148
+ >> tag.author
149
+ => #<Fleakr::Objects::User:0x1a149f0 @username="the decapitator", ... >
150
+
151
+ See Fleakr::Objects::Tag for more information.
152
+
153
+ === Comments
154
+
155
+ Similar to tags, photosets and photos can each have comments:
156
+
157
+ >> user.sets.first.comments
158
+ => [#<Fleakr::Objects::Comment:0x19795cc ...
159
+ >> user.photos.first.comments
160
+ => [#<Fleakr::Objects::Comment:0x17bf0b0 @body="Dayum, that's some wishful thinking!" ...
161
+
162
+ All comments have additional information:
163
+
164
+ >> comment = user.photos.first.comments.first
165
+ >> comment.id
166
+ => "21729829-3263659141-72157613553885978"
167
+ >> comment.body
168
+ => "Dayum, that's some wishful thinking!"
169
+ >> comment.to_s
170
+ => "Dayum, that's some wishful thinking!"
171
+ >> comment.url
172
+ => "http://www.flickr.com/photos/the_decapitator/3263659141/#comment72157613553885978"
173
+ >> comment.author
174
+ => #<Fleakr::Objects::User:0x178e3d4 @username="jaspertandy", ... >
175
+
176
+ See Fleakr::Objects::Comment for more information.
123
177
 
124
178
  === Saving Images
125
179
 
@@ -0,0 +1,49 @@
1
+ module Fleakr
2
+ module Objects # :nodoc:
3
+
4
+ # = Comment
5
+ #
6
+ # This class represents a comment that can be associated with a single photo or an
7
+ # entire photoset.
8
+ #
9
+ # == Attributes
10
+ #
11
+ # [id] The unique identifier for this comment
12
+ # [url] The direct URL / permalink to reference this comment
13
+ # [body] The comment itself - also available with <tt>to_s</tt>
14
+ #
15
+ class Comment
16
+
17
+ include Fleakr::Support::Object
18
+
19
+ find_all :by_photo_id, :call => 'photos.comments.getList', :path => 'comments/comment'
20
+ find_all :by_set_id, :using => :photoset_id, :call => 'photosets.comments.getList', :path => 'comments/comment'
21
+
22
+ flickr_attribute :id
23
+ flickr_attribute :author_id, :from => '@author'
24
+ flickr_attribute :created, :from => '@datecreate'
25
+ flickr_attribute :url, :from => '@permalink'
26
+ flickr_attribute :body, :from => '.'
27
+
28
+ # The user who supplied the comment. See Fleakr::Objects::User for more information
29
+ #
30
+ def author
31
+ @author ||= User.find_by_id(author_id)
32
+ end
33
+
34
+ # When was this comment created?
35
+ #
36
+ def created_at
37
+ Time.at(created.to_i)
38
+ end
39
+
40
+ # The contents of the comment - also available as <tt>body</tt>
41
+ #
42
+ def to_s
43
+ body
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
@@ -8,18 +8,28 @@ module Fleakr
8
8
  # [id] This group's ID
9
9
  # [name] The name of the group
10
10
  #
11
+ # == Associations
12
+ #
13
+ # [photos] The photos that are in this group
14
+ #
11
15
  class Group
12
16
 
13
17
  include Fleakr::Support::Object
14
18
 
15
19
  flickr_attribute :id, :from => '@nsid'
16
20
  flickr_attribute :name
21
+ flickr_attribute :adult_flag, :from => '@eighteenplus'
17
22
 
18
23
  find_all :by_user_id, :call => 'people.getPublicGroups', :path => 'groups/group'
19
24
 
20
25
  has_many :photos
21
26
 
22
27
  scoped_search
28
+
29
+ # Is this group adult-only? (e.g. only 18+ allowed to view)
30
+ def adult?
31
+ (adult_flag == '1')
32
+ end
23
33
 
24
34
  end
25
35
  end
@@ -24,9 +24,8 @@ module Fleakr
24
24
 
25
25
  include Fleakr::Support::Object
26
26
 
27
+ flickr_attribute :width, :height
27
28
  flickr_attribute :size, :from => '@label'
28
- flickr_attribute :width
29
- flickr_attribute :height
30
29
  flickr_attribute :url, :from => '@source'
31
30
  flickr_attribute :page, :from => '@url'
32
31
 
@@ -20,10 +20,14 @@ module Fleakr
20
20
  # [medium] The medium representation of this photo
21
21
  # [large] The large representation of this photo
22
22
  # [original] The original photo
23
+ # [previous] The previous photo based on the current context
24
+ # [next] The next photo based on the current context
23
25
  #
24
26
  # == Associations
25
27
  #
26
28
  # [images] The underlying images for this photo.
29
+ # [tags] The tags for this photo.
30
+ # [comments] The comments associated with this photo
27
31
  #
28
32
  class Photo
29
33
 
@@ -31,28 +35,24 @@ module Fleakr
31
35
  SIZES = [:square, :thumbnail, :small, :medium, :large, :original]
32
36
 
33
37
  include Fleakr::Support::Object
38
+ extend Forwardable
39
+
40
+ def_delegators :context, :next, :previous
34
41
 
35
42
  flickr_attribute :id, :from => ['@id', 'photoid']
36
- flickr_attribute :title
37
- flickr_attribute :description
43
+ flickr_attribute :title, :description, :secret, :posted, :taken, :url
38
44
  flickr_attribute :farm_id, :from => '@farm'
39
45
  flickr_attribute :server_id, :from => '@server'
40
- flickr_attribute :secret
41
- flickr_attribute :posted
42
- flickr_attribute :taken
46
+ flickr_attribute :owner_id, :from => ['@owner', 'owner@nsid']
43
47
  flickr_attribute :updated, :from => '@lastupdate'
44
48
  flickr_attribute :comment_count, :from => 'comments'
45
- flickr_attribute :url
46
49
 
47
50
  # TODO:
48
- # * owner (user)
49
51
  # * visibility
50
52
  # * editability
51
53
  # * usage
52
- # * notes
53
- # * tags
54
54
 
55
- find_all :by_photoset_id, :call => 'photosets.getPhotos', :path => 'photoset/photo'
55
+ find_all :by_set_id, :using => :photoset_id, :call => 'photosets.getPhotos', :path => 'photoset/photo'
56
56
  find_all :by_user_id, :call => 'people.getPublicPhotos', :path => 'photos/photo'
57
57
  find_all :by_group_id, :call => 'groups.pools.getPhotos', :path => 'photos/photo'
58
58
 
@@ -60,7 +60,7 @@ module Fleakr
60
60
 
61
61
  lazily_load :posted, :taken, :updated, :comment_count, :url, :description, :with => :load_info
62
62
 
63
- has_many :images
63
+ has_many :images, :tags, :comments
64
64
 
65
65
  # Upload the photo specified by <tt>filename</tt> to the user's Flickr account. When uploading,
66
66
  # there are several options available (none are required):
@@ -98,6 +98,19 @@ module Fleakr
98
98
  self.populate_from(response.body)
99
99
  end
100
100
 
101
+ def context # :nodoc:
102
+ @context ||= begin
103
+ response = Fleakr::Api::MethodRequest.with_response!('photos.getContext', :photo_id => self.id)
104
+ PhotoContext.new(response.body)
105
+ end
106
+ end
107
+
108
+ # The user who uploaded this photo. See Fleakr::Objects::User for additional information.
109
+ #
110
+ def owner
111
+ @owner ||= User.find_by_id(owner_id)
112
+ end
113
+
101
114
  # When was this photo posted?
102
115
  #
103
116
  def posted_at
@@ -0,0 +1,49 @@
1
+ module Fleakr
2
+ module Objects # :nodoc:
3
+
4
+ # = PhotoContext
5
+ #
6
+ # This class represents the context for a photo as retrieved from the API. It's not
7
+ # intended to be used directly, but is used in conjunction with Photo#previous and
8
+ # Photo#next
9
+ #
10
+ # == Attributes
11
+ #
12
+ # [count] The number of photos available
13
+
14
+ class PhotoContext
15
+
16
+ include Fleakr::Support::Object
17
+
18
+ flickr_attribute :count
19
+ flickr_attribute :next_id, :from => 'nextphoto@id'
20
+ flickr_attribute :previous_id, :from => 'prevphoto@id'
21
+
22
+ # Is there a previous photo available for the current photo?
23
+ #
24
+ def previous?
25
+ previous_id != '0'
26
+ end
27
+
28
+ # The previous photo if one is available
29
+ #
30
+ def previous
31
+ Photo.find_by_id(previous_id) if previous?
32
+ end
33
+
34
+ # Is there a next photo available for the current photo?
35
+ #
36
+ def next?
37
+ next_id != '0'
38
+ end
39
+
40
+ # The next photo if one is available
41
+ #
42
+ def next
43
+ Photo.find_by_id(next_id) if next?
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
@@ -13,16 +13,15 @@ module Fleakr
13
13
  # == Associations
14
14
  #
15
15
  # [photos] The collection of photos for this set. See Fleakr::Objects::Photo
16
+ # [comments] All comments associated with this set. See Fleakr::Objects::Comment
16
17
  #
17
18
  class Set
18
19
 
19
20
  include Fleakr::Support::Object
20
21
 
21
- has_many :photos, :using => :photoset_id
22
+ has_many :photos, :comments
22
23
 
23
- flickr_attribute :id
24
- flickr_attribute :title
25
- flickr_attribute :description
24
+ flickr_attribute :id, :title, :description
26
25
  flickr_attribute :count, :from => '@photos'
27
26
 
28
27
  find_all :by_user_id, :call => 'photosets.getList', :path => 'photosets/photoset'
@@ -0,0 +1,56 @@
1
+ module Fleakr
2
+ module Objects # :nodoc:
3
+
4
+ # = Tag
5
+ #
6
+ # This class represents a tag that can be associated with a photo or an individual user.
7
+ #
8
+ # == Attributes
9
+ #
10
+ # [id] The unique identifier for this tag
11
+ # [raw] The raw, user-entered value for this tag
12
+ # [value] The formatted value for this tag. Also available through <tt>to_s</tt>
13
+ #
14
+ class Tag
15
+
16
+ include Fleakr::Support::Object
17
+
18
+ flickr_attribute :id, :raw
19
+ flickr_attribute :author_id, :from => '@author'
20
+ flickr_attribute :value, :from => '.' # pull this from the current node
21
+ flickr_attribute :machine_flag, :from => '@machine_tag'
22
+
23
+ find_all :by_photo_id, :call => 'tags.getListPhoto', :path => 'photo/tags/tag'
24
+ find_all :by_user_id, :call => 'tags.getListUser', :path => 'who/tags/tag'
25
+
26
+ # The first user who created this tag. See Fleakr::Objects::User for more information
27
+ #
28
+ def author
29
+ @author ||= User.find_by_id(author_id) unless author_id.nil?
30
+ end
31
+
32
+ # A list of related tags. Each of the objects in the collection is an instance of Tag
33
+ #
34
+ def related
35
+ @related ||= begin
36
+ response = Fleakr::Api::MethodRequest.with_response!('tags.getRelated', :tag => value)
37
+ (response.body/'rsp/tags/tag').map {|e| Tag.new(e) }
38
+ end
39
+ end
40
+
41
+ # Is this a machine tag?
42
+ #
43
+ def machine?
44
+ machine_flag != '0'
45
+ end
46
+
47
+ # The formatted value of the tag. Also available as <tt>value</tt>
48
+ #
49
+ def to_s
50
+ value
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+ end
@@ -28,6 +28,7 @@ module Fleakr
28
28
  # [groups] A list of this user's public groups. See Fleakr::Objects::Group.
29
29
  # [photos] A list of this user's public photos (newest first). See Fleakr::Objects::Photo.
30
30
  # [contacts] A list of this user's contacts - these are simply User objects
31
+ # [tags] The tags associated with this user
31
32
  #
32
33
  # == Examples
33
34
  #
@@ -44,9 +45,8 @@ module Fleakr
44
45
  include Fleakr::Support::Object
45
46
 
46
47
  flickr_attribute :id, :from => 'user@nsid'
47
- flickr_attribute :username
48
+ flickr_attribute :username, :location
48
49
  flickr_attribute :name, :from => 'person/realname'
49
- flickr_attribute :location
50
50
  flickr_attribute :photos_url, :from => 'person/photosurl'
51
51
  flickr_attribute :profile_url, :from => 'person/profileurl'
52
52
  flickr_attribute :photos_count, :from => 'person/photos/count'
@@ -55,10 +55,11 @@ module Fleakr
55
55
  flickr_attribute :pro, :from => 'person@ispro'
56
56
  flickr_attribute :admin, :from => 'person@isadmin'
57
57
 
58
- has_many :sets, :groups, :photos, :contacts
58
+ has_many :sets, :groups, :photos, :contacts, :tags
59
59
 
60
60
  find_one :by_username, :call => 'people.findByUsername'
61
61
  find_one :by_email, :using => :find_email, :call => 'people.findByEmail'
62
+ find_one :by_id, :using => :user_id, :call => 'people.getInfo'
62
63
 
63
64
  lazily_load :name, :photos_url, :profile_url, :photos_count, :location, :with => :load_info
64
65
  lazily_load :icon_server, :icon_farm, :pro, :admin, :with => :load_info
@@ -3,7 +3,10 @@ require 'fleakr/objects/contact'
3
3
  require 'fleakr/objects/error'
4
4
  require 'fleakr/objects/group'
5
5
  require 'fleakr/objects/image'
6
+ require 'fleakr/objects/photo_context'
6
7
  require 'fleakr/objects/photo'
8
+ require 'fleakr/objects/comment'
9
+ require 'fleakr/objects/tag'
7
10
  require 'fleakr/objects/search'
8
11
  require 'fleakr/objects/set'
9
12
  require 'fleakr/objects/user'
@@ -8,18 +8,22 @@ module Fleakr
8
8
  @attributes ||= []
9
9
  end
10
10
 
11
- def flickr_attribute(name, options = {})
12
- self.attributes << Attribute.new(name, options[:from])
13
- class_eval "attr_accessor :#{name}"
11
+ def flickr_attribute(*names_and_options)
12
+ options = names_and_options.extract_options!
13
+
14
+ names_and_options.each do |name|
15
+ self.attributes << Attribute.new(name, options[:from])
16
+ class_eval "attr_accessor :#{name}"
17
+ end
14
18
  end
15
19
 
16
20
  def has_many(*attributes)
17
- options = attributes.extract_options!
18
21
  class_name = self.name
19
22
 
20
23
  attributes.each do |attribute|
21
- target = "Fleakr::Objects::#{attribute.to_s.classify}"
22
- finder_attribute = options[:using].nil? ? "#{class_name.demodulize.underscore}_id": options[:using]
24
+ target = "Fleakr::Objects::#{attribute.to_s.classify}"
25
+ finder_attribute = "#{class_name.demodulize.underscore}_id"
26
+
23
27
  class_eval <<-CODE
24
28
  def #{attribute}
25
29
  @#{attribute} ||= #{target}.send("find_all_by_#{finder_attribute}".to_sym, self.id)
@@ -3,7 +3,7 @@ module Fleakr
3
3
 
4
4
  MAJOR = 0
5
5
  MINOR = 4
6
- TINY = 2
6
+ TINY = 3
7
7
 
8
8
  def self.to_s
9
9
  [MAJOR, MINOR, TINY].join('.')
data/lib/fleakr.rb CHANGED
@@ -5,6 +5,7 @@ require 'uri'
5
5
  require 'cgi'
6
6
  require 'net/http'
7
7
  require 'hpricot'
8
+ require 'forwardable'
8
9
 
9
10
  # Require only what we need from ActiveSupport
10
11
  require 'active_support/core_ext/array'
@@ -1,7 +1,7 @@
1
1
  <?xml version="1.0" encoding="utf-8" ?>
2
2
  <rsp stat="ok">
3
3
  <groups>
4
- <group nsid="13378274@N00" name="Group #1" admin="0" eighteenplus="0" />
5
- <group nsid="52242140489@N01" name="Group #2" admin="0" eighteenplus="0" />
4
+ <group nsid="13378274@N00" name="Group #1" admin="0" eighteenplus="1" />
5
+ <group nsid="52242140489@N01" name="Group #2" admin="1" eighteenplus="0" />
6
6
  </groups>
7
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,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,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>
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <rsp stat="ok">
3
+ <who id="32719556@N00">
4
+ <tags>
5
+ <tag>08fo</tag>
6
+ <tag>101building</tag>
7
+ <tag>101cookbooks</tag>
8
+ </tags>
9
+ </who>
10
+ </rsp>
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <rsp stat="ok">
3
+ <tags source="family">
4
+ <tag>portrait</tag>
5
+ <tag>baby</tag>
6
+ <tag>child</tag>
7
+ </tags>
8
+ </rsp>
9
+
data/test/test_helper.rb CHANGED
@@ -92,13 +92,15 @@ class Test::Unit::TestCase
92
92
  end
93
93
 
94
94
  def self.should_find_all(thing, options)
95
- class_name = thing.to_s.singularize.camelcase
96
- klass = "Fleakr::Objects::#{class_name}".constantize
97
- object_type = class_name.downcase
95
+ class_name = thing.to_s.singularize.camelcase
96
+ klass = "Fleakr::Objects::#{class_name}".constantize
97
+ object_type = class_name.downcase
98
98
 
99
99
  it "should be able to find all #{thing} by #{options[:by]}" do
100
100
  condition_value = '1'
101
- response = mock_request_cycle :for => options[:call], :with => {options[:by] => condition_value}
101
+ finder_options = {(options[:using] || options[:by]) => condition_value}
102
+
103
+ response = mock_request_cycle :for => options[:call], :with => finder_options
102
104
 
103
105
  stubs = []
104
106
  elements = (response.body/options[:path]).map
@@ -0,0 +1,66 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+
3
+ module Fleakr::Objects
4
+ class CommentTest < Test::Unit::TestCase
5
+
6
+ describe "The Comment class" do
7
+
8
+ should_find_all :comments, :by => :photo_id, :call => 'photos.comments.getList', :path => 'rsp/comments/comment'
9
+ should_find_all :comments, :by => :set_id, :using => :photoset_id, :call => 'photosets.comments.getList', :path => 'rsp/comments/comment'
10
+
11
+ end
12
+
13
+ describe "An instance of the Comment class" do
14
+
15
+ context "when populating from the photos_comments_getList XML data" do
16
+ before do
17
+ @object = Comment.new(Hpricot.XML(read_fixture('photos.comments.getList')).at('rsp/comments/comment'))
18
+ end
19
+
20
+ should_have_a_value_for :id => '1'
21
+ should_have_a_value_for :author_id => '10490170@N04'
22
+ should_have_a_value_for :created => '1239217523'
23
+ should_have_a_value_for :url => 'http://www.flickr.com/photos/frootpantz/3422268412/#comment72157616515348062'
24
+ should_have_a_value_for :body => 'comment one'
25
+
26
+ end
27
+
28
+ context "in general" do
29
+
30
+ before { @comment = Comment.new }
31
+
32
+ it "should have a value for :created_at" do
33
+ @comment.expects(:created).with().returns('1239217523')
34
+ Time.expects(:at).with(1239217523).returns('time')
35
+
36
+ @comment.created_at.should == 'time'
37
+ end
38
+
39
+ it "should use the body as the string representation" do
40
+ @comment.expects(:body).with().returns('bod')
41
+ @comment.to_s.should == 'bod'
42
+ end
43
+
44
+ it "should be able to find the author of the comment" do
45
+ author = stub()
46
+
47
+
48
+ @comment.stubs(:author_id).with().returns('1')
49
+ User.expects(:find_by_id).with('1').returns(author)
50
+
51
+ @comment.author.should == author
52
+ end
53
+
54
+ it "should memoize the owner information" do
55
+ @comment.stubs(:author_id).with().returns('1')
56
+
57
+ User.expects(:find_by_id).with('1').once.returns(stub())
58
+
59
+ 2.times { @comment.author }
60
+ end
61
+
62
+ end
63
+ end
64
+
65
+ end
66
+ end
@@ -23,9 +23,24 @@ module Fleakr::Objects
23
23
 
24
24
  should_have_a_value_for :id => '13378274@N00'
25
25
  should_have_a_value_for :name => 'Group #1'
26
+ should_have_a_value_for :adult_flag => '1'
26
27
 
27
28
  end
29
+
30
+ it "should know that the group is adult-only" do
31
+ group = Group.new
32
+ group.stubs(:adult_flag).with().returns('1')
33
+ group.adult?.should be(true)
34
+ end
35
+
36
+ it "should know that the group is not adult-only" do
37
+ group = Group.new
38
+ group.stubs(:adult_flag).with().returns('0')
39
+ group.adult?.should be(false)
40
+ end
41
+
28
42
  end
29
43
 
30
44
  end
31
- end
45
+ end
46
+
@@ -0,0 +1,80 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+
3
+ module Fleakr::Objects
4
+ class PhotoContextTest < Test::Unit::TestCase
5
+
6
+ describe "An instance of the PhotoContext class" do
7
+
8
+ before { @context = PhotoContext.new }
9
+
10
+ context "when populating from the photos_getContext XML data" do
11
+ before do
12
+ @object = PhotoContext.new(Hpricot.XML(read_fixture('photos.getContext')))
13
+ end
14
+
15
+ should_have_a_value_for :count => '5584'
16
+ should_have_a_value_for :next_id => '12343'
17
+ should_have_a_value_for :previous_id => '12345'
18
+
19
+ end
20
+
21
+ it "should know that there is a previous photo" do
22
+ @context.expects(:previous_id).with().returns('1')
23
+ @context.previous?.should be(true)
24
+ end
25
+
26
+ it "should know that there isn't a previous photo" do
27
+ @context.expects(:previous_id).with().returns('0')
28
+ @context.previous?.should be(false)
29
+ end
30
+
31
+ it "should know that there is a next photo" do
32
+ @context.expects(:next_id).with().returns('1')
33
+ @context.next?.should be(true)
34
+ end
35
+
36
+ it "should know that there isn't a next photo" do
37
+ @context.expects(:next_id).with().returns('0')
38
+ @context.next?.should be(false)
39
+ end
40
+
41
+ it "should find the previous photo" do
42
+ photo = stub()
43
+
44
+ @context.expects(:previous_id).with().returns('1')
45
+ @context.expects(:previous?).with().returns(true)
46
+
47
+ Photo.expects(:find_by_id).with('1').returns(photo)
48
+
49
+ @context.previous.should == photo
50
+ end
51
+
52
+ it "should not try to find the previous photo if it doesn't exist" do
53
+ @context.expects(:previous?).with().returns(false)
54
+ Photo.expects(:find_by_id).never
55
+
56
+ @context.previous.should be(nil)
57
+ end
58
+
59
+ it "should find the next photo" do
60
+ photo = stub()
61
+ @context.expects(:next_id).with().returns('1')
62
+ @context.expects(:next?).with().returns(true)
63
+
64
+ Photo.expects(:find_by_id).with('1').returns(photo)
65
+
66
+ @context.next.should == photo
67
+ end
68
+
69
+ it "should not try to find the next photo if it doesn't exist" do
70
+ @context.expects(:next?).with().returns(false)
71
+ Photo.expects(:find_by_id).never
72
+
73
+ @context.next.should be(nil)
74
+ end
75
+
76
+
77
+ end
78
+
79
+ end
80
+ end
@@ -3,7 +3,7 @@ require File.dirname(__FILE__) + '/../../../test_helper'
3
3
  module Fleakr::Objects
4
4
  class PhotoTest < Test::Unit::TestCase
5
5
 
6
- should_have_many :images
6
+ should_have_many :images, :tags, :comments
7
7
 
8
8
  should_autoload_when_accessing :posted, :taken, :updated, :comment_count, :with => :load_info
9
9
  should_autoload_when_accessing :url, :description, :with => :load_info
@@ -11,7 +11,7 @@ module Fleakr::Objects
11
11
  describe "The Photo class" do
12
12
 
13
13
  should_find_all :photos, :by => :user_id, :call => 'people.getPublicPhotos', :path => 'rsp/photos/photo'
14
- should_find_all :photos, :by => :photoset_id, :call => 'photosets.getPhotos', :path => 'rsp/photoset/photo'
14
+ should_find_all :photos, :by => :set_id, :using => :photoset_id, :call => 'photosets.getPhotos', :path => 'rsp/photoset/photo'
15
15
  should_find_all :photos, :by => :group_id, :call => 'groups.pools.getPhotos', :path => 'rsp/photos/photo'
16
16
 
17
17
  should_find_one :photo, :by => :id, :with => :photo_id, :call => 'photos.getInfo'
@@ -74,6 +74,8 @@ module Fleakr::Objects
74
74
  should_have_a_value_for :farm_id => '4'
75
75
  should_have_a_value_for :server_id => '3250'
76
76
  should_have_a_value_for :secret => 'cbc1804258'
77
+ should_have_a_value_for :owner_id => '21775151@N06'
78
+
77
79
  end
78
80
 
79
81
  context "when populating from the photo upload XML data" do
@@ -95,6 +97,7 @@ module Fleakr::Objects
95
97
  should_have_a_value_for :description => 'A Tree'
96
98
  should_have_a_value_for :farm_id => '4'
97
99
  should_have_a_value_for :server_id => '3085'
100
+ should_have_a_value_for :owner_id => '31066442@N69'
98
101
  should_have_a_value_for :secret => 'secret'
99
102
  should_have_a_value_for :posted => '1230274722'
100
103
  should_have_a_value_for :taken => '2008-12-25 18:26:55'
@@ -166,10 +169,75 @@ module Fleakr::Objects
166
169
  end
167
170
  end
168
171
 
172
+ it "should be able to retrieve the context for this photo" do
173
+ id = '1'
174
+
175
+ context = stub()
176
+
177
+ photo = Photo.new
178
+ photo.stubs(:id).with().returns(id)
179
+
180
+ response = mock_request_cycle :for => 'photos.getContext', :with => {:photo_id => id}
181
+ PhotoContext.expects(:new).with(response.body).returns(context)
182
+
183
+ photo.context.should == context
184
+ end
185
+
186
+ it "should memoize the context data" do
187
+ id = '1'
188
+
189
+ context = stub()
190
+
191
+ photo = Photo.new
192
+ photo.stubs(:id).with().returns(id)
193
+
194
+ response = mock_request_cycle :for => 'photos.getContext', :with => {:photo_id => id}
195
+ PhotoContext.expects(:new).once.returns(context)
196
+
197
+ 2.times { photo.context }
198
+ end
199
+
200
+ it "should be able to retrieve the next photo" do
201
+ next_photo = stub()
202
+
203
+ photo = Photo.new
204
+ photo.expects(:context).with().returns(mock {|m| m.expects(:next).with().returns(next_photo)})
205
+
206
+ photo.next.should == next_photo
207
+ end
208
+
209
+ it "should be able to retrieve the previous photo" do
210
+ previous_photo = stub()
211
+
212
+ photo = Photo.new
213
+ photo.expects(:context).with().returns(mock {|m| m.expects(:previous).with().returns(previous_photo)})
214
+
215
+ photo.previous.should == previous_photo
216
+ end
217
+
218
+ it "should be able to find the owner of the photo" do
219
+ owner = stub()
220
+
221
+ photo = Photo.new
222
+ photo.stubs(:owner_id).with().returns('1')
223
+
224
+ User.expects(:find_by_id).with('1').returns(owner)
225
+
226
+ photo.owner.should == owner
227
+ end
228
+
229
+ it "should memoize the owner information" do
230
+ photo = Photo.new
231
+ photo.stubs(:owner_id).with().returns('1')
232
+
233
+ User.expects(:find_by_id).with('1').once.returns(stub())
234
+
235
+ 2.times { photo.owner }
236
+ end
169
237
 
170
238
  end
171
239
  end
172
240
 
173
241
  end
174
242
 
175
- end
243
+ end
@@ -3,7 +3,7 @@ require File.dirname(__FILE__) + '/../../../test_helper'
3
3
  module Fleakr::Objects
4
4
  class SetTest < Test::Unit::TestCase
5
5
 
6
- should_have_many :photos, :using => 'photoset_id'
6
+ should_have_many :photos, :comments
7
7
 
8
8
  describe "The Set class" do
9
9
 
@@ -0,0 +1,98 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+
3
+ module Fleakr::Objects
4
+ class TagTest < Test::Unit::TestCase
5
+
6
+ describe "The Tag class" do
7
+
8
+ should_find_all :tags, :by => :photo_id, :call => 'tags.getListPhoto', :path => 'rsp/photo/tags/tag'
9
+ should_find_all :tags, :by => :user_id, :call => 'tags.getListUser', :path => 'rsp/who/tags/tag'
10
+ end
11
+
12
+ describe "An instance of the Tag class" do
13
+
14
+ before { @tag = Tag.new }
15
+
16
+ context "when populating from the tags_getListPhoto XML data" do
17
+ before do
18
+ @object = Tag.new(Hpricot.XML(read_fixture('tags.getListPhoto')).at('rsp/photo/tags/tag'))
19
+ end
20
+
21
+ should_have_a_value_for :id => '1'
22
+ should_have_a_value_for :author_id => '15498419@N05'
23
+ should_have_a_value_for :value => 'stu72'
24
+ should_have_a_value_for :raw => 'stu 72'
25
+ should_have_a_value_for :machine_flag => '0'
26
+
27
+ end
28
+
29
+ it "should have an author" do
30
+ user = stub()
31
+
32
+ @tag.expects(:author_id).at_least_once.with().returns('1')
33
+
34
+
35
+ User.expects(:find_by_id).with('1').returns(user)
36
+
37
+ @tag.author.should == user
38
+ end
39
+
40
+ it "should memoize the author data" do
41
+ @tag.expects(:author_id).at_least_once.with().returns('1')
42
+
43
+ User.expects(:find_by_id).with('1').once.returns(stub())
44
+
45
+ 2.times { @tag.author }
46
+ end
47
+
48
+ it "should return nil for author if author_id is not present" do
49
+ @tag.expects(:author_id).with().returns(nil)
50
+
51
+ @tag.author.should be(nil)
52
+ end
53
+
54
+ it "should have related tags" do
55
+ @tag.expects(:value).with().returns('foo')
56
+
57
+ response = mock_request_cycle :for => 'tags.getRelated', :with => {:tag => 'foo'}
58
+
59
+ stubs = []
60
+ elements = (response.body/'rsp/tags/tag').map
61
+
62
+ elements.each do |element|
63
+ stub = stub()
64
+ stubs << stub
65
+
66
+ Tag.expects(:new).with(element).returns(stub)
67
+ end
68
+
69
+ @tag.related.should == stubs
70
+ end
71
+
72
+ it "should memoize the data for related tags" do
73
+ @tag.expects(:value).with().returns('foo')
74
+
75
+ mock_request_cycle :for => 'tags.getRelated', :with => {:tag => 'foo'}
76
+
77
+ 2.times { @tag.related }
78
+ end
79
+
80
+ it "should be able to generate a string representation of itself" do
81
+ @tag.expects(:value).with().returns('foo')
82
+ @tag.to_s.should == 'foo'
83
+ end
84
+
85
+ it "should know that it is not a machine tag" do
86
+ @tag.expects(:machine_flag).with().returns('0')
87
+ @tag.machine?.should be(false)
88
+ end
89
+
90
+ it "should know that it is a machine tag" do
91
+ @tag.expects(:machine_flag).with().returns('1')
92
+ @tag.machine?.should be(true)
93
+ end
94
+
95
+ end
96
+
97
+ end
98
+ end
@@ -5,7 +5,7 @@ module Fleakr::Objects
5
5
 
6
6
  should_search_by :user_id
7
7
 
8
- should_have_many :photos, :groups, :sets, :contacts
8
+ should_have_many :photos, :groups, :sets, :contacts, :tags
9
9
 
10
10
  should_autoload_when_accessing :name, :photos_url, :profile_url, :photos_count, :location, :with => :load_info
11
11
  should_autoload_when_accessing :icon_server, :icon_farm, :pro, :admin, :icon_url, :with => :load_info
@@ -14,6 +14,7 @@ module Fleakr::Objects
14
14
 
15
15
  should_find_one :user, :by => :username, :call => 'people.findByUsername', :path => 'rsp/user'
16
16
  should_find_one :user, :by => :email, :with => :find_email, :call => 'people.findByEmail', :path => 'rsp/user'
17
+ should_find_one :user, :by => :id, :with => :user_id, :call => 'people.getInfo', :path => 'rsp/person'
17
18
 
18
19
  end
19
20
 
@@ -12,6 +12,7 @@ class FlickrObject
12
12
  flickr_attribute :description, :from => 'desc'
13
13
  flickr_attribute :id, :from => '@nsid'
14
14
  flickr_attribute :photoset_id, :from => 'photoset@id'
15
+ flickr_attribute :tag, :category
15
16
 
16
17
  find_one :by_id, :call => 'people.getInfo'
17
18
 
@@ -27,7 +28,7 @@ module Fleakr
27
28
  end
28
29
 
29
30
  it "should know the names of all its attributes" do
30
- FlickrObject.attributes.map {|a| a.name.to_s }.should == %w(name description id photoset_id)
31
+ FlickrObject.attributes.map {|a| a.name.to_s }.should == %w(name description id photoset_id tag category)
31
32
  end
32
33
 
33
34
  it "should be able to find by ID" do
@@ -56,7 +57,7 @@ module Fleakr
56
57
  describe "An instance method provided by the Flickr::Object module" do
57
58
 
58
59
  it "should have default reader methods" do
59
- [:name, :description, :id, :photoset_id].each do |method_name|
60
+ [:name, :description, :id, :photoset_id, :tag, :category].each do |method_name|
60
61
  FlickrObject.new.respond_to?(method_name).should == true
61
62
  end
62
63
  end
@@ -67,6 +68,8 @@ module Fleakr
67
68
  <name>Fleakr</name>
68
69
  <desc>Awesome</desc>
69
70
  <photoset id="1" />
71
+ <tag>Tag</tag>
72
+ <category>Category</category>
70
73
  XML
71
74
 
72
75
  @object = FlickrObject.new
@@ -91,6 +94,14 @@ module Fleakr
91
94
 
92
95
  @object.id.should == '1'
93
96
  end
97
+
98
+ it "should have the correct value for :tag" do
99
+ @object.tag.should == 'Tag'
100
+ end
101
+
102
+ it "should have the correct value for :category" do
103
+ @object.category.should == 'Category'
104
+ end
94
105
  end
95
106
 
96
107
  it "should populate its data from an XML document when initializing" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fleakr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrick Reagan
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-03 00:00:00 -05:00
12
+ date: 2009-04-11 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -71,13 +71,16 @@ files:
71
71
  - lib/fleakr/core_ext.rb
72
72
  - lib/fleakr/objects
73
73
  - lib/fleakr/objects/authentication_token.rb
74
+ - lib/fleakr/objects/comment.rb
74
75
  - lib/fleakr/objects/contact.rb
75
76
  - lib/fleakr/objects/error.rb
76
77
  - lib/fleakr/objects/group.rb
77
78
  - lib/fleakr/objects/image.rb
78
79
  - lib/fleakr/objects/photo.rb
80
+ - lib/fleakr/objects/photo_context.rb
79
81
  - lib/fleakr/objects/search.rb
80
82
  - lib/fleakr/objects/set.rb
83
+ - lib/fleakr/objects/tag.rb
81
84
  - lib/fleakr/objects/user.rb
82
85
  - lib/fleakr/objects.rb
83
86
  - lib/fleakr/support
@@ -97,11 +100,17 @@ files:
97
100
  - test/fixtures/people.getInfo.xml
98
101
  - test/fixtures/people.getPublicGroups.xml
99
102
  - test/fixtures/people.getPublicPhotos.xml
103
+ - test/fixtures/photos.comments.getList.xml
104
+ - test/fixtures/photos.getContext.xml
100
105
  - test/fixtures/photos.getInfo.xml
101
106
  - test/fixtures/photos.getSizes.xml
102
107
  - test/fixtures/photos.search.xml
108
+ - test/fixtures/photosets.comments.getList.xml
103
109
  - test/fixtures/photosets.getList.xml
104
110
  - test/fixtures/photosets.getPhotos.xml
111
+ - test/fixtures/tags.getListPhoto.xml
112
+ - test/fixtures/tags.getListUser.xml
113
+ - test/fixtures/tags.getRelated.xml
105
114
  - test/test_helper.rb
106
115
  - test/unit
107
116
  - test/unit/fleakr
@@ -120,13 +129,16 @@ files:
120
129
  - test/unit/fleakr/core_ext/true_class_test.rb
121
130
  - test/unit/fleakr/objects
122
131
  - test/unit/fleakr/objects/authentication_token_test.rb
132
+ - test/unit/fleakr/objects/comment_test.rb
123
133
  - test/unit/fleakr/objects/contact_test.rb
124
134
  - test/unit/fleakr/objects/error_test.rb
125
135
  - test/unit/fleakr/objects/group_test.rb
126
136
  - test/unit/fleakr/objects/image_test.rb
137
+ - test/unit/fleakr/objects/photo_context_test.rb
127
138
  - test/unit/fleakr/objects/photo_test.rb
128
139
  - test/unit/fleakr/objects/search_test.rb
129
140
  - test/unit/fleakr/objects/set_test.rb
141
+ - test/unit/fleakr/objects/tag_test.rb
130
142
  - test/unit/fleakr/objects/user_test.rb
131
143
  - test/unit/fleakr/support
132
144
  - test/unit/fleakr/support/attribute_test.rb