reagent-fleakr 0.1.0 → 0.1.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.markdown CHANGED
@@ -6,12 +6,50 @@ A teeny tiny gem to interface with Flickr photostreams
6
6
 
7
7
  ## Installation
8
8
 
9
- sudo gem install fleakr
9
+ sudo gem install reagent-fleakr --source=http://gems.github.com
10
+
11
+ Or ...
12
+
13
+ $ git clone git://github.com/reagent/fleakr.git
14
+ $ cd fleakr
15
+ $ rake gem && sudo gem install pkg/fleakr-<version>.gem
10
16
 
11
17
  ## Usage
12
18
 
13
- require 'fleakr'
19
+ Before doing anything, require the library:
20
+
21
+ >> require 'rubygems'
22
+ >> require 'fleakr'
23
+
24
+ Then, set your API key (only need to do this once per session):
25
+
26
+ >> Fleakr::Request.api_key = '<your api key here>'
27
+
28
+ Find a user by username:
29
+
30
+ >> user = Fleakr::User.find_by_username('the decapitator')
31
+ => #<Fleakr::User:0x692648 @username="the decapitator", @id="21775151@N06">
32
+
33
+ And that user's associated sets:
34
+
35
+ >> user.sets
36
+ => [#<Fleakr::Set:0x671358 @title="The Decapitator", @description="">,
37
+ #<Fleakr::Set:0x66d898 @title="londonpaper hijack", ...
38
+
39
+ You can also grab photos for a particular set:
40
+
41
+ >> user.sets.first
42
+ => #<Fleakr::Set:0x1195bbc @title="The Decapitator", @id="72157603480986566", @description="">
43
+ >> user.sets.first.photos.first
44
+ => #<Fleakr::Photo:0x1140108 ... >
45
+ >> user.sets.first.photos.first.title
46
+ => "Untitled1"
47
+
48
+ ## TODO
14
49
 
50
+ * Refactor the attribute retrieval to something more reusable
51
+ * Implement remaining bits of person, photoset, and photo-releated APIs
52
+
15
53
  ## License
16
54
 
17
55
  Copyright (c) 2008 Patrick Reagan (reaganpr@gmail.com)
@@ -0,0 +1,12 @@
1
+ module Fleakr
2
+ class Error
3
+
4
+ attr_accessor :code, :message
5
+
6
+ def initialize(code, message)
7
+ self.code = code
8
+ self.message = message
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ module Fleakr
2
+ class Photo
3
+
4
+ def self.find_all_by_photoset_id(photoset_id)
5
+ response = Request.with_response!('photosets.getPhotos', :photoset_id => photoset_id)
6
+ (response.body/'rsp/photoset/photo').map do |photo_body|
7
+ Photo.new(photo_body)
8
+ end
9
+ end
10
+
11
+ def initialize(photo_body)
12
+ @response_body = photo_body
13
+ end
14
+
15
+ def title
16
+ (@response_body).attributes['title']
17
+ end
18
+
19
+ end
20
+ end
@@ -1,6 +1,8 @@
1
1
  module Fleakr
2
2
  class Request
3
3
 
4
+ class ApiError < StandardError; end
5
+
4
6
  def self.api_key=(key)
5
7
  @api_key = key
6
8
  end
@@ -9,6 +11,15 @@ module Fleakr
9
11
  @api_key
10
12
  end
11
13
 
14
+ def self.with_response!(method, additional_parameters = {})
15
+ request = Request.new(method, additional_parameters)
16
+ response = request.send
17
+
18
+ raise(ApiError, "Code: #{response.error.code} - #{response.error.message}") if response.error?
19
+
20
+ response
21
+ end
22
+
12
23
  def endpoint_uri
13
24
  uri = URI.parse('http://api.flickr.com/services/rest/')
14
25
  uri.query = self.query_parameters
@@ -16,7 +27,7 @@ module Fleakr
16
27
  end
17
28
 
18
29
  def query_parameters
19
- @parameters.map {|key,value| "#{key}=#{value}" }.join('&')
30
+ @parameters.map {|key,value| "#{key}=#{CGI.escape(value)}" }.join('&')
20
31
  end
21
32
 
22
33
  def initialize(method, additional_parameters = {})
@@ -13,5 +13,12 @@ module Fleakr
13
13
  (self.body/'rsp').attr('stat') != 'ok'
14
14
  end
15
15
 
16
+ def error
17
+ if self.error?
18
+ node = (self.body/'rsp/err')
19
+ Error.new(node.attr('code'), node.attr('msg'))
20
+ end
21
+ end
22
+
16
23
  end
17
24
  end
data/lib/fleakr/set.rb CHANGED
@@ -1,13 +1,14 @@
1
1
  module Fleakr
2
2
  class Set
3
3
 
4
- attr_accessor :title, :description
4
+ attr_accessor :id, :title, :description
5
5
 
6
6
  def self.find_all_by_user_id(user_id)
7
- response = Request.new('photosets.getList', :user_id => user_id).send
7
+ response = Request.with_response!('photosets.getList', :user_id => user_id)
8
8
 
9
- (response.body/'photosets/photoset').map do |flickr_set|
9
+ (response.body/'rsp/photosets/photoset').map do |flickr_set|
10
10
  set = Set.new
11
+ set.id = (flickr_set).attributes['id']
11
12
  set.title = (flickr_set/'title').inner_text
12
13
  set.description = (flickr_set/'description').inner_text
13
14
  set
@@ -15,5 +16,9 @@ module Fleakr
15
16
 
16
17
  end
17
18
 
19
+ def photos
20
+ @photos ||= Photo.find_all_by_photoset_id(self.id)
21
+ end
22
+
18
23
  end
19
24
  end
data/lib/fleakr/user.rb CHANGED
@@ -4,13 +4,23 @@ module Fleakr
4
4
  attr_accessor :id, :username
5
5
 
6
6
  def self.find_by_username(username)
7
- response = Fleakr::Request.new('people.findByUsername', :username => username).send
8
-
9
- user = User.new
10
- user.id = (response.body/'rsp/user').attr('id')
11
- user.username = (response.body/'rsp/user/username').inner_text
12
-
13
- user
7
+ response = Request.with_response!('people.findByUsername', :username => username)
8
+ User.new(response.body)
9
+ end
10
+
11
+ # flickr_attribute :id, :from => 'user', :attribute => 'nsid'
12
+ # flickr_attribute :username, :from => 'user/username', :text => true
13
+
14
+ def initialize(response_body)
15
+ @response_body = (response_body/'rsp')
16
+ end
17
+
18
+ def id
19
+ (@response_body/'user').attr('id')
20
+ end
21
+
22
+ def username
23
+ (@response_body/'user/username').inner_text
14
24
  end
15
25
 
16
26
  def sets
@@ -3,7 +3,7 @@ module Fleakr
3
3
 
4
4
  MAJOR = 0
5
5
  MINOR = 1
6
- TINY = 0
6
+ TINY = 1
7
7
 
8
8
  def self.to_s
9
9
  [MAJOR, MINOR, TINY].join('.')
data/lib/fleakr.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  $:.unshift(File.dirname(__FILE__))
2
2
 
3
3
  require 'uri'
4
+ require 'cgi'
4
5
  require 'net/http'
5
6
  require 'hpricot'
6
7
 
@@ -1,13 +1,13 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
2
  <rsp stat="ok">
3
- <photosets>
4
- <photoset videos="0" primary="3044180117" farm="4" photos="138" id="72157609490909659" server="3012" secret="01cd1a741d">
5
- <title>Second Set</title>
6
- <description>This is the second set.</description>
7
- </photoset>
8
- <photoset videos="0" primary="2988511085" farm="4" photos="139" id="72157608538140671" server="3241" secret="a7b90926ba">
9
- <title>First Set</title>
10
- <description>This is the first set.</description>
11
- </photoset>
12
- </photosets>
3
+ <photosets>
4
+ <photoset videos="0" primary="3044180117" farm="4" photos="138" id="72157609490909659" server="3012" secret="01cd1a741d">
5
+ <title>Second Set</title>
6
+ <description>This is the second set.</description>
7
+ </photoset>
8
+ <photoset videos="0" primary="2988511085" farm="4" photos="139" id="72157608538140671" server="3241" secret="a7b90926ba">
9
+ <title>First Set</title>
10
+ <description>This is the first set.</description>
11
+ </photoset>
12
+ </photosets>
13
13
  </rsp>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <rsp stat="ok">
3
+ <photoset id="72157609490909659" primary="3044180117" owner="31066442@N69" ownername="frootpantz" page="1" per_page="500" perpage="500" pages="1" total="138">
4
+ <photo id="3044163577" secret="fa27e5a824" server="3153" farm="4" title="Photo #1" isprimary="0" />
5
+ <photo id="3045001128" secret="a8c0e51b39" server="3204" farm="4" title="Photo #2" isprimary="0" />
6
+ </photoset>
7
+ </rsp>
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ module Fleakr
4
+ class ErrorTest < Test::Unit::TestCase
5
+
6
+ describe "An instance of the Error class" do
7
+
8
+ it "should have a code and a message" do
9
+ error = Error.new('1', 'User not found')
10
+
11
+ error.code.should == '1'
12
+ error.message.should == 'User not found'
13
+ end
14
+
15
+ end
16
+
17
+
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ module Fleakr
4
+ class PhotoTest < Test::Unit::TestCase
5
+
6
+ describe "The Photo class" do
7
+
8
+ context "when finding all photos by photoset ID" do
9
+
10
+ before do
11
+ mock_request_cycle :for => 'photosets.getPhotos', :with => {:photoset_id => '1'}
12
+ @photos = Photo.find_all_by_photoset_id('1')
13
+ end
14
+
15
+ it "should have the correct number of items" do
16
+ @photos.length.should == 2
17
+ end
18
+
19
+ it "should have the proper title" do
20
+ @photos.map {|p| p.title}.should == ['Photo #1', 'Photo #2']
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+ end
@@ -29,6 +29,11 @@ module Fleakr
29
29
 
30
30
  request.query_parameters.split('&').sort.should == expected
31
31
  end
32
+
33
+ it "should escape the keys and values in the parameter list" do
34
+ request = Request.new('flickr.people.findByUsername', :username => 'the decapitator')
35
+ request.query_parameters.split('&').include?("username=#{CGI.escape('the decapitator')}").should be(true)
36
+ end
32
37
 
33
38
  it "should translate a shorthand API call" do
34
39
  request = Request.new('people.findByUsername')
@@ -71,6 +76,22 @@ module Fleakr
71
76
  request.send.should == response_stub
72
77
  end
73
78
 
79
+ it "should be able to make a full request and response cycle" do
80
+ response = stub(:error? => false)
81
+ Response.expects(:new).with(kind_of(String)).returns(response)
82
+
83
+ Request.with_response!('flickr.people.findByUsername', :username => 'foobar').should == response
84
+ end
85
+
86
+ it "should raise an exception when the full request / response cycle has errors" do
87
+ response = stub(:error? => true, :error => stub(:code => '1', :message => 'User not found'))
88
+ Response.stubs(:new).with(kind_of(String)).returns(response)
89
+
90
+ lambda do
91
+ Request.with_response!('flickr.people.findByUsername', :username => 'foobar')
92
+ end.should raise_error(Fleakr::Request::ApiError)
93
+ end
94
+
74
95
  end
75
96
 
76
97
  end
@@ -29,6 +29,19 @@ module Fleakr
29
29
 
30
30
  response.error?.should be(true)
31
31
  end
32
+
33
+ it "should not have an error if there are no errors in the XML" do
34
+ response = Response.new(read_fixture('people.findByUsername'))
35
+ response.error.should be(nil)
36
+ end
37
+
38
+ it "should have an error if there is an error in the response" do
39
+ response_xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<rsp stat=\"fail\">\n\t<err code=\"1\" msg=\"User not found\" />\n</rsp>\n"
40
+ response = Response.new(response_xml)
41
+
42
+ response.error.code.should == '1'
43
+ response.error.message.should == 'User not found'
44
+ end
32
45
 
33
46
  end
34
47
 
@@ -2,35 +2,59 @@ require File.dirname(__FILE__) + '/../test_helper'
2
2
 
3
3
  module Fleakr
4
4
  class SetTest < Test::Unit::TestCase
5
-
6
- def mock_request_cycle(options)
7
- response = stub(:body => read_fixture(options[:for]))
8
- Request.expects(:new).with(options[:for], options[:with]).returns(stub(:send => response))
9
- end
10
-
5
+
11
6
  describe "The Set class" do
12
-
13
7
  context "When finding all sets for a user_id" do
14
8
  before do
15
9
  user_id = '31066442@N69'
16
10
  mock_request_cycle :for => 'photosets.getList', :with => {:user_id => user_id}
17
-
11
+
18
12
  @sets = Set.find_all_by_user_id(user_id)
19
13
  end
20
-
14
+
21
15
  it "should return an array with the expected number of elements" do
22
16
  @sets.length.should == 2
23
17
  end
24
-
18
+
25
19
  it "should have the proper titles for each set in the collection" do
26
20
  @sets.map {|s| s.title }.should == ["Second Set", "First Set"]
27
21
  end
28
-
22
+
29
23
  it "should have the proper descriptions for each set in the collection" do
30
24
  @sets.map {|s| s.description }.should == ['This is the second set.', 'This is the first set.']
31
25
  end
26
+
27
+ it "should have the correct IDs for each of the sets" do
28
+ @sets.map {|s| s.id }.should == %w(72157609490909659 72157608538140671)
29
+ end
30
+
31
+ end
32
+ end
33
+
34
+ describe "An instance of the Set class" do
35
+ context "when accessing its list of photos" do
36
+
37
+ before do
38
+ @set = Set.new()
39
+ @set.stubs(:id).with().returns('1')
40
+ end
41
+
42
+ it "should retrieve a list of photos" do
43
+ photos = [stub()]
44
+
45
+ Photo.expects(:find_all_by_photoset_id).with('1').returns(photos)
46
+
47
+ @set.photos.should == photos
48
+ end
49
+
50
+ it "should memoize the list of photos retrieved" do
51
+ Photo.expects(:find_all_by_photoset_id).once.returns([])
52
+ 2.times { @set.photos }
53
+ end
32
54
 
33
55
  end
56
+
34
57
  end
58
+
35
59
  end
36
60
  end
@@ -6,8 +6,7 @@ module Fleakr
6
6
  describe "The User class" do
7
7
 
8
8
  it "should be able to find a user by his username" do
9
- response = stub(:body => read_fixture('people.findByUsername'))
10
- Request.expects(:new).with('people.findByUsername', :username => 'frootpantz').returns(stub(:send => response))
9
+ mock_request_cycle :for => 'people.findByUsername', :with => {:username => 'frootpantz'}
11
10
 
12
11
  user = User.find_by_username('frootpantz')
13
12
 
@@ -22,7 +21,7 @@ module Fleakr
22
21
  before do
23
22
  @user_id = '1'
24
23
 
25
- @user = User.new
24
+ @user = User.new(Hpricot.XML(read_fixture('people.findByUsername')))
26
25
  @user.stubs(:id).with().returns(@user_id)
27
26
  end
28
27
 
data/test/test_helper.rb CHANGED
@@ -11,7 +11,12 @@ class Test::Unit::TestCase
11
11
 
12
12
  def read_fixture(method_call)
13
13
  fixture_path = File.dirname(__FILE__) + '/fixtures'
14
- Hpricot.XML(File.read("#{fixture_path}/#{method_call}.xml"))
14
+ File.read("#{fixture_path}/#{method_call}.xml")
15
+ end
16
+
17
+ def mock_request_cycle(options)
18
+ response = stub(:body => Hpricot.XML(read_fixture(options[:for])))
19
+ Fleakr::Request.expects(:with_response!).with(options[:for], options[:with]).returns(response)
15
20
  end
16
21
 
17
22
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reagent-fleakr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrick Reagan
@@ -33,6 +33,8 @@ files:
33
33
  - README.markdown
34
34
  - Rakefile
35
35
  - lib/fleakr
36
+ - lib/fleakr/error.rb
37
+ - lib/fleakr/photo.rb
36
38
  - lib/fleakr/request.rb
37
39
  - lib/fleakr/response.rb
38
40
  - lib/fleakr/set.rb
@@ -42,7 +44,10 @@ files:
42
44
  - test/fixtures
43
45
  - test/fixtures/people.findByUsername.xml
44
46
  - test/fixtures/photosets.getList.xml
47
+ - test/fixtures/photosets.getPhotos.xml
45
48
  - test/fleakr
49
+ - test/fleakr/error_test.rb
50
+ - test/fleakr/photo_test.rb
46
51
  - test/fleakr/request_test.rb
47
52
  - test/fleakr/response_test.rb
48
53
  - test/fleakr/set_test.rb