reagent-fleakr 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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