hexorx-rumblr 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ *.gem
data/LICENSE.rdoc ADDED
@@ -0,0 +1,24 @@
1
+ = License
2
+
3
+ (The MIT License)
4
+
5
+ Copyright (c) 2009 Brent Hargrave
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining
8
+ a copy of this software and associated documentation files (the
9
+ "Software"), to deal in the Software without restriction, including
10
+ without limitation the rights to use, copy, modify, merge, publish,
11
+ distribute, sublicense, and/or sell copies of the Software, and to
12
+ permit persons to whom the Software is furnished to do so, subject to
13
+ the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,59 @@
1
+ = Rumblr
2
+
3
+ Rumblr is a Ruby client for http://www.tumblr.com XML API. It currently only provides read functionality; you can read User, Tumblelog and Post data.
4
+
5
+ = Overview
6
+
7
+ Rumblr maps the Tumblr API 'authenticate' and 'read' calls. User, Tumblelog and Post models have the attributes provided by the API, as well as some convenience methods for common tasks.
8
+
9
+ Please read Tumblr's official documentation (http://tumblr.com/api/) to learn more about the API.
10
+
11
+
12
+ == Dependencies
13
+
14
+ * Ruby >= 1.8.6 (not tested with previous versions)
15
+ * libxml-ruby >= 0.8.3
16
+
17
+
18
+ == Download and Installation
19
+
20
+ RubyGems[http://rubyforge.org/projects/rubygems/] is the preferred install method.
21
+ To get the latest version, simply type the following instruction into your command prompt:
22
+
23
+ $ sudo gem install jamescallmebrent-rumblr -s http://gems.github.com
24
+
25
+
26
+ == Getting Started
27
+
28
+ In order to use this library you need a valid Tumblr account.
29
+ Go to http://tumblr.com and register for a new account if you don't already have one.
30
+
31
+
32
+ === Sample usage:
33
+
34
+ require 'rumblr'
35
+ include Rumblr
36
+
37
+ user = User.login({:email => 'name@domain.com', :password => 'pass'})
38
+
39
+ user.tumblelogs.each do |log|
40
+ puts log.name # 'the tumblelogger'
41
+ puts log.type # 'public'
42
+ puts log.url # 'http://tumblelogger.tumblr.com/'
43
+ puts
44
+ end
45
+
46
+ tumblelog = user.primary_tumblelog
47
+
48
+ tumblelog.posts.each do |post|
49
+ puts post.type # 'quote'
50
+ puts post.url # 'http://tumblelogger.tumblr.com/post/12345/my-first-tumblr-post'
51
+ end
52
+
53
+ post = RegularPost.new(:title => "Post Title", :body => "Just a regular post!")
54
+ Client.instance.write(post, {:email => 'name@domain.com', :password => 'pass'})
55
+
56
+
57
+ == License
58
+
59
+ Copyright (c) 2009 Brent Hargrave. Rumblr is released under the MIT license.
data/Rakefile ADDED
@@ -0,0 +1,48 @@
1
+ require 'rake'
2
+
3
+ begin
4
+ require 'jeweler'
5
+ Jeweler::Tasks.new do |s|
6
+ summary = %Q{Ruby client for the Tumblr API}
7
+
8
+ s.name = "rumblr"
9
+ s.summary = summary
10
+ s.email = "brent.hargrave@gmail.com"
11
+ s.homepage = "http://github.com/jamescallmebrent/rumblr"
12
+ s.description = summary
13
+ s.authors = ["Brent Hargrave", "Benny Wong"]
14
+ s.add_dependency('libxml-ruby', '>= 0.8.3')
15
+ end
16
+ rescue LoadError
17
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
18
+ end
19
+
20
+ require 'rake/rdoctask'
21
+ Rake::RDocTask.new do |rdoc|
22
+ rdoc.rdoc_dir = 'rdoc'
23
+ rdoc.title = 'rumblr'
24
+ rdoc.options << '--line-numbers' << '--inline-source'
25
+ rdoc.rdoc_files.include('README*')
26
+ rdoc.rdoc_files.include('lib/**/*.rb')
27
+ end
28
+
29
+ require 'spec/rake/spectask'
30
+ Spec::Rake::SpecTask.new(:spec) do |t|
31
+ t.libs << 'lib' << 'spec'
32
+ t.spec_files = FileList['spec/**/*_spec.rb']
33
+ end
34
+
35
+ Spec::Rake::SpecTask.new(:rcov) do |t|
36
+ t.libs << 'lib' << 'spec'
37
+ t.spec_files = FileList['spec/**/*_spec.rb']
38
+ t.rcov = true
39
+ end
40
+
41
+ begin
42
+ require 'cucumber/rake/task'
43
+ Cucumber::Rake::Task.new(:features)
44
+ rescue LoadError
45
+ puts "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
46
+ end
47
+
48
+ task :default => :spec
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 0
4
+ :patch: 2
@@ -0,0 +1,146 @@
1
+ module Rumblr
2
+
3
+ class Client
4
+ include Singleton
5
+
6
+ # The default set of headers for each request.
7
+ DEFAULT_HEADER = {
8
+ 'User-Agent' => 'Rumblr',
9
+ 'Accept' => 'application/xml'
10
+ }
11
+
12
+ def authenticate(email,password)
13
+ raise ArgumentError unless (email && password)
14
+ user_credentials = { :email => email, :password => password }
15
+ uri = URI::HTTP.build({:path => '/api/authenticate'})
16
+ request = Net::HTTP::Post.new(uri.request_uri, DEFAULT_HEADER)
17
+ request.set_form_data(user_credentials)
18
+
19
+ user_attributes = nil
20
+ complete_request(request) do |response_body|
21
+ user_attributes = parse_user_attributes_from(response_body)
22
+ user_attributes.merge!(user_credentials)
23
+ end
24
+ user = User.new(user_attributes)
25
+ user.tumblelogs.each{ |tumblelog| tumblelog.user = user }
26
+ user
27
+ end
28
+
29
+ def read(options={})
30
+ tumblelog, posts = nil, [] # initialize the return targets
31
+
32
+ uri = URI::HTTP.build({:path => '/api/read'})
33
+ request = Net::HTTP::Post.new(uri.request_uri, DEFAULT_HEADER)
34
+ request.set_form_data(options)
35
+
36
+ raise(ArgumentError) unless (options && options[:url] && !options[:url].empty?)
37
+
38
+ request_url_host = URI.parse(options[:url]).host
39
+ complete_request(request,host=request_url_host) do |response_body|
40
+ parser = XML::Parser.string(response_body)
41
+ doc = parser.parse
42
+ # parse and map tumblelog
43
+ tumblelog_element = doc.find_first('//tumblr/tumblelog')
44
+ tumblelog_attrs = cleanup_hash(tumblelog_element.attributes.to_h)
45
+ tumblelog_attrs.merge!(:url => options[:url])
46
+ tumblelog = Tumblelog.new(tumblelog_attrs)
47
+ # parse and map posts
48
+ posts = doc.find('//tumblr/posts/post').inject([]) do |array, element|
49
+ post_attrs = cleanup_hash(element.attributes.to_h)
50
+ # inner elements => sublcass-specific attribute hash
51
+ subclass_attrs = element.children.inject({'tags' => []}) do |hash, child|
52
+ hash['tags'] << child.content if (child.name[/tag/])
53
+ hash[child.name] = child.content
54
+ hash
55
+ end
56
+ # merge hashes, clean out cruft
57
+ inner_attrs = cleanup_hash(subclass_attrs)
58
+ inner_attrs.delete(:text)
59
+ inner_attrs.delete(:tag)
60
+ post_attrs.merge!(inner_attrs)
61
+ # turn attributes into proper model
62
+ klass = Rumblr.const_get(Post::TYPES[post_attrs[:type]])
63
+ raise 'unknown post type' unless klass
64
+ post = klass.new(post_attrs)
65
+ post.tumblelog = tumblelog
66
+ array << post
67
+ array
68
+ end
69
+ end
70
+ return tumblelog, posts
71
+ end
72
+
73
+ def write(post, creds)
74
+ raise(ArgumentError) unless post && post.is_a?(Post)
75
+ raise(ArgumentError) unless creds
76
+ uri = URI::HTTP.build(:path => "/api/write")
77
+ request = Net::HTTP::Post.new(uri.request_uri, DEFAULT_HEADER)
78
+ request.set_form_data(creds.merge(:type => Post::TYPES.invert[post.class]).merge(post.attribute_hash))
79
+ request_url_host = URI.parse(uri.request_uri).host
80
+ complete_request(request)
81
+ end
82
+
83
+
84
+ protected
85
+
86
+ # Starts and completes the given request. Returns or yields the response body.
87
+ def complete_request(request, host = URI.parse(Rumblr.api_url).host)
88
+ http = Net::HTTP.new(host)
89
+ # Set to debug http output.
90
+ # http.set_debug_output $stderr
91
+ response = http.start { |http| http.request(request) }
92
+
93
+ case response
94
+ when Net::HTTPSuccess then yield response.body if block_given?
95
+ when Net::HTTPBadRequest then raise Rumblr::RequestError, parse_error_message(response)
96
+ when Net::HTTPForbidden then raise Rumblr::AuthorizationError, parse_error_message(response)
97
+ when Net::HTTPNotFound then raise Rumblr::MissingResourceError, parse_error_message(response)
98
+ when Net::HTTPMovedPermanently then raise Rumblr::MovedResourceError, parse_error_message(response)
99
+ when Net::HTTPServerError then raise Rumblr::ServerError, connection_error_message
100
+ else raise "Received an unexpected HTTP response: #{response}"
101
+ end
102
+
103
+ response.body
104
+ end
105
+
106
+ # Extracts the error message from the response for the exception.
107
+ def parse_error_message(response)
108
+ response.body
109
+ end
110
+
111
+ def connection_error_message
112
+ "There was a problem connecting to Tumblr"
113
+ end
114
+
115
+
116
+ private
117
+
118
+ def parse_user_attributes_from(response_body)
119
+ parser = XML::Parser.string response_body
120
+ doc = parser.parse
121
+ tumblelogs = doc.find('//tumblr/tumblelog').inject([]) do |array, element|
122
+ tumblelog_attrs = cleanup_hash(element.attributes.to_h)
123
+ array << Tumblelog.new(tumblelog_attrs)
124
+ array
125
+ end
126
+ raw_user_attributes = doc.find('//tumblr/user').first.attributes.to_h
127
+ user_attributes = cleanup_hash(raw_user_attributes)
128
+ user_attributes.merge!(:tumblelogs => tumblelogs)
129
+ end
130
+
131
+ def cleanup_hash(attrs={})
132
+ clean_attrs = attrs.inject({}) do |hash,(key,value)|
133
+ mapped_key = key.gsub(/-/,'_').to_sym
134
+ mapped_value = case value
135
+ when /($1^|$yes^)/ then true
136
+ when /($0^|$no^)/ then false
137
+ else value
138
+ end
139
+ hash[mapped_key] = mapped_value
140
+ hash
141
+ end
142
+ end
143
+
144
+ end
145
+
146
+ end
@@ -0,0 +1,102 @@
1
+ module Rumblr
2
+
3
+ # for attribute details, see Tumblr's documentation:
4
+ # http://www.tumblr.com/api
5
+ class Post < Resource
6
+
7
+ TYPES = {
8
+ 'regular' => "RegularPost",
9
+ 'photo' => "PhotoPost",
10
+ 'quote' => "QuotePost",
11
+ 'link' => "LinkPost",
12
+ 'conversation' => "ConversationPost",
13
+ 'video' => "VideoPost",
14
+ 'audio' => "AudioPost"
15
+ }
16
+
17
+ attr_reader :id, :url, :type, :unix_timestamp, :date_gmt, :date, :tags, :private
18
+ attr_accessor :tumblelog
19
+
20
+ def initialize(attrs={})
21
+ @private = false
22
+ super
23
+ end
24
+
25
+ def private?
26
+ @private
27
+ end
28
+
29
+ def public?
30
+ !self.private?
31
+ end
32
+
33
+ def attribute_hash
34
+ {:date => date}
35
+ end
36
+
37
+ end
38
+
39
+ class RegularPost < Post
40
+ attr_accessor :title, :body
41
+
42
+ def attribute_hash
43
+ super.merge(:title => title, :body => body)
44
+ end
45
+
46
+ end
47
+
48
+ class PhotoPost < Post
49
+ attr_accessor :source, :data, :caption, :click_through_url
50
+
51
+ def attribute_hash
52
+ super.merge(:source => source, :data => data, :caption => caption, :click_through_url => click_through_url)
53
+ end
54
+
55
+ end
56
+
57
+ class QuotePost < Post
58
+ attr_accessor :quote, :source
59
+
60
+ def attribute_hash
61
+ super.merge(:quote => quote, :source => source)
62
+ end
63
+
64
+ end
65
+
66
+ class LinkPost < Post
67
+ attr_accessor :name, :url, :description
68
+
69
+ def attribute_hash
70
+ super.merge(:name => name, :url => url, :description => description)
71
+ end
72
+
73
+ end
74
+
75
+ class ConversationPost < Post
76
+ attr_accessor :title, :conversation
77
+
78
+ def attribute_hash
79
+ super.merge(:title => title, :conversation => conversation)
80
+ end
81
+
82
+ end
83
+
84
+ class VideoPost < Post
85
+ attr_accessor :embed, :data, :title, :caption
86
+
87
+ def attribute_hash
88
+ super.merge(:embed => embed, :data => data, :title => title, :caption => caption)
89
+ end
90
+
91
+ end
92
+
93
+ class AudioPost < Post
94
+ attr_accessor :data, :caption
95
+
96
+ def attribute_hash
97
+ super.merge(:data => data, :caption => caption)
98
+ end
99
+
100
+ end
101
+
102
+ end
@@ -0,0 +1,13 @@
1
+ module Rumblr
2
+
3
+ class Resource
4
+
5
+ def initialize(attrs={})
6
+ attrs.each do |key,value|
7
+ self.instance_variable_set(:"@#{key.to_s}", value)
8
+ end
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,30 @@
1
+ module Rumblr
2
+
3
+ class Tumblelog < Resource
4
+ attr_reader :name, :timezone, :cname, :title, :url, :avatar_url, :is_primary,
5
+ :type, :private_id
6
+ attr_accessor :user
7
+
8
+ def posts(options={})
9
+ return [] unless self.url
10
+ options.reverse_merge!(:url => self.url)
11
+ log, posts = Client.instance.read(options)
12
+ return posts
13
+ end
14
+
15
+ def primary?
16
+ is_primary == "yes"
17
+ end
18
+
19
+ class << self
20
+
21
+ def find_by_url(url)
22
+ log, posts = Client.instance.read(:url => url)
23
+ return log
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,27 @@
1
+ module Rumblr
2
+
3
+ class User < Resource
4
+ attr_reader :email, :password, :can_upload_video, :can_upload_aiff, :vimeo_login_url, :can_upload_audio
5
+
6
+ def tumblelogs
7
+ instance_variable_get(:@tumblelogs) || []
8
+ end
9
+
10
+ def primary_tumblelog
11
+ self.tumblelogs.find { |log| log.primary? }
12
+ end
13
+
14
+ def auth
15
+ {:email => self.email, :password => self.password}
16
+ end
17
+
18
+ class << self
19
+ def login(attrs={})
20
+ email, password = attrs[:email], attrs[:password]
21
+ Client.instance.authenticate(email,password)
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ end
data/lib/rumblr.rb ADDED
@@ -0,0 +1,28 @@
1
+ module Rumblr
2
+
3
+ class MissingResourceError < Exception; end
4
+ class MovedResourceError < Exception; end
5
+ class AuthorizationError < Exception; end
6
+ class RequestError < Exception; end
7
+ class ServerError < Exception; end
8
+
9
+ class << self
10
+ attr_accessor :api_url
11
+ end
12
+ end
13
+
14
+ Rumblr.api_url = "http://www.tumblr.com"
15
+
16
+ require 'rubygems'
17
+ require 'singleton'
18
+ require 'net/http'
19
+ require 'uri'
20
+ gem 'libxml-ruby', '>= 0.8.3'
21
+ require 'xml'
22
+ require 'pp'
23
+
24
+ require 'rumblr/client'
25
+ require 'rumblr/resource'
26
+ require 'rumblr/tumblelog'
27
+ require 'rumblr/user'
28
+ require 'rumblr/post'
data/rumblr.gemspec ADDED
@@ -0,0 +1,60 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{rumblr}
5
+ s.version = "0.0.3"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Brent Hargrave", "Benny Wong"]
9
+ s.date = %q{2009-05-30}
10
+ s.description = %q{Ruby client for the Tumblr API}
11
+ s.email = %q{brent.hargrave@gmail.com}
12
+ s.extra_rdoc_files = [
13
+ "LICENSE.rdoc",
14
+ "README.rdoc"
15
+ ]
16
+ s.files = [
17
+ ".gitignore",
18
+ "LICENSE.rdoc",
19
+ "README.rdoc",
20
+ "Rakefile",
21
+ "VERSION.yml",
22
+ "lib/rumblr.rb",
23
+ "lib/rumblr/client.rb",
24
+ "lib/rumblr/post.rb",
25
+ "lib/rumblr/resource.rb",
26
+ "lib/rumblr/tumblelog.rb",
27
+ "lib/rumblr/user.rb",
28
+ "rumblr.gemspec",
29
+ "spec/rumblr/client_spec.rb",
30
+ "spec/rumblr/post_spec.rb",
31
+ "spec/rumblr/tumblelog_spec.rb",
32
+ "spec/rumblr/user_spec.rb",
33
+ "spec/spec_helper.rb"
34
+ ]
35
+ s.homepage = %q{http://github.com/jamescallmebrent/rumblr}
36
+ s.rdoc_options = ["--charset=UTF-8"]
37
+ s.require_paths = ["lib"]
38
+ s.rubygems_version = %q{1.3.3}
39
+ s.summary = %q{Ruby client for the Tumblr API}
40
+ s.test_files = [
41
+ "spec/rumblr/client_spec.rb",
42
+ "spec/rumblr/post_spec.rb",
43
+ "spec/rumblr/tumblelog_spec.rb",
44
+ "spec/rumblr/user_spec.rb",
45
+ "spec/spec_helper.rb"
46
+ ]
47
+
48
+ if s.respond_to? :specification_version then
49
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
50
+ s.specification_version = 3
51
+
52
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
53
+ s.add_runtime_dependency(%q<libxml-ruby>, [">= 0.8.3"])
54
+ else
55
+ s.add_dependency(%q<libxml-ruby>, [">= 0.8.3"])
56
+ end
57
+ else
58
+ s.add_dependency(%q<libxml-ruby>, [">= 0.8.3"])
59
+ end
60
+ end
@@ -0,0 +1,145 @@
1
+ require File.join(File.dirname(__FILE__), "/../spec_helper" )
2
+
3
+ module Rumblr
4
+
5
+ describe Client do
6
+
7
+ it 'should not be able to be instantiated externally' do
8
+ lambda { Client.new }.should raise_error(NoMethodError)
9
+ end
10
+
11
+ it 'should be able to instantiate itself' do
12
+ lambda { Client.instance }.should_not raise_error
13
+ end
14
+
15
+ end
16
+
17
+ describe Client, "authentication" do
18
+
19
+ before(:each) { mock_successful(:authenticate) }
20
+
21
+ it 'should raise an ArgumentError without email' do
22
+ lambda do
23
+ @client.authenticate('email', nil)
24
+ end.should raise_error(ArgumentError)
25
+ end
26
+
27
+ it 'should raise an ArgumentError without password' do
28
+ lambda do
29
+ @client.authenticate(nil,'password')
30
+ end.should raise_error(ArgumentError)
31
+ end
32
+
33
+ it 'should return a User if successful' do
34
+ result = @client.authenticate('foo@foo.com','password')
35
+ result.should be_an_instance_of(User)
36
+ end
37
+
38
+ it "should include user's existing tumblelogs" do
39
+ user = @client.authenticate('foo@foo.com','password')
40
+ user.tumblelogs.size.should == 2
41
+ end
42
+
43
+ end
44
+
45
+ describe Client, "reading from a public tumblelog" do
46
+
47
+ it 'without a URL should raise an error' do
48
+ mock_successful(:anonymous_read)
49
+ lambda do
50
+ @client.read
51
+ end.should raise_error(ArgumentError)
52
+ end
53
+
54
+ it 'with an empty URL should raise an error' do
55
+ mock_successful(:anonymous_read)
56
+ lambda do
57
+ @client.read(:url => '')
58
+ end.should raise_error(ArgumentError)
59
+ end
60
+
61
+ describe 'without credentials' do
62
+
63
+ before(:each) do
64
+ mock_successful(:anonymous_read)
65
+ @tumblelog, posts = @client.read(:url => 'http://dummylog.tumblr.com/')
66
+ end
67
+
68
+ it 'should yield only posts' do
69
+ @tumblelog.posts.all? {|post| post.kind_of?(Post)}.should be_true
70
+ end
71
+
72
+ it 'should not include all posts, assuming some are private' do
73
+ @tumblelog.posts.size.should == 7
74
+ end
75
+
76
+ it 'should only include public posts' do
77
+ @tumblelog.posts.all? {|post| post.public? }.should be_true
78
+ end
79
+
80
+ it 'should not include any private posts' do
81
+ @tumblelog.posts.any? {|post| post.private? }.should be_false
82
+ end
83
+
84
+ end
85
+
86
+ describe 'with valid credentials' do
87
+
88
+ before(:each) do
89
+ mock_successful(:authenticated_read)
90
+ @tumblelog, posts = @client.read( :url => 'http://dummylog.tumblr.com/',
91
+ :email => 'valid',
92
+ :password => 'valid' )
93
+ end
94
+
95
+ it 'should include all tumblelog posts' do
96
+ @tumblelog.posts.size.should == 14
97
+ end
98
+
99
+ it 'should include all public posts' do
100
+ @tumblelog.posts.find_all {|p| p.public? }.size.should == 7
101
+ end
102
+
103
+ it 'should include private posts' do
104
+ @tumblelog.posts.find_all {|p| p.public? }.size.should == 7
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+
111
+ describe Client, "writing to a public tumblelog" do
112
+
113
+ before(:each) do
114
+ mock_successful(:authenticated_read)
115
+ @tumblelog, posts = @client.read( :url => 'http://dummylog.tumblr.com/',
116
+ :email => 'valid',
117
+ :password => 'valid' )
118
+ mock_successful(:authenticated_write)
119
+ end
120
+
121
+ it 'should raise an ArgumentError without post' do
122
+ lambda do
123
+ @client.write(nil, {:email => 'valid', :password => 'valid'})
124
+ end.should raise_error(ArgumentError)
125
+ end
126
+
127
+ it 'should raise an ArgumentError if post is incorrect class' do
128
+ lambda do
129
+ @client.write("", {:email => 'valid', :password => 'valid'})
130
+ end.should raise_error(ArgumentError)
131
+ end
132
+
133
+ it 'should raise an ArgumentError without creds' do
134
+ lambda do
135
+ @client.write(Rumblr::Post.new, nil)
136
+ end.should raise_error(ArgumentError)
137
+ end
138
+
139
+ it 'should return an id' do
140
+ @client.write(Rumblr::Post.new, {:email => 'valid', :password => 'valid'}).should == "10001"
141
+ end
142
+
143
+ end
144
+
145
+ end
@@ -0,0 +1,29 @@
1
+ require File.join(File.dirname(__FILE__), "/../spec_helper" )
2
+
3
+ module Rumblr
4
+
5
+ describe Post, 'instances' do
6
+
7
+ it 'should have attributes shared by every Post' do
8
+ Post.new.should respond_to(:id, :url, :type, :unix_timestamp, :date_gmt, :date, :tags, :private, :tumblelog)
9
+ end
10
+
11
+ it 'private attribute should default to false' do
12
+ Post.new.private.should be_false
13
+ end
14
+
15
+ it 'should provide it private status' do
16
+ Post.new.should respond_to(:private?)
17
+ end
18
+
19
+ it 'should provide it public status (inverse of private status)' do
20
+ Post.new.should respond_to(:public?)
21
+ end
22
+
23
+ it 'should provide a hash of attributes and values for API' do
24
+ Post.new.should respond_to(:attribute_hash)
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,64 @@
1
+ require File.join(File.dirname(__FILE__), "/../spec_helper" )
2
+
3
+ module Rumblr
4
+
5
+ describe Tumblelog, 'instances' do
6
+
7
+ it 'should have the attributes of a Tumblelog' do
8
+ Tumblelog.new.should respond_to( :name, :timezone, :cname, :title, :url,
9
+ :avatar_url, :is_primary, :type, :private_id)
10
+ end
11
+
12
+ it "' posts should initialize empty" do
13
+ Tumblelog.new.posts.should be_a_kind_of(Array)
14
+ end
15
+
16
+ end
17
+
18
+ describe Tumblelog, 'finder' do
19
+
20
+ describe 'provided a valid URL' do
21
+
22
+ it 'should successfully retrieve a tumblelog' do
23
+ mock_successful(:anonymous_read)
24
+ log = Tumblelog.find_by_url('valid_url')
25
+ log.should be_an_instance_of(Tumblelog)
26
+ end
27
+
28
+ it 'should retrieve a tumblelog with posts' do
29
+ mock_successful(:anonymous_read)
30
+ log = Tumblelog.find_by_url('valid_url')
31
+ log.posts.first.should be_a_kind_of(Post)
32
+ log.posts.first.type.should_not be_nil
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+
39
+ describe Tumblelog, 'user' do
40
+
41
+ describe 'logged in' do
42
+
43
+ before(:each) do
44
+ mock_successful(:authenticate)
45
+ @user = User.login(:email => 'valid_email', :password => 'valid_password')
46
+ end
47
+
48
+ it 'should have a user associated with it' do
49
+ @user.primary_tumblelog.user.should_not be_nil
50
+ end
51
+
52
+ end
53
+
54
+ describe 'not logged in' do
55
+
56
+ it 'should not have a user if anonymous read' do
57
+ mock_successful(:anonymous_read)
58
+ Tumblelog.find_by_url('valid_url').user.should be_nil
59
+ end
60
+
61
+ end
62
+ end
63
+
64
+ end
@@ -0,0 +1,69 @@
1
+ require File.join(File.dirname(__FILE__), "/../spec_helper" )
2
+
3
+ module Rumblr
4
+
5
+ describe User, 'initializing' do
6
+
7
+ it 'should have the attributes of a User' do
8
+ User.new.should respond_to( :email,
9
+ :password,
10
+ :can_upload_video,
11
+ :can_upload_aiff,
12
+ :vimeo_login_url,
13
+ :can_upload_audio )
14
+ end
15
+
16
+ it 'tumblelogs should initialize empty' do
17
+ User.new.tumblelogs.should be_a_kind_of(Array)
18
+ end
19
+
20
+ end
21
+
22
+ describe User, 'logging in' do
23
+
24
+ before(:each) do
25
+ mock_successful(:authenticate)
26
+ end
27
+
28
+ it 'should login with email and password' do
29
+ user = User.login(:email => 'valid_email', :password => 'valid_password')
30
+ user.should be_an_instance_of(User)
31
+ end
32
+
33
+ it 'should not initialize without email' do
34
+ lambda do
35
+ User.login(:email => nil, :password => 'valid_password')
36
+ end.should raise_error(ArgumentError)
37
+ end
38
+
39
+ it 'should not initialize without password' do
40
+ lambda do
41
+ User.login(:email => 'valid_email', :password => nil)
42
+ end.should raise_error(ArgumentError)
43
+ end
44
+
45
+ end
46
+
47
+ describe User, ', once logged in,' do
48
+
49
+ before(:each) do
50
+ mock_successful(:authenticate)
51
+ @user = User.login(:email => 'valid_email', :password => 'valid_password')
52
+ end
53
+
54
+ it 'should provide one or more tumblelogs' do
55
+ @user.tumblelogs.size.should == 2
56
+ end
57
+
58
+ it 'should provide *only* tumblelogs' do
59
+ @user.tumblelogs.all? { |obj| obj.should be_an_instance_of(Tumblelog) }
60
+ end
61
+
62
+ it 'should provide a primary tumblelog' do
63
+ primary = @user.primary_tumblelog
64
+ primary.is_primary.should == 'yes'
65
+ end
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,106 @@
1
+ $: << File.join(File.dirname(__FILE__), "/../lib" )
2
+
3
+ require 'spec'
4
+ require 'rumblr'
5
+
6
+ def mock_successful(request)
7
+ responses_to = {
8
+ :authenticate => successful_authenticate_xml,
9
+ :anonymous_read => successful_anonymous_read_xml,
10
+ :authenticated_read => successful_authenticated_read_xml,
11
+ :authenticated_write => successful_authenticated_write_xml
12
+ }
13
+
14
+ @client = Rumblr::Client.instance
15
+ if request == :authenticated_write
16
+ @client.stub!(:complete_request).and_return(responses_to[request])
17
+ else
18
+ # yes, this is cheating, but for now just concerned that xml is parsed right
19
+ @client.stub!(:complete_request).and_yield(responses_to[request])
20
+ end
21
+ end
22
+
23
+ def successful_authenticate_xml
24
+ response = <<-EOF
25
+ <?xml version="1.0" encoding="UTF-8"?>
26
+ <tumblr version="1.0">
27
+ <user can-upload-audio="1" can-upload-aiff="1" can-upload-video="0" vimeo-login-url="http://www.vimeo.com/services/foo"/>
28
+ <tumblelog title="" name="foo" url="http://foo.com/" type="public" avatar-url="http://assets.tumblr.com/images/default_avatar_foo.gif" is-primary="yes"/>
29
+ <tumblelog title="bar" private-id="000000" type="private"/>
30
+ </tumblr>
31
+ EOF
32
+ response.strip!
33
+ end
34
+
35
+ def successful_anonymous_read_xml
36
+ response = <<-EOF
37
+ <?xml version="1.0" encoding="UTF-8"?>
38
+ <tumblr version="1.0">
39
+ <tumblelog name="dummylog" timezone="US/Eastern" title="dummy tumblelog title">dummylog description</tumblelog>
40
+ <posts start="0" total="7">
41
+ <post id="78846368" url="http://dummylog.tumblr.com/post/78846368" type="video" date-gmt="2009-02-16 19:11:45 GMT" date="Mon, 16 Feb 2009 14:11:45" unix-timestamp="1234811505">
42
+ <video-caption>public video post caption</video-caption>
43
+ <video-source>http://www.youtube.com/watch?v=rPaWZOM1LnY</video-source>
44
+ <video-player>&lt;object width="400" height="336"&gt;&lt;param name="movie" value="http://www.youtube.com/v/rPaWZOM1LnY&amp;amp;rel=0&amp;amp;egm=0&amp;amp;showinfo=0&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/rPaWZOM1LnY&amp;amp;rel=0&amp;amp;egm=0&amp;amp;showinfo=0&amp;amp;fs=1" type="application/x-shockwave-flash" width="400" height="336" allowFullScreen="true" wmode="transparent"&gt;&lt;/embed&gt;&lt;/object&gt;</video-player>
45
+ <tag>sale</tag>
46
+ <tag>music</tag>
47
+ </post>
48
+ <post id="78846080" url="http://dummylog.tumblr.com/post/78846080" type="audio" date-gmt="2009-02-16 19:10:20 GMT" date="Mon, 16 Feb 2009 14:10:20" unix-timestamp="1234811420" audio-plays="0">
49
+ <audio-caption>public audio post description</audio-caption><audio-player>&lt;embed type="application/x-shockwave-flash" src="http://dummylog.tumblr.com/swf/audio_player.swf?audio_file=http://www.tumblr.com/audio_file/78846080/TofwJxqCAk12g1e0ClxHx7gh&amp;color=FFFFFF" height="27" width="207" quality="best"&gt;&lt;/embed&gt;</audio-player>
50
+ <tag>sale</tag>
51
+ </post>
52
+ <post id="78844911" url="http://dummylog.tumblr.com/post/78844911" type="conversation" date-gmt="2009-02-16 19:04:48 GMT" date="Mon, 16 Feb 2009 14:04:48" unix-timestamp="1234811088">
53
+ <conversation-title>public chat post title</conversation-title>
54
+ <conversation-text>me: public&#13;
55
+ you: chat&#13;
56
+ me: post&#13;
57
+ you: dialogue</conversation-text><conversation><line name="me" label="me:">public&#13;</line><line name="you" label="you:">chat&#13;</line><line name="me" label="me:">post&#13;</line><line name="you" label="you:">dialogue</line></conversation><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">public&#13;</conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">chat&#13;</conversation-line><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">post&#13;</conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">dialogue</conversation-line>
58
+ <tag>sale</tag>
59
+ </post>
60
+ <post id="78844351" url="http://dummylog.tumblr.com/post/78844351" type="link" date-gmt="2009-02-16 19:02:00 GMT" date="Mon, 16 Feb 2009 14:02:00" unix-timestamp="1234810920">
61
+ <link-text>public link post name</link-text><link-url>http://www.google.com</link-url>
62
+ <link-description>public link post description</link-description>
63
+ <tag>sale</tag>
64
+ </post>
65
+ <post id="78844076" url="http://dummylog.tumblr.com/post/78844076" type="quote" date-gmt="2009-02-16 19:01:06 GMT" date="Mon, 16 Feb 2009 14:01:06" unix-timestamp="1234810866">
66
+ <quote-text>public quote post content</quote-text>
67
+ <quote-source>public quote post source</quote-source>
68
+ <tag>sale</tag>
69
+ </post>
70
+ <post id="78841604" url="http://dummylog.tumblr.com/post/78841604" type="regular" date-gmt="2009-02-16 18:50:00 GMT" date="Mon, 16 Feb 2009 13:50:00" unix-timestamp="1234810200">
71
+ <regular-title>public text post title</regular-title>
72
+ <regular-body>public text post body</regular-body>
73
+ <tag>sale</tag>
74
+ </post>
75
+ <post id="78841444" url="http://dummylog.tumblr.com/post/78841444" type="photo" date-gmt="2009-02-16 18:49:00 GMT" date="Mon, 16 Feb 2009 13:49:00" unix-timestamp="1234810140">
76
+ <photo-caption>public photo post</photo-caption>
77
+ <photo-url max-width="500">http://21.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_500.jpg</photo-url>
78
+ <photo-url max-width="400">http://1.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_400.jpg</photo-url>
79
+ <photo-url max-width="250">http://22.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_250.jpg</photo-url>
80
+ <photo-url max-width="100">http://19.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_100.jpg</photo-url>
81
+ <photo-url max-width="75">http://2.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_75sq.jpg</photo-url>
82
+ <tag>sale</tag>
83
+ </post>
84
+ </posts>
85
+ </tumblr>
86
+ EOF
87
+ response.strip!
88
+ end
89
+
90
+ def successful_authenticated_read_xml
91
+ response = <<-EOF
92
+ <?xml version="1.0" encoding="UTF-8"?>
93
+ <tumblr version="1.0"><tumblelog name="dummylog" timezone="US/Eastern" title="dummy tumblelog title">dummy tumblelog description</tumblelog><posts start="0" total="7"><post id="78846474" url="http://dummylog.tumblr.com/post/78846474" type="video" date-gmt="2009-02-16 19:12:00 GMT" date="Mon, 16 Feb 2009 14:12:00" unix-timestamp="1234811520" private="true"><video-caption>private video post caption</video-caption><video-source>http://www.youtube.com/watch?v=rPaWZOM1LnY</video-source><video-player>&lt;object width="400" height="336"&gt;&lt;param name="movie" value="http://www.youtube.com/v/rPaWZOM1LnY&amp;amp;rel=0&amp;amp;egm=0&amp;amp;showinfo=0&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/rPaWZOM1LnY&amp;amp;rel=0&amp;amp;egm=0&amp;amp;showinfo=0&amp;amp;fs=1" type="application/x-shockwave-flash" width="400" height="336" allowFullScreen="true" wmode="transparent"&gt;&lt;/embed&gt;&lt;/object&gt;</video-player><tag>sale</tag><tag>tag2</tag><tag>music</tag></post><post id="78846368" url="http://dummylog.tumblr.com/post/78846368" type="video" date-gmt="2009-02-16 19:11:00 GMT" date="Mon, 16 Feb 2009 14:11:00" unix-timestamp="1234811460"><video-caption>public video post caption</video-caption><video-source>hilhttp://www.youtube.com/watch?v=rPaWZOM1LnY</video-source><video-player>&lt;object width="400" height="336"&gt;&lt;param name="movie" value="http://www.youtube.com/v/rPaWZOM1LnY&amp;amp;rel=0&amp;amp;egm=0&amp;amp;showinfo=0&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/rPaWZOM1LnY&amp;amp;rel=0&amp;amp;egm=0&amp;amp;showinfo=0&amp;amp;fs=1" type="application/x-shockwave-flash" width="400" height="336" allowFullScreen="true" wmode="transparent"&gt;&lt;/embed&gt;&lt;/object&gt;</video-player><tag>hilarious</tag></post><post id="78846150" url="http://dummylog.tumblr.com/post/78846150" type="audio" date-gmt="2009-02-16 19:10:43 GMT" date="Mon, 16 Feb 2009 14:10:43" unix-timestamp="1234811443" private="true" audio-plays="2"><audio-caption>private audio post description</audio-caption><audio-player>&lt;embed type="application/x-shockwave-flash" src="http://dummylog.tumblr.com/swf/audio_player.swf?audio_file=http://www.tumblr.com/audio_file/78846150/TofwJxqCAk12gje4UYRllUwM&amp;color=FFFFFF" height="27" width="207" quality="best"&gt;&lt;/embed&gt;</audio-player><tag>sale</tag></post><post id="78846080" url="http://dummylog.tumblr.com/post/78846080" type="audio" date-gmt="2009-02-16 19:10:00 GMT" date="Mon, 16 Feb 2009 14:10:00" unix-timestamp="1234811400" audio-plays="0"><audio-caption>public audio post description</audio-caption><audio-player>&lt;embed type="application/x-shockwave-flash" src="http://dummylog.tumblr.com/swf/audio_player.swf?audio_file=http://www.tumblr.com/audio_file/78846080/TofwJxqCAk12g1e0ClxHx7gh&amp;color=FFFFFF" height="27" width="207" quality="best"&gt;&lt;/embed&gt;</audio-player><tag>sale</tag><tag>music</tag></post><post id="78844968" url="http://dummylog.tumblr.com/post/78844968" type="conversation" date-gmt="2009-02-16 19:05:08 GMT" date="Mon, 16 Feb 2009 14:05:08" unix-timestamp="1234811108" private="true"><conversation-title>private chat post title</conversation-title><conversation-text>me: private&#13;
94
+ you: chat&#13;
95
+ me: post&#13;
96
+ you: dialogue</conversation-text><conversation><line name="me" label="me:">private&#13;</line><line name="you" label="you:">chat&#13;</line><line name="me" label="me:">post&#13;</line><line name="you" label="you:">dialogue</line></conversation><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">private&#13;</conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">chat&#13;</conversation-line><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">post&#13;</conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">dialogue</conversation-line><tag>sale</tag></post><post id="78844911" url="http://dummylog.tumblr.com/post/78844911" type="conversation" date-gmt="2009-02-16 19:04:48 GMT" date="Mon, 16 Feb 2009 14:04:48" unix-timestamp="1234811088"><conversation-title>public chat post title</conversation-title><conversation-text>me: public&#13;
97
+ you: chat&#13;
98
+ me: post&#13;
99
+ you: dialogue</conversation-text><conversation><line name="me" label="me:">public&#13;</line><line name="you" label="you:">chat&#13;</line><line name="me" label="me:">post&#13;</line><line name="you" label="you:">dialogue</line></conversation><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">public&#13;</conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">chat&#13;</conversation-line><conversation-line name="me" label="me:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">post&#13;</conversation-line><conversation-line name="you" label="you:" deprecated="conversation-line is deprecated and will soon be removed. Use ./conversation/line.">dialogue</conversation-line><tag>sale</tag></post><post id="78844625" url="http://dummylog.tumblr.com/post/78844625" type="link" date-gmt="2009-02-16 19:03:00 GMT" date="Mon, 16 Feb 2009 14:03:00" unix-timestamp="1234810980" private="true"><link-text>private link post name</link-text><link-url>http://www.google.com</link-url><link-description>private link post description</link-description><tag>sale</tag></post><post id="78844351" url="http://dummylog.tumblr.com/post/78844351" type="link" date-gmt="2009-02-16 19:02:00 GMT" date="Mon, 16 Feb 2009 14:02:00" unix-timestamp="1234810920"><link-text>public link post name</link-text><link-url>http://www.google.com</link-url><link-description>public link post description</link-description><tag>sale</tag></post><post id="78844076" url="http://dummylog.tumblr.com/post/78844076" type="quote" date-gmt="2009-02-16 19:01:06 GMT" date="Mon, 16 Feb 2009 14:01:06" unix-timestamp="1234810866"><quote-text>public quote post content</quote-text><quote-source>public quote post source</quote-source><tag>sale</tag></post><post id="78844136" url="http://dummylog.tumblr.com/post/78844136" type="quote" date-gmt="2009-02-16 19:01:00 GMT" date="Mon, 16 Feb 2009 14:01:00" unix-timestamp="1234810860" private="true"><quote-text>private quote post content</quote-text><quote-source>private quote post content</quote-source><tag>sale</tag></post><post id="78843778" url="http://dummylog.tumblr.com/post/78843778" type="photo" date-gmt="2009-02-16 18:59:40 GMT" date="Mon, 16 Feb 2009 13:59:40" unix-timestamp="1234810780" private="true"><photo-caption>private photo post</photo-caption><photo-url max-width="500">http://7.media.tumblr.com/TofwJxqCAk122bofvQLGsl89o1_500.jpg</photo-url><photo-url max-width="400">http://6.media.tumblr.com/TofwJxqCAk122bofvQLGsl89o1_400.jpg</photo-url><photo-url max-width="250">http://11.media.tumblr.com/TofwJxqCAk122bofvQLGsl89o1_250.jpg</photo-url><photo-url max-width="100">http://11.media.tumblr.com/TofwJxqCAk122bofvQLGsl89o1_100.jpg</photo-url><photo-url max-width="75">http://22.media.tumblr.com/TofwJxqCAk122bofvQLGsl89o1_75sq.jpg</photo-url><tag>sale</tag></post><post id="78843501" url="http://dummylog.tumblr.com/post/78843501" type="regular" date-gmt="2009-02-16 18:58:00 GMT" date="Mon, 16 Feb 2009 13:58:00" unix-timestamp="1234810680" private="true"><regular-title>private text post title</regular-title><regular-body>private text post body</regular-body><tag>sale</tag></post><post id="78841604" url="http://dummylog.tumblr.com/post/78841604" type="regular" date-gmt="2009-02-16 18:50:00 GMT" date="Mon, 16 Feb 2009 13:50:00" unix-timestamp="1234810200"><regular-title>public text post title</regular-title><regular-body>public text post body</regular-body><tag>sale</tag></post><post id="78841444" url="http://dummylog.tumblr.com/post/78841444" type="photo" date-gmt="2009-02-16 18:49:00 GMT" date="Mon, 16 Feb 2009 13:49:00" unix-timestamp="1234810140"><photo-caption>public photo post</photo-caption><photo-url max-width="500">http://21.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_500.jpg</photo-url><photo-url max-width="400">http://1.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_400.jpg</photo-url><photo-url max-width="250">http://22.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_250.jpg</photo-url><photo-url max-width="100">http://19.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_100.jpg</photo-url><photo-url max-width="75">http://2.media.tumblr.com/TofwJxqCAk11p5psVgVhLwzJo1_75sq.jpg</photo-url><tag>sale</tag></post></posts></tumblr>
100
+ EOF
101
+ response.strip!
102
+ end
103
+
104
+ def successful_authenticated_write_xml
105
+ "10001"
106
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hexorx-rumblr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Brent Hargrave
8
+ - Benny Wong
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-05-30 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: libxml-ruby
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 0.8.3
25
+ version:
26
+ description: Ruby client for the Tumblr API
27
+ email: brent.hargrave@gmail.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - LICENSE.rdoc
34
+ - README.rdoc
35
+ files:
36
+ - .gitignore
37
+ - LICENSE.rdoc
38
+ - README.rdoc
39
+ - Rakefile
40
+ - VERSION.yml
41
+ - lib/rumblr.rb
42
+ - lib/rumblr/client.rb
43
+ - lib/rumblr/post.rb
44
+ - lib/rumblr/resource.rb
45
+ - lib/rumblr/tumblelog.rb
46
+ - lib/rumblr/user.rb
47
+ - rumblr.gemspec
48
+ - spec/rumblr/client_spec.rb
49
+ - spec/rumblr/post_spec.rb
50
+ - spec/rumblr/tumblelog_spec.rb
51
+ - spec/rumblr/user_spec.rb
52
+ - spec/spec_helper.rb
53
+ has_rdoc: false
54
+ homepage: http://github.com/jamescallmebrent/rumblr
55
+ licenses:
56
+ post_install_message:
57
+ rdoc_options:
58
+ - --charset=UTF-8
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.3.5
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: Ruby client for the Tumblr API
80
+ test_files:
81
+ - spec/rumblr/client_spec.rb
82
+ - spec/rumblr/post_spec.rb
83
+ - spec/rumblr/tumblelog_spec.rb
84
+ - spec/rumblr/user_spec.rb
85
+ - spec/spec_helper.rb