mwilliams-fleakr 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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 +31 -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 +147 -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 +164 -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 +61 -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 +246 -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
@@ -0,0 +1,147 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects # :nodoc:
|
3
|
+
|
4
|
+
# = Photo
|
5
|
+
#
|
6
|
+
# Handles both the retrieval of Photo objects from various associations (e.g. User / Set) as
|
7
|
+
# well as the ability to upload images to the Flickr site.
|
8
|
+
#
|
9
|
+
# == Attributes
|
10
|
+
#
|
11
|
+
# [id] The ID for this photo
|
12
|
+
# [title] The title of this photo
|
13
|
+
# [description] The description of this photo
|
14
|
+
# [secret] This photo's secret (used for sharing photo without permissions checking)
|
15
|
+
# [comment_count] Count of the comments attached to this photo
|
16
|
+
# [url] This photo's page on Flickr
|
17
|
+
# [square] The tiny square representation of this photo
|
18
|
+
# [thumbnail] The thumbnail for this photo
|
19
|
+
# [small] The small representation of this photo
|
20
|
+
# [medium] The medium representation of this photo
|
21
|
+
# [large] The large representation of this photo
|
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
|
25
|
+
#
|
26
|
+
# == Associations
|
27
|
+
#
|
28
|
+
# [images] The underlying images for this photo.
|
29
|
+
# [tags] The tags for this photo.
|
30
|
+
# [comments] The comments associated with this photo
|
31
|
+
#
|
32
|
+
class Photo
|
33
|
+
|
34
|
+
# Available sizes for this photo
|
35
|
+
SIZES = [:square, :thumbnail, :small, :medium, :large, :original]
|
36
|
+
|
37
|
+
include Fleakr::Support::Object
|
38
|
+
extend Forwardable
|
39
|
+
|
40
|
+
def_delegators :context, :next, :previous
|
41
|
+
|
42
|
+
flickr_attribute :id, :from => ['@id', 'photoid']
|
43
|
+
flickr_attribute :title, :description, :secret, :posted, :taken, :url
|
44
|
+
flickr_attribute :farm_id, :from => '@farm'
|
45
|
+
flickr_attribute :server_id, :from => '@server'
|
46
|
+
flickr_attribute :owner_id, :from => ['@owner', 'owner@nsid']
|
47
|
+
flickr_attribute :updated, :from => '@lastupdate'
|
48
|
+
flickr_attribute :comment_count, :from => 'comments'
|
49
|
+
|
50
|
+
# TODO:
|
51
|
+
# * visibility
|
52
|
+
# * editability
|
53
|
+
# * usage
|
54
|
+
|
55
|
+
find_all :by_set_id, :using => :photoset_id, :call => 'photosets.getPhotos', :path => 'photoset/photo'
|
56
|
+
find_all :by_user_id, :call => 'people.getPublicPhotos', :path => 'photos/photo'
|
57
|
+
find_all :by_group_id, :call => 'groups.pools.getPhotos', :path => 'photos/photo'
|
58
|
+
|
59
|
+
find_one :by_id, :using => :photo_id, :call => 'photos.getInfo'
|
60
|
+
|
61
|
+
lazily_load :posted, :taken, :updated, :comment_count, :url, :description, :with => :load_info
|
62
|
+
|
63
|
+
has_many :images, :tags, :comments
|
64
|
+
|
65
|
+
# Upload the photo specified by <tt>filename</tt> to the user's Flickr account. When uploading,
|
66
|
+
# there are several options available (none are required):
|
67
|
+
#
|
68
|
+
# [:title] The title for this photo. Any string is allowed.
|
69
|
+
# [:description] The description for this photo. Any string is allowed.
|
70
|
+
# [:tags] A collection of tags for this photo. This can be a string or array of strings.
|
71
|
+
# [:viewable_by] Who can view this photo? Acceptable values are one of <tt>:everyone</tt>,
|
72
|
+
# <tt>:friends</tt> or <tt>:family</tt>. This can also take an array of values
|
73
|
+
# (e.g. <tt>[:friends, :family]</tt>) to make it viewable by friends and family.
|
74
|
+
# [:level] The safety level of this photo. Acceptable values are one of <tt>:safe</tt>,
|
75
|
+
# <tt>:moderate</tt>, or <tt>:restricted</tt>.
|
76
|
+
# [:type] The type of image this is. Acceptable values are one of <tt>:photo</tt>,
|
77
|
+
# <tt>:screenshot</tt>, or <tt>:other</tt>.
|
78
|
+
# [:hide?] Should this photo be hidden from public searches? Takes a boolean.
|
79
|
+
#
|
80
|
+
def self.upload(filename, options = {})
|
81
|
+
response = Fleakr::Api::UploadRequest.with_response!(filename, :create, options)
|
82
|
+
photo = Photo.new(response.body)
|
83
|
+
Photo.find_by_id(photo.id)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Replace the current photo's image with the one specified by filename. This
|
87
|
+
# call requires authentication.
|
88
|
+
#
|
89
|
+
def replace_with(filename)
|
90
|
+
response = Fleakr::Api::UploadRequest.with_response!(filename, :update, :photo_id => self.id)
|
91
|
+
self.populate_from(response.body)
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
# TODO: Refactor this to remove duplication w/ User#load_info - possibly in the lazily_load class method
|
96
|
+
def load_info # :nodoc:
|
97
|
+
response = Fleakr::Api::MethodRequest.with_response!('photos.getInfo', :photo_id => self.id)
|
98
|
+
self.populate_from(response.body)
|
99
|
+
end
|
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
|
+
|
114
|
+
# When was this photo posted?
|
115
|
+
#
|
116
|
+
def posted_at
|
117
|
+
Time.at(posted.to_i)
|
118
|
+
end
|
119
|
+
|
120
|
+
# When was this photo taken?
|
121
|
+
#
|
122
|
+
def taken_at
|
123
|
+
Time.parse(taken)
|
124
|
+
end
|
125
|
+
|
126
|
+
# When was this photo last updated? This includes addition of tags and other metadata.
|
127
|
+
#
|
128
|
+
def updated_at
|
129
|
+
Time.at(updated.to_i)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Create methods to access image sizes by name
|
133
|
+
SIZES.each do |size|
|
134
|
+
define_method(size) do
|
135
|
+
images_by_size[size]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
def images_by_size
|
141
|
+
image_sizes = SIZES.inject({}) {|l,o| l.merge(o => nil)}
|
142
|
+
self.images.inject(image_sizes) {|l,o| l.merge!(o.size.downcase.to_sym => o) }
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -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
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects # :nodoc:
|
3
|
+
class Search
|
4
|
+
|
5
|
+
# Create a new search
|
6
|
+
def initialize(search_options)
|
7
|
+
@search_options = search_options
|
8
|
+
end
|
9
|
+
|
10
|
+
# Retrieve search results from the API
|
11
|
+
def results
|
12
|
+
@results ||= begin
|
13
|
+
response = Fleakr::Api::MethodRequest.with_response!('photos.search', parameters)
|
14
|
+
(response.body/'rsp/photos/photo').map {|p| Photo.new(p) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def tag_list
|
20
|
+
Array(@search_options[:tags]).join(',')
|
21
|
+
end
|
22
|
+
|
23
|
+
def parameters
|
24
|
+
@search_options.merge!(:tags => tag_list) if tag_list.length > 0
|
25
|
+
@search_options
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects # :nodoc:
|
3
|
+
|
4
|
+
# = Set
|
5
|
+
#
|
6
|
+
# == Attributes
|
7
|
+
#
|
8
|
+
# [id] The ID for this photoset
|
9
|
+
# [title] The title of this photoset
|
10
|
+
# [description] The description of this set
|
11
|
+
# [count] Count of photos in this set
|
12
|
+
#
|
13
|
+
# == Associations
|
14
|
+
#
|
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
|
17
|
+
#
|
18
|
+
class Set
|
19
|
+
|
20
|
+
include Fleakr::Support::Object
|
21
|
+
|
22
|
+
has_many :photos, :comments
|
23
|
+
|
24
|
+
flickr_attribute :id, :title, :description
|
25
|
+
flickr_attribute :count, :from => '@photos'
|
26
|
+
|
27
|
+
find_all :by_user_id, :call => 'photosets.getList', :path => 'photosets/photoset'
|
28
|
+
|
29
|
+
# Save all photos in this set to the specified directory for the specified size. Allowed
|
30
|
+
# Sizes include <tt>:square</tt>, <tt>:small</tt>, <tt>:thumbnail</tt>, <tt>:medium</tt>,
|
31
|
+
# <tt>:large</tt>, and <tt>:original</tt>. When saving the set, this method will create
|
32
|
+
# a subdirectory based on the set's title.
|
33
|
+
#
|
34
|
+
def save_to(path, size)
|
35
|
+
target = "#{path}/#{self.title}"
|
36
|
+
FileUtils.mkdir(target) unless File.exist?(target)
|
37
|
+
|
38
|
+
self.photos.each_with_index do |photo, index|
|
39
|
+
image = photo.send(size)
|
40
|
+
image.save_to(target, file_prefix(index)) unless image.nil?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def file_prefix(index) # :nodoc:
|
45
|
+
sprintf("%0#{self.count.length}d_", (index + 1))
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -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
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects # :nodoc:
|
3
|
+
|
4
|
+
# = User
|
5
|
+
#
|
6
|
+
# == Accessors
|
7
|
+
#
|
8
|
+
# This class maps directly onto the flickr.people.* API methods and provides the following attributes
|
9
|
+
# for a user:
|
10
|
+
#
|
11
|
+
# [id] The ID for this user (also referred to as the NSID in the API docs)
|
12
|
+
# [username] This user's username
|
13
|
+
# [name] This user's full name (if entered)
|
14
|
+
# [location] This user's location (if entered)
|
15
|
+
# [photos_url] The direct URL to this user's photostream
|
16
|
+
# [profile_url] The direct URL to this user's profile
|
17
|
+
# [photos_count] The number of photos that this user has uploaded
|
18
|
+
# [icon_url] This user's buddy icon (or a default one if an icon wasn't uploaded)
|
19
|
+
# [pro?] Does this user have a pro account?
|
20
|
+
# [admin?] Is this user an admin?
|
21
|
+
#
|
22
|
+
# == Associations
|
23
|
+
#
|
24
|
+
# The User class is pretty central to many of the other data available across the system, so there are a
|
25
|
+
# few associations available to a user:
|
26
|
+
#
|
27
|
+
# [sets] A list of this user's public sets (newest first). See Fleakr::Objects::Set for more information.
|
28
|
+
# [groups] A list of this user's public groups. See Fleakr::Objects::Group.
|
29
|
+
# [photos] A list of this user's public photos (newest first). See Fleakr::Objects::Photo.
|
30
|
+
# [contacts] A list of this user's contacts - these are simply User objects
|
31
|
+
# [tags] The tags associated with this user
|
32
|
+
#
|
33
|
+
# == Examples
|
34
|
+
#
|
35
|
+
# Access to a specific user is typically done through the Fleakr.user method:
|
36
|
+
#
|
37
|
+
# user = Fleakr.user('brownout')
|
38
|
+
# user.id
|
39
|
+
# user.username
|
40
|
+
# user.sets
|
41
|
+
# user.contacts
|
42
|
+
#
|
43
|
+
class User
|
44
|
+
|
45
|
+
include Fleakr::Support::Object
|
46
|
+
|
47
|
+
flickr_attribute :id, :from => 'user@nsid'
|
48
|
+
flickr_attribute :username, :location
|
49
|
+
flickr_attribute :name, :from => 'person/realname'
|
50
|
+
flickr_attribute :photos_url, :from => 'person/photosurl'
|
51
|
+
flickr_attribute :profile_url, :from => 'person/profileurl'
|
52
|
+
flickr_attribute :photos_count, :from => 'person/photos/count'
|
53
|
+
flickr_attribute :icon_server, :from => 'person@iconserver'
|
54
|
+
flickr_attribute :icon_farm, :from => 'person@iconfarm'
|
55
|
+
flickr_attribute :pro, :from => 'person@ispro'
|
56
|
+
flickr_attribute :admin, :from => 'person@isadmin'
|
57
|
+
|
58
|
+
has_many :sets, :groups, :photos, :contacts, :tags
|
59
|
+
|
60
|
+
find_one :by_username, :call => 'people.findByUsername'
|
61
|
+
find_one :by_email, :using => :find_email, :call => 'people.findByEmail'
|
62
|
+
find_one :by_id, :using => :user_id, :call => 'people.getInfo'
|
63
|
+
|
64
|
+
lazily_load :name, :photos_url, :profile_url, :photos_count, :location, :with => :load_info
|
65
|
+
lazily_load :icon_server, :icon_farm, :pro, :admin, :with => :load_info
|
66
|
+
|
67
|
+
scoped_search
|
68
|
+
|
69
|
+
# Is this a pro account?
|
70
|
+
def pro?
|
71
|
+
(self.pro.to_i == 0) ? false : true
|
72
|
+
end
|
73
|
+
|
74
|
+
# Is this user an admin?
|
75
|
+
def admin?
|
76
|
+
(self.admin.to_i == 0) ? false : true
|
77
|
+
end
|
78
|
+
|
79
|
+
# This user's buddy icon
|
80
|
+
def icon_url
|
81
|
+
if self.icon_server.to_i > 0
|
82
|
+
"http://farm#{self.icon_farm}.static.flickr.com/#{self.icon_server}/buddyicons/#{self.id}.jpg"
|
83
|
+
else
|
84
|
+
'http://www.flickr.com/images/buddyicon.jpg'
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def load_info # :nodoc:
|
89
|
+
response = Fleakr::Api::MethodRequest.with_response!('people.getInfo', :user_id => self.id)
|
90
|
+
self.populate_from(response.body)
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'fleakr/objects/authentication_token'
|
2
|
+
require 'fleakr/objects/contact'
|
3
|
+
require 'fleakr/objects/error'
|
4
|
+
require 'fleakr/objects/group'
|
5
|
+
require 'fleakr/objects/image'
|
6
|
+
require 'fleakr/objects/photo_context'
|
7
|
+
require 'fleakr/objects/photo'
|
8
|
+
require 'fleakr/objects/comment'
|
9
|
+
require 'fleakr/objects/tag'
|
10
|
+
require 'fleakr/objects/search'
|
11
|
+
require 'fleakr/objects/set'
|
12
|
+
require 'fleakr/objects/user'
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Support # :nodoc:all
|
3
|
+
class Attribute
|
4
|
+
|
5
|
+
# TODO: Refactor the location / attribute logic into a Source class
|
6
|
+
|
7
|
+
attr_reader :name, :sources
|
8
|
+
|
9
|
+
def initialize(name, sources = nil)
|
10
|
+
@name = name.to_sym
|
11
|
+
|
12
|
+
@sources = Array(sources)
|
13
|
+
@sources << @name.to_s if @sources.empty?
|
14
|
+
end
|
15
|
+
|
16
|
+
def split(source)
|
17
|
+
location, attribute = source.split('@')
|
18
|
+
location = self.name.to_s if location.blank?
|
19
|
+
|
20
|
+
[location, attribute]
|
21
|
+
end
|
22
|
+
|
23
|
+
def node_for(document, source)
|
24
|
+
document.at(location(source)) || document.search("//[@#{attribute(source)}]").first
|
25
|
+
end
|
26
|
+
|
27
|
+
def attribute(source)
|
28
|
+
location, attribute = source.split('@')
|
29
|
+
attribute || location
|
30
|
+
end
|
31
|
+
|
32
|
+
def location(source)
|
33
|
+
split(source).first
|
34
|
+
end
|
35
|
+
|
36
|
+
def value_from(document)
|
37
|
+
values = sources.map do |source|
|
38
|
+
node = node_for(document, source)
|
39
|
+
(node.attributes[attribute(source)] || node.inner_text) unless node.nil?
|
40
|
+
end
|
41
|
+
values.compact.first
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Support # :nodoc:all
|
3
|
+
module Object
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
|
7
|
+
def attributes
|
8
|
+
@attributes ||= []
|
9
|
+
end
|
10
|
+
|
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
|
18
|
+
end
|
19
|
+
|
20
|
+
def has_many(*attributes)
|
21
|
+
class_name = self.name
|
22
|
+
|
23
|
+
attributes.each do |attribute|
|
24
|
+
target = "Fleakr::Objects::#{attribute.to_s.classify}"
|
25
|
+
finder_attribute = "#{class_name.demodulize.underscore}_id"
|
26
|
+
|
27
|
+
class_eval <<-CODE
|
28
|
+
def #{attribute}
|
29
|
+
@#{attribute} ||= #{target}.send("find_all_by_#{finder_attribute}".to_sym, self.id)
|
30
|
+
end
|
31
|
+
CODE
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def find_all(condition, options)
|
36
|
+
attribute = options[:using].nil? ? condition.to_s.sub(/^by_/, '') : options[:using]
|
37
|
+
target_class = options[:class_name].nil? ? self.name : "Fleakr::Objects::#{options[:class_name]}"
|
38
|
+
|
39
|
+
class_eval <<-CODE
|
40
|
+
def self.find_all_#{condition}(value, options = {})
|
41
|
+
options.merge!(:#{attribute} => value)
|
42
|
+
|
43
|
+
response = Fleakr::Api::MethodRequest.with_response!('#{options[:call]}', options)
|
44
|
+
(response.body/'rsp/#{options[:path]}').map {|e| #{target_class}.new(e) }
|
45
|
+
end
|
46
|
+
CODE
|
47
|
+
end
|
48
|
+
|
49
|
+
def find_one(condition, options)
|
50
|
+
attribute = options[:using].nil? ? condition.to_s.sub(/^by_/, '') : options[:using]
|
51
|
+
|
52
|
+
class_eval <<-CODE
|
53
|
+
def self.find_#{condition}(value, options = {})
|
54
|
+
options.merge!(:#{attribute} => value)
|
55
|
+
|
56
|
+
response = Fleakr::Api::MethodRequest.with_response!('#{options[:call]}', options)
|
57
|
+
#{self.name}.new(response.body)
|
58
|
+
end
|
59
|
+
CODE
|
60
|
+
end
|
61
|
+
|
62
|
+
def scoped_search
|
63
|
+
key = "#{self.name.demodulize.underscore.downcase}_id".to_sym
|
64
|
+
|
65
|
+
class_eval <<-CODE
|
66
|
+
def search(search_text)
|
67
|
+
Fleakr::Objects::Search.new(:text => search_text, :#{key} => self.id).results
|
68
|
+
end
|
69
|
+
CODE
|
70
|
+
end
|
71
|
+
|
72
|
+
def lazily_load(*attributes)
|
73
|
+
options = attributes.extract_options!
|
74
|
+
|
75
|
+
attributes.each do |attribute|
|
76
|
+
class_eval <<-CODE
|
77
|
+
def #{attribute}_with_loading
|
78
|
+
self.send(:#{options[:with]}) if @#{attribute}.nil?
|
79
|
+
#{attribute}_without_loading
|
80
|
+
end
|
81
|
+
alias_method_chain :#{attribute}, :loading
|
82
|
+
CODE
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
module InstanceMethods
|
89
|
+
|
90
|
+
def initialize(document = nil)
|
91
|
+
self.populate_from(document) unless document.nil?
|
92
|
+
end
|
93
|
+
|
94
|
+
def populate_from(document)
|
95
|
+
self.class.attributes.each do |attribute|
|
96
|
+
value = attribute.value_from(document)
|
97
|
+
self.send("#{attribute.name}=".to_sym, value) unless value.nil?
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.included(other)
|
104
|
+
other.send(:extend, Fleakr::Support::Object::ClassMethods)
|
105
|
+
other.send(:include, Fleakr::Support::Object::InstanceMethods)
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|