latompa-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 +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
 
| 
         @@ -0,0 +1,148 @@ 
     | 
|
| 
      
 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 
     | 
    
         
            +
                  flickr_attribute :originalsecret
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  # TODO:
         
     | 
| 
      
 52 
     | 
    
         
            +
                  # * visibility
         
     | 
| 
      
 53 
     | 
    
         
            +
                  # * editability
         
     | 
| 
      
 54 
     | 
    
         
            +
                  # * usage
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  find_all :by_set_id, :using => :photoset_id, :call => 'photosets.getPhotos', :path => 'photoset/photo'
         
     | 
| 
      
 57 
     | 
    
         
            +
                  find_all :by_user_id, :call => 'people.getPublicPhotos', :path => 'photos/photo'
         
     | 
| 
      
 58 
     | 
    
         
            +
                  find_all :by_group_id, :call => 'groups.pools.getPhotos', :path => 'photos/photo'
         
     | 
| 
      
 59 
     | 
    
         
            +
                  
         
     | 
| 
      
 60 
     | 
    
         
            +
                  find_one :by_id, :using => :photo_id, :call => 'photos.getInfo'
         
     | 
| 
      
 61 
     | 
    
         
            +
                  
         
     | 
| 
      
 62 
     | 
    
         
            +
                  lazily_load :posted, :taken, :updated, :comment_count, :url, :description, :with => :load_info
         
     | 
| 
      
 63 
     | 
    
         
            +
                  
         
     | 
| 
      
 64 
     | 
    
         
            +
                  has_many :images, :tags, :comments
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  # Upload the photo specified by <tt>filename</tt> to the user's Flickr account. When uploading,
         
     | 
| 
      
 67 
     | 
    
         
            +
                  # there are several options available (none are required):
         
     | 
| 
      
 68 
     | 
    
         
            +
                  #
         
     | 
| 
      
 69 
     | 
    
         
            +
                  # [:title] The title for this photo. Any string is allowed.
         
     | 
| 
      
 70 
     | 
    
         
            +
                  # [:description] The description for this photo. Any string is allowed.
         
     | 
| 
      
 71 
     | 
    
         
            +
                  # [:tags] A collection of tags for this photo. This can be a string or array of strings.
         
     | 
| 
      
 72 
     | 
    
         
            +
                  # [:viewable_by] Who can view this photo?  Acceptable values are one of <tt>:everyone</tt>,
         
     | 
| 
      
 73 
     | 
    
         
            +
                  #                <tt>:friends</tt> or <tt>:family</tt>.  This can also take an array of values
         
     | 
| 
      
 74 
     | 
    
         
            +
                  #                (e.g. <tt>[:friends, :family]</tt>) to make it viewable by friends and family.
         
     | 
| 
      
 75 
     | 
    
         
            +
                  # [:level] The safety level of this photo.  Acceptable values are one of <tt>:safe</tt>,
         
     | 
| 
      
 76 
     | 
    
         
            +
                  #          <tt>:moderate</tt>, or <tt>:restricted</tt>.
         
     | 
| 
      
 77 
     | 
    
         
            +
                  # [:type] The type of image this is.  Acceptable values are one of <tt>:photo</tt>,
         
     | 
| 
      
 78 
     | 
    
         
            +
                  #         <tt>:screenshot</tt>, or <tt>:other</tt>.
         
     | 
| 
      
 79 
     | 
    
         
            +
                  # [:hide?] Should this photo be hidden from public searches? Takes a boolean.
         
     | 
| 
      
 80 
     | 
    
         
            +
                  #
         
     | 
| 
      
 81 
     | 
    
         
            +
                  def self.upload(filename, options = {})
         
     | 
| 
      
 82 
     | 
    
         
            +
                    response = Fleakr::Api::UploadRequest.with_response!(filename, :create, options)
         
     | 
| 
      
 83 
     | 
    
         
            +
                    photo = Photo.new(response.body)
         
     | 
| 
      
 84 
     | 
    
         
            +
                    Photo.find_by_id(photo.id)
         
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  # Replace the current photo's image with the one specified by filename.  This 
         
     | 
| 
      
 88 
     | 
    
         
            +
                  # call requires authentication.
         
     | 
| 
      
 89 
     | 
    
         
            +
                  #
         
     | 
| 
      
 90 
     | 
    
         
            +
                  def replace_with(filename)
         
     | 
| 
      
 91 
     | 
    
         
            +
                    response = Fleakr::Api::UploadRequest.with_response!(filename, :update, :photo_id => self.id)
         
     | 
| 
      
 92 
     | 
    
         
            +
                    self.populate_from(response.body)
         
     | 
| 
      
 93 
     | 
    
         
            +
                    self
         
     | 
| 
      
 94 
     | 
    
         
            +
                  end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                  # TODO: Refactor this to remove duplication w/ User#load_info - possibly in the lazily_load class method
         
     | 
| 
      
 97 
     | 
    
         
            +
                  def load_info # :nodoc:
         
     | 
| 
      
 98 
     | 
    
         
            +
                    response = Fleakr::Api::MethodRequest.with_response!('photos.getInfo', :photo_id => self.id)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    self.populate_from(response.body)
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                  def context # :nodoc:
         
     | 
| 
      
 103 
     | 
    
         
            +
                    @context ||= begin
         
     | 
| 
      
 104 
     | 
    
         
            +
                      response = Fleakr::Api::MethodRequest.with_response!('photos.getContext', :photo_id => self.id)
         
     | 
| 
      
 105 
     | 
    
         
            +
                      PhotoContext.new(response.body)
         
     | 
| 
      
 106 
     | 
    
         
            +
                    end
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                  # The user who uploaded this photo.  See Fleakr::Objects::User for additional information.
         
     | 
| 
      
 110 
     | 
    
         
            +
                  # 
         
     | 
| 
      
 111 
     | 
    
         
            +
                  def owner
         
     | 
| 
      
 112 
     | 
    
         
            +
                    @owner ||= User.find_by_id(owner_id)
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                  # When was this photo posted?
         
     | 
| 
      
 116 
     | 
    
         
            +
                  #
         
     | 
| 
      
 117 
     | 
    
         
            +
                  def posted_at
         
     | 
| 
      
 118 
     | 
    
         
            +
                    Time.at(posted.to_i)
         
     | 
| 
      
 119 
     | 
    
         
            +
                  end
         
     | 
| 
      
 120 
     | 
    
         
            +
                  
         
     | 
| 
      
 121 
     | 
    
         
            +
                  # When was this photo taken?
         
     | 
| 
      
 122 
     | 
    
         
            +
                  #
         
     | 
| 
      
 123 
     | 
    
         
            +
                  def taken_at
         
     | 
| 
      
 124 
     | 
    
         
            +
                    Time.parse(taken)
         
     | 
| 
      
 125 
     | 
    
         
            +
                  end
         
     | 
| 
      
 126 
     | 
    
         
            +
                  
         
     | 
| 
      
 127 
     | 
    
         
            +
                  # When was this photo last updated?  This includes addition of tags and other metadata.
         
     | 
| 
      
 128 
     | 
    
         
            +
                  #
         
     | 
| 
      
 129 
     | 
    
         
            +
                  def updated_at
         
     | 
| 
      
 130 
     | 
    
         
            +
                    Time.at(updated.to_i)
         
     | 
| 
      
 131 
     | 
    
         
            +
                  end
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                  # Create methods to access image sizes by name
         
     | 
| 
      
 134 
     | 
    
         
            +
                  SIZES.each do |size|
         
     | 
| 
      
 135 
     | 
    
         
            +
                    define_method(size) do
         
     | 
| 
      
 136 
     | 
    
         
            +
                      images_by_size[size]
         
     | 
| 
      
 137 
     | 
    
         
            +
                    end
         
     | 
| 
      
 138 
     | 
    
         
            +
                  end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                  private
         
     | 
| 
      
 141 
     | 
    
         
            +
                  def images_by_size
         
     | 
| 
      
 142 
     | 
    
         
            +
                    image_sizes = SIZES.inject({}) {|l,o| l.merge(o => nil)}
         
     | 
| 
      
 143 
     | 
    
         
            +
                    self.images.inject(image_sizes) {|l,o| l.merge!(o.size.downcase.to_sym => o) }
         
     | 
| 
      
 144 
     | 
    
         
            +
                  end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
            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, :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
         
     |