hexorx-rumblr 0.0.3

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/.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