tumblr4r 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog CHANGED
@@ -1,3 +1,8 @@
1
+ == 0.8.0 / 2011-02-20
2
+ * new: dashboard support.
3
+ * new: active_support 3.0 support.
4
+
5
+
1
6
  == 0.7.2 / 2009-10-15
2
7
  * new: photoset support added.(Thanks to http://github.com/smajda for the patch.)
3
8
 
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ require 'rake/rdoctask'
8
8
  require 'rake/contrib/rubyforgepublisher'
9
9
  require 'rake/contrib/sshpublisher'
10
10
  require 'fileutils'
11
- require 'lib/tumblr4r'
11
+ require './lib/tumblr4r'
12
12
  include FileUtils
13
13
 
14
14
  NAME = "tumblr4r"
data/lib/tumblr4r.rb CHANGED
@@ -1,12 +1,25 @@
1
+ # -*- coding: utf-8 -*-
1
2
  require 'net/http'
2
3
  require 'rubygems'
3
4
  require 'rexml/document'
4
- require 'active_support'
5
+ begin
6
+ require 'active_support/core_ext'
7
+ require 'active_support/core_ext'
8
+ rescue
9
+ require 'activesupport'
10
+ end
11
+
5
12
  require 'logger'
6
13
  require 'cgi'
14
+
7
15
  module Tumblr4r
8
- VERSION = '0.7.2'
16
+ VERSION = '0.8.0'
9
17
  class TumblrError < StandardError
18
+ attr_accessor :attachment
19
+ def initialize(msg, attachment=nil)
20
+ super(msg)
21
+ @attachment = attachment
22
+ end
10
23
  end
11
24
 
12
25
  module POST_TYPE
@@ -28,9 +41,9 @@ module Tumblr4r
28
41
  attr_accessor :hostname, :email, :password, :name, :timezone, :title, :cname,
29
42
  :description, :feeds
30
43
  attr_accessor :logger
31
- # TODO: 変数名もうちょっと考える
32
- API_READ_LIMIT = 50
33
- @@default_log_level = Logger::INFO
44
+ API_READ_MAX_ALLOWED_COUNT = 50
45
+ SLEEP_SECONDS_FOR_EVERY_FETCH = 10.0 # API manual says "Requests are rate-limited to one every 10 seconds."
46
+ @@default_log_level = Logger::DEBUG
34
47
  cattr_accessor :default_log_level
35
48
 
36
49
  class << self
@@ -59,71 +72,127 @@ module Tumblr4r
59
72
  self.site_info
60
73
  end
61
74
 
62
- # TODO: ここの再帰取得ロジックはTumblrAPIとは独立してるので
63
- # TumblrAPIとは独立した形に切り出したり、TumblrAPIとは切り離してテストを書きたいものだ
64
75
  # @param [Symbol|Integer] id_or_type :all, id
76
+ # @param [Hash] options :offset, :limit, :type, :filter, :tagged, :search,
65
77
  # @return [Array<Post>|Post]
66
78
  def find(id_or_type, options = { })
79
+ if id_or_type == :all
80
+ normal_find(options)
81
+ elsif id_or_type.kind_of?(Integer)
82
+ xml = @conn.get({:id => id_or_type})
83
+ posts, start, total = @parser.posts(xml)
84
+ @logger.info("size: #{posts.size}")
85
+ @logger.info("start: #{start}")
86
+ @logger.info("total: #{total}")
87
+ return posts[0]
88
+ else
89
+ raise ArgumentError.new("id_or_type must be :all or Integer, but was #{id_or_type}(<#{id_or_type.class}>)")
90
+ end
91
+ end
92
+
93
+ # TODO: ループごとに実行して欲しい処理をblockで渡せるようにするといいかも?
94
+ # そのブロック引数にエラー情報も渡してあげれば、エラーが起きたのならretryだな、みたいな
95
+ # 指示ができない、、、、かな
96
+ def normal_find(options)
97
+ limit = options[:limit] && options[:limit].to_i
98
+ offset = options[:offset].to_i
99
+ total = self.count(options)
100
+ result = []
67
101
  params = { }
68
- return result if options[:offset] && options[:offset].to_i < 0
69
102
  [:type, :filter, :tagged, :search].each do |option|
70
103
  params[option] = options[option] if options[option]
71
104
  end
72
-
73
- if id_or_type == :all
74
- result = []
75
- # 取得開始位置の初期化
76
- params[:start] = options[:offset] || 0
77
- # goal の設定
78
- total = self.count(options)
79
- if options[:limit]
80
- goal = [total - params[:start],
81
- options[:limit]].min
82
- else
83
- goal = total - params[:start]
105
+ last_fetched_at = nil
106
+ each_fetch(limit, offset, API_READ_MAX_ALLOWED_COUNT, total) do |offset, num|
107
+ params[:start] = offset
108
+ params[:num] = num
109
+ # APIマニュアルにはこっちのスリープ時間については明記されてないが、dashboardと同じ秒数SLEEPしとく
110
+ sleep_secs = last_fetched_at ? SLEEP_SECONDS_FOR_EVERY_FETCH - (Time.now - last_fetched_at) : 0
111
+ if sleep_secs > 0
112
+ logger.debug("sleeping #{sleep_secs} secs.")
113
+ sleep sleep_secs
84
114
  end
85
- # 取得件数の初期化
86
- if goal < 0
87
- return result
88
- elsif goal < API_READ_LIMIT
89
- params[:num] = goal
90
- else
91
- params[:num] = API_READ_LIMIT # :num を指定しないとデフォルトでは20件しかとれない
115
+ xml = @conn.get(params)
116
+ last_fetched_at = Time.now
117
+ posts, start, total = @parser.posts(xml)
118
+ result += posts
119
+ if posts.size == 0
120
+ # Tumblr API の total で得られる値は全く信用ならない。
121
+ # 検索条件を考慮した件数を返してくれない。
122
+ # (つまり、goalは信用ならない)ので、posts.sizeも終了判定に利用する。
123
+ # TODO: もしくは:numの値を足し合わせていって、それとgoalを比較する?
124
+ break
92
125
  end
126
+ posts.size
127
+ end
128
+ result
129
+ end
93
130
 
94
- loop do
95
- xml = @conn.get(params)
96
- posts, start, total = @parser.posts(xml)
97
- @logger.info("size: #{posts.size}")
98
- @logger.info("start: #{start}")
99
- @logger.info("total: #{total}")
100
- result += posts
101
- if result.size >= goal || posts.size == 0
102
- # Tumblr API の total で得られる値は全く信用ならない。
103
- # 検索条件を考慮した件数を返してくれない。
104
- # (つまり、goalは信用ならない)ので、posts.sizeも終了判定に利用する。
105
- # TODO: もしくは:numの値を足し合わせていって、それとgoalを比較する?
106
- break
107
- end
108
- # 取得開始位置の調整
109
- params[:start] += params[:num]
110
- # 取得件数の調整
111
- if (goal - result.size) >= API_READ_LIMIT
112
- params[:num] = API_READ_LIMIT
113
- else
114
- params[:num] = goal - result.size
115
- end
131
+ #, :search,
132
+ # @param [Hash] options :offset, :limit, :type, :filter
133
+ # @return [Array<Post>]
134
+ def dashboard(options = { })
135
+ limit = options[:limit] ? options[:limit].to_i : nil
136
+ offset = options[:offset].to_i
137
+ result = []
138
+ params = {:likes => "1" }
139
+ [:type, :filter].each do |option|
140
+ params[option] = options[option] if options[option]
141
+ end
142
+
143
+ total = 1000 # 明記されてないがたぶん1000件ぐらいが上限?
144
+ last_fetched_at = nil
145
+ each_fetch(limit, offset, API_READ_MAX_ALLOWED_COUNT, total) do |offset, num|
146
+ params[:start] = offset
147
+ params[:num] = num
148
+ sleep_secs = last_fetched_at ? SLEEP_SECONDS_FOR_EVERY_FETCH - (Time.now - last_fetched_at) : 0
149
+ if sleep_secs > 0
150
+ logger.debug("sleeping #{sleep_secs} secs.")
151
+ sleep sleep_secs
116
152
  end
117
- return result
118
- elsif id_or_type.kind_of?(Integer)
119
- xml = @conn.get({:id => id_or_type})
153
+ xml = @conn.dashboard(params)
154
+ last_fetched_at = Time.now
120
155
  posts, start, total = @parser.posts(xml)
121
- @logger.info("size: #{posts.size}")
156
+ result += posts
157
+ if posts.size == 0
158
+ # Tumblr API の total で得られる値は全く信用ならない。
159
+ # 検索条件を考慮した件数を返してくれない。
160
+ # (つまり、goalは信用ならない)ので、posts.sizeも終了判定に利用する。
161
+ # TODO: もしくは:numの値を足し合わせていって、それとgoalを比較する?
162
+ break
163
+ end
164
+ posts.size
165
+ end
166
+ result
167
+ end
168
+
169
+ def each_fetch(limit, offset, max_at_once, total, &block)
170
+ return if offset && offset.to_i < 0
171
+
172
+ # 取得開始位置の初期化
173
+ start = offset || 0
174
+ if limit
175
+ goal = [total - start, limit].min
176
+ else
177
+ goal = total - start
178
+ end
179
+ # 取得件数の初期化
180
+ num = [goal, max_at_once].min
181
+ if num < 0
182
+ return
183
+ end
184
+
185
+ all_fetched = 0
186
+ while all_fetched < goal
187
+ fetched_count = yield(start, num)
188
+ @logger.info("size: #{fetched_count}")
122
189
  @logger.info("start: #{start}")
123
190
  @logger.info("total: #{total}")
124
- return posts[0]
125
- else
126
- raise ArgumentError
191
+ all_fetched += fetched_count
192
+ # 取得開始位置の調整
193
+ start += num
194
+ # 取得件数の調整
195
+ num = [goal - fetched_count, max_at_once].min
127
196
  end
128
197
  end
129
198
 
@@ -150,8 +219,17 @@ module Tumblr4r
150
219
  return new_post
151
220
  end
152
221
 
153
- # @param [Integer] post_id
154
- def delete(post_id)
222
+ # @param [Integer|Post] post_id_or_post
223
+ def delete(post_id_or_post)
224
+ post_id = nil
225
+ case post_id_or_post
226
+ when Tumblr4r::Post
227
+ post_id = post_id_or_post.post_id
228
+ when Integer
229
+ post_id = post_id_or_post
230
+ else
231
+ raise ArgumentError.new("post_id_or_post must be Tumblr4r::Post or Integer, but was #{post_id_or_post}(<#{post_id_or_post.class}>)")
232
+ end
155
233
  return @conn.delete(post_id)
156
234
  end
157
235
 
@@ -173,6 +251,9 @@ module Tumblr4r
173
251
  :private, # Integer(0|1)
174
252
  :generator # String
175
253
 
254
+ attr_accessor :liked, # Boolean
255
+ :reblog_key # String
256
+
176
257
  @@default_generator = nil
177
258
  cattr_accessor :default_generator
178
259
 
@@ -293,7 +374,7 @@ module Tumblr4r
293
374
  when Net::HTTP
294
375
  @conn = http_or_hostname
295
376
  else
296
- raise ArgumentError.new("http_or_hostname must be String or Net::HTTP")
377
+ raise ArgumentError.new("http_or_hostname must be String or Net::HTTP but is #{http_or_hostname.class}")
297
378
  end
298
379
  @email= email
299
380
  @password = password
@@ -321,9 +402,25 @@ module Tumblr4r
321
402
  when Net::HTTPOK
322
403
  return res.body
323
404
  when Net::HTTPNotFound
324
- raise TumblrError.new("no such site(#{@hostname})")
405
+ raise TumblrError.new("no such site(#{@hostname})", res)
325
406
  else
326
- raise TumblrError.new("unexpected response #{res.inspect}")
407
+ raise TumblrError.new("unexpected response #{res.inspect}", res)
408
+ end
409
+ end
410
+
411
+ def dashboard(options = { })
412
+ response = nil
413
+ http = Net::HTTP.new("www.tumblr.com")
414
+ params = options.merge({"email" => @email, "password" => @password, "group" => @group})
415
+ query_string = params.delete_if{|k,v| v == nil }.map{|k,v| "#{k}=#{CGI.escape(v.to_s)}" unless v.nil?}.join("&")
416
+ logger.debug("#### query_string: #{query_string}")
417
+ response = http.post('/api/dashboard', query_string)
418
+ logger.debug(response.body)
419
+ case response
420
+ when Net::HTTPSuccess
421
+ return response.body
422
+ else
423
+ raise TumblrError.new(format_error(response), response)
327
424
  end
328
425
  end
329
426
 
@@ -339,7 +436,7 @@ module Tumblr4r
339
436
  when Net::HTTPOK
340
437
  return true
341
438
  else
342
- raise TumblrError.new(response.inspect + "\n" + response.body)
439
+ raise TumblrError.new(format_error(response), response)
343
440
  end
344
441
  end
345
442
 
@@ -358,10 +455,7 @@ module Tumblr4r
358
455
  when Net::HTTPSuccess
359
456
  return response.body.to_i
360
457
  else
361
- msg = response.inspect + "\n"
362
- response.each{|k,v| msg += "#{k}: #{v}\n"}
363
- msg += response.body
364
- raise TumblrError.new(msg)
458
+ raise TumblrError.new(format_error(response), response)
365
459
  end
366
460
  end
367
461
 
@@ -379,12 +473,16 @@ module Tumblr4r
379
473
  logger.debug("#### response: #{response.code}: #{response.body}")
380
474
  return true
381
475
  else
382
- msg = response.inspect + "\n"
383
- response.each{|k,v| msg += "#{k}: #{v}\n"}
384
- msg += response.body
385
- raise TumblrError.new(msg)
476
+ raise TumblrError.new(format_error(response), response)
386
477
  end
387
478
  end
479
+
480
+ def format_error(response)
481
+ msg = response.inspect + "\n"
482
+ response.each{|k,v| msg += "#{k}: #{v}\n"}
483
+ msg += response.body
484
+ msg
485
+ end
388
486
  end
389
487
 
390
488
  # Tumblr XML API
@@ -446,6 +544,8 @@ module Tumblr4r
446
544
  post.post_id = rexml_post.attributes["id"].to_i
447
545
  post.url = rexml_post.attributes["url"]
448
546
  post.url_with_slug = rexml_post.attributes["url-with-slug"]
547
+ post.liked = (rexml_post.attributes["liked"] == "true")
548
+ post.reblog_key = rexml_post.attributes["reblog-key"]
449
549
  post.type = rexml_post.attributes["type"]
450
550
  # TODO: time 関係の型をStringじゃなくTimeとかにする?
451
551
  post.date_gmt = rexml_post.attributes["date-gmt"]
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+ require "test/unit"
3
+ require 'pit'
4
+ require 'pp'
5
+ $KCODE='u'
6
+ class Tumblr4rDashboardTest < Test::Unit::TestCase
7
+ include Tumblr4r
8
+ DASHBOARD_TEST_HOST = "tumblr4r-dashboard-test.tumblr.com"
9
+ TOTAL_COUNT = 123
10
+ REGULAR_COUNT = 6
11
+ QUOTE_COUNT = 103
12
+ PHOTO_COUNT = 2
13
+
14
+ def setup
15
+ Site.default_log_level = Logger::DEBUG
16
+ auth_info = Pit.get("tumblr4r-dashbard-test",
17
+ :require => {"email" => "required email",
18
+ "password" => "required password"})
19
+ @site = Site.new(DASHBOARD_TEST_HOST,
20
+ auth_info["email"],
21
+ auth_info["password"])
22
+ end
23
+
24
+ def teardown
25
+ end
26
+ =begin
27
+ def test_find_all
28
+ posts = @site.dashboard
29
+ pp posts
30
+ assert_equal TOTAL_COUNT, posts.size
31
+ end
32
+ =end
33
+ def test_type
34
+ posts = @site.dashboard(:type => "regular")
35
+ assert_equal REGULAR_COUNT, posts.size
36
+ assert posts.all?{|p| p.type == Tumblr4r::POST_TYPE::REGULAR }
37
+
38
+ posts = @site.dashboard(:type => "quote")
39
+ assert_equal QUOTE_COUNT, posts.size
40
+ assert posts.all?{|p| p.type == Tumblr4r::POST_TYPE::QUOTE }
41
+
42
+ posts = @site.dashboard(:type => "photo")
43
+ assert_equal PHOTO_COUNT, posts.size
44
+ assert posts.all?{|p| p.type == Tumblr4r::POST_TYPE::PHOTO }
45
+ end
46
+ end
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  require File.dirname(__FILE__) + '/test_helper.rb'
2
3
  require "test/unit"
3
4
  require 'pit'
@@ -53,6 +54,7 @@ class Tumblr4rTest < Test::Unit::TestCase
53
54
  end
54
55
 
55
56
  def test_find
57
+ debugger
56
58
  posts = @site.find(:all)
57
59
  assert_equal 9, posts.size
58
60
  assert_equal Photo, posts[0].class
@@ -144,7 +146,7 @@ EOF
144
146
  assert_equal false, posts[1].bookmarklet
145
147
 
146
148
  assert_equal "", posts[1].regular_title
147
- assert_equal "Tumblr4rのテストです", posts[1].regular_body
149
+ assert_equal "<p>Tumblr4rのテストです</p>", posts[1].regular_body
148
150
  end
149
151
 
150
152
  def test_find_with_type_photo
@@ -166,7 +168,7 @@ EOF
166
168
 
167
169
  assert_equal "<p>Photoのテストです。</p>\n\n<p>ギコです。</p>", posts[1].photo_caption
168
170
  assert_equal "http://www.google.co.jp/", posts[1].photo_link_url
169
- assert_equal "http://5.media.tumblr.com/GyEYZujUYopiula4XKmXhCgmo1_250.jpg", posts[1].photo_url
171
+ assert_equal "http://28.media.tumblr.com/GyEYZujUYopiula4XKmXhCgmo1_250.jpg", posts[1].photo_url
170
172
  assert_equal [], posts[1].photoset
171
173
 
172
174
  # photoset
@@ -182,12 +184,12 @@ EOF
182
184
  assert_equal [], posts[0].tags
183
185
  assert_equal false, posts[0].bookmarklet
184
186
 
185
- assert_equal "Photoset test.", posts[0].photo_caption
187
+ assert_equal "<p>Photoset test.</p>", posts[0].photo_caption
186
188
  assert_equal "", posts[0].photo_link_url
187
- assert_equal "http://22.media.tumblr.com/tumblr_krg7btBOD21qzfaavo1_250.jpg", posts[0].photo_url
188
- assert_equal ["http://22.media.tumblr.com/tumblr_krg7btBOD21qzfaavo1_250.jpg",
189
- "http://6.media.tumblr.com/tumblr_krg7btBOD21qzfaavo2_500.jpg",
190
- "http://16.media.tumblr.com/tumblr_krg7btBOD21qzfaavo3_500.png"], posts[0].photoset
189
+ assert_equal "http://25.media.tumblr.com/tumblr_krg7btBOD21qzfaavo1_250.jpg", posts[0].photo_url
190
+ assert_equal ["http://25.media.tumblr.com/tumblr_krg7btBOD21qzfaavo1_250.jpg",
191
+ "http://30.media.tumblr.com/tumblr_krg7btBOD21qzfaavo2_500.jpg",
192
+ "http://27.media.tumblr.com/tumblr_krg7btBOD21qzfaavo3_500.png"], posts[0].photoset
191
193
 
192
194
  end
193
195
 
@@ -229,7 +231,7 @@ EOF
229
231
 
230
232
  assert_equal "たんぶらー", posts[0].link_text
231
233
  assert_equal "http://www.tumblr.com/", posts[0].link_url
232
- assert_equal "ですくりぷしょん", posts[0].link_description
234
+ assert_equal "<p>ですくりぷしょん</p>", posts[0].link_description
233
235
  end
234
236
 
235
237
  def test_find_with_type_conversation
@@ -274,8 +276,9 @@ EOF
274
276
  assert_equal false, posts[0].bookmarklet
275
277
 
276
278
  assert_equal true, posts[0].audio_plays
277
- assert_equal "tumblr4r miku", posts[0].audio_caption
278
- assert_equal "<embed type=\"application/x-shockwave-flash\" src=\"http://tumblr4rtest.tumblr.com/swf/audio_player.swf?audio_file=http://www.tumblr.com/audio_file/131705561/GyEYZujUYp9df3nv1WMefTH8&color=FFFFFF\" height=\"27\" width=\"207\" quality=\"best\"></embed>", posts[0].audio_player
279
+ assert_equal "<p>tumblr4r miku</p>", posts[0].audio_caption
280
+ # assert_equal "<embed type=\"application/x-shockwave-flash\" src=\"http://tumblr4rtest.tumblr.com/swf/audio_player.swf?audio_file=http://www.tumblr.com/audio_file/131705561/GyEYZujUYp9df3nv1WMefTH8&color=FFFFFF\" height=\"27\" width=\"207\" quality=\"best\"></embed>", posts[0].audio_player
281
+ assert_equal "<embed type=\"application/x-shockwave-flash\" src=\"http://assets.tumblr.com/swf/audio_player.swf?audio_file=http://www.tumblr.com/audio_file/131705561/GyEYZujUYp9df3nv1WMefTH8&color=FFFFFF\" height=\"27\" width=\"207\" quality=\"best\"></embed>", posts[0].audio_player
279
282
  end
280
283
 
281
284
  def test_find_with_type_video
@@ -293,9 +296,9 @@ EOF
293
296
  assert_equal [], posts[0].tags
294
297
  assert_equal false, posts[0].bookmarklet
295
298
 
296
- assert_equal "matrix sappoloaded", posts[0].video_caption
299
+ assert_equal "<p>matrix sappoloaded</p>", posts[0].video_caption
297
300
  assert_equal "http://www.youtube.com/watch?v=FavWH5RhYpw", posts[0].video_source
298
- assert_equal "<object width=\"400\" height=\"336\"><param name=\"movie\" value=\"http://www.youtube.com/v/FavWH5RhYpw&amp;rel=0&amp;egm=0&amp;showinfo=0&amp;fs=1\"></param><param name=\"wmode\" value=\"transparent\"></param><param name=\"allowFullScreen\" value=\"true\"></param><embed src=\"http://www.youtube.com/v/FavWH5RhYpw&amp;rel=0&amp;egm=0&amp;showinfo=0&amp;fs=1\" type=\"application/x-shockwave-flash\" width=\"400\" height=\"336\" allowFullScreen=\"true\" wmode=\"transparent\"></embed></object>", posts[0].video_player
301
+ assert_equal "<object width=\"400\" height=\"325\"><param name=\"movie\" value=\"http://www.youtube.com/v/FavWH5RhYpw&amp;rel=0&amp;egm=0&amp;showinfo=0&amp;fs=1\"></param><param name=\"wmode\" value=\"transparent\"></param><param name=\"allowFullScreen\" value=\"true\"></param><embed src=\"http://www.youtube.com/v/FavWH5RhYpw&amp;rel=0&amp;egm=0&amp;showinfo=0&amp;fs=1\" type=\"application/x-shockwave-flash\" width=\"400\" height=\"325\" allowFullScreen=\"true\" wmode=\"transparent\"></embed></object>", posts[0].video_player
299
302
  end
300
303
 
301
304
  def test_find_with_tagged
@@ -402,6 +405,5 @@ EOF
402
405
  videos = @site.find(:all, :type => Tumblr4r::POST_TYPE::VIDEO)
403
406
  post = @write_site.save(videos[0])
404
407
  end
405
-
406
408
  end
407
409
 
metadata CHANGED
@@ -1,7 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tumblr4r
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ prerelease:
5
+ version: 0.8.0
5
6
  platform: ruby
6
7
  authors:
7
8
  - Tomoki MAEDA
@@ -9,29 +10,30 @@ autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
12
 
12
- date: 2009-10-15 00:00:00 +09:00
13
- default_executable:
13
+ date: 2012-01-26 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
23
  version: 2.3.2
24
- version:
24
+ type: :runtime
25
+ version_requirements: *id001
25
26
  - !ruby/object:Gem::Dependency
26
27
  name: pit
27
- type: :development
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
30
31
  requirements:
31
32
  - - ">="
32
33
  - !ruby/object:Gem::Version
33
34
  version: 0.0.6
34
- version:
35
+ type: :development
36
+ version_requirements: *id002
35
37
  description: Tumblr API Wrapper for Ruby
36
38
  email: tmaeda@ruby-sapporo.org
37
39
  executables: []
@@ -46,10 +48,12 @@ files:
46
48
  - ChangeLog
47
49
  - Rakefile
48
50
  - test/test_helper.rb
51
+ - test/tumblr4r_dashboard_test.rb
49
52
  - test/tumblr4r_test.rb
50
53
  - lib/tumblr4r.rb
51
- has_rdoc: true
52
54
  homepage: http://tumblr4r.rubyforge.org
55
+ licenses: []
56
+
53
57
  post_install_message:
54
58
  rdoc_options:
55
59
  - --title
@@ -67,23 +71,24 @@ rdoc_options:
67
71
  require_paths:
68
72
  - lib
69
73
  required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
70
75
  requirements:
71
76
  - - ">="
72
77
  - !ruby/object:Gem::Version
73
78
  version: 1.8.6
74
- version:
75
79
  required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
76
81
  requirements:
77
82
  - - ">="
78
83
  - !ruby/object:Gem::Version
79
84
  version: "0"
80
- version:
81
85
  requirements: []
82
86
 
83
87
  rubyforge_project: tumblr4r
84
- rubygems_version: 1.3.1
88
+ rubygems_version: 1.8.11
85
89
  signing_key:
86
- specification_version: 2
90
+ specification_version: 3
87
91
  summary: Tumblr API Wrapper for Ruby
88
92
  test_files:
93
+ - test/tumblr4r_dashboard_test.rb
89
94
  - test/tumblr4r_test.rb