douban-rails2.3 0.6.4
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 +3 -0
- data/MIT-LICENSE +20 -0
- data/README +53 -0
- data/Rakefile +18 -0
- data/VERSION +1 -0
- data/douban-rails2.3-0.6.0.gem +0 -0
- data/douban-rails2.3-0.6.1.gem +0 -0
- data/douban-rails2.3-0.6.2.gem +0 -0
- data/douban-rails2.3-0.6.3.gem +0 -0
- data/douban-rails2.3.gemspec +55 -0
- data/generators/douban/douban_generator.rb +50 -0
- data/generators/douban/templates/douban.yml +16 -0
- data/generators/douban/templates/douban_controller.rb +31 -0
- data/generators/douban/templates/douban_helper.rb +21 -0
- data/generators/douban/templates/douban_init.rb +7 -0
- data/lib/douban.rb +130 -0
- metadata +95 -0
data/.gitignore
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 [name of plugin creator]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
Douban
|
2
|
+
======
|
3
|
+
|
4
|
+
A Ruby wrapper for Douban(豆瓣) API, Rails 3 support only.
|
5
|
+
|
6
|
+
Install
|
7
|
+
=======
|
8
|
+
|
9
|
+
$ gem install douban
|
10
|
+
|
11
|
+
Usage
|
12
|
+
=======
|
13
|
+
|
14
|
+
1. Add below lines to your Gemfile:
|
15
|
+
|
16
|
+
gem 'douban', :require => 'oauth'
|
17
|
+
require 'douban'
|
18
|
+
|
19
|
+
2. Run generator
|
20
|
+
|
21
|
+
$ script/rails generate douban
|
22
|
+
|
23
|
+
3. Set you api key and secret in config/douban.yml, and include
|
24
|
+
DoubanHelper in your ApplicationController:
|
25
|
+
|
26
|
+
class ApplicationController
|
27
|
+
include DoubanHelper
|
28
|
+
end
|
29
|
+
|
30
|
+
4. Then you can insert below lines into your application layout
|
31
|
+
|
32
|
+
<% if douban_authorized? %>
|
33
|
+
<%= link_to 'Logout From Douban', douban_logout_path %>
|
34
|
+
<% else %>
|
35
|
+
<%= link_to "Login with douban", douban_login_path %>
|
36
|
+
<% end %>
|
37
|
+
|
38
|
+
Other available helpers:
|
39
|
+
|
40
|
+
* douban_auth_or_login_required, it's useful if you use RESTFUL_AUTH.
|
41
|
+
* douban_auth_required, you can add it to before_filter.
|
42
|
+
|
43
|
+
5. To access douban resources, you can simple call:
|
44
|
+
|
45
|
+
douban.get('/people/ahbei')
|
46
|
+
douban.post('/reviews', review)
|
47
|
+
|
48
|
+
6. To determine if your have authorized by user, simple call:
|
49
|
+
|
50
|
+
douban.authorized?
|
51
|
+
=> true # if your access token is valid.
|
52
|
+
|
53
|
+
Feedback are always welcome, Yuanyi Zhang(zhangyuanyi#gmail.com)
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |s|
|
7
|
+
s.name = "douban-rails2.3"
|
8
|
+
s.summary = "A Ruby wrapper of Douban(豆瓣) API"
|
9
|
+
s.email = "cheng.donghui@gmail.com"
|
10
|
+
s.homepage = "http://github.com/yzhang/douban"
|
11
|
+
s.description = "A Ruby wrapper of Douban(豆瓣) API"
|
12
|
+
s.authors = ["Yuanyi Zhang chengdh"]
|
13
|
+
s.files = FileList["[A-Z]*","{generators}/**/*", "{lib}/**/*", '.gitignore']
|
14
|
+
s.add_dependency 'oauth'
|
15
|
+
end
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
18
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.6.4
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{douban-rails2.3}
|
8
|
+
s.version = "0.6.4"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Yuanyi Zhang chengdh"]
|
12
|
+
s.date = %q{2010-08-14}
|
13
|
+
s.description = %q{A Ruby wrapper of Douban(豆瓣) API}
|
14
|
+
s.email = %q{cheng.donghui@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"MIT-LICENSE",
|
21
|
+
"README",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"douban-rails2.3-0.6.0.gem",
|
25
|
+
"douban-rails2.3-0.6.1.gem",
|
26
|
+
"douban-rails2.3-0.6.2.gem",
|
27
|
+
"douban-rails2.3-0.6.3.gem",
|
28
|
+
"douban-rails2.3.gemspec",
|
29
|
+
"generators/douban/douban_generator.rb",
|
30
|
+
"generators/douban/templates/douban.yml",
|
31
|
+
"generators/douban/templates/douban_controller.rb",
|
32
|
+
"generators/douban/templates/douban_helper.rb",
|
33
|
+
"generators/douban/templates/douban_init.rb",
|
34
|
+
"lib/douban.rb"
|
35
|
+
]
|
36
|
+
s.homepage = %q{http://github.com/yzhang/douban}
|
37
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
38
|
+
s.require_paths = ["lib"]
|
39
|
+
s.rubygems_version = %q{1.3.7}
|
40
|
+
s.summary = %q{A Ruby wrapper of Douban(豆瓣) API}
|
41
|
+
|
42
|
+
if s.respond_to? :specification_version then
|
43
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
44
|
+
s.specification_version = 3
|
45
|
+
|
46
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
47
|
+
s.add_runtime_dependency(%q<oauth>, [">= 0"])
|
48
|
+
else
|
49
|
+
s.add_dependency(%q<oauth>, [">= 0"])
|
50
|
+
end
|
51
|
+
else
|
52
|
+
s.add_dependency(%q<oauth>, [">= 0"])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class DoubanGenerator < Rails::Generator::Base
|
2
|
+
def manifest
|
3
|
+
record do |m|
|
4
|
+
m.file 'douban_controller.rb', 'app/controllers/douban_controller.rb'
|
5
|
+
m.file "douban_helper.rb", 'app/helpers/douban_helper.rb'
|
6
|
+
m.file "douban.yml", 'config/douban.yml'
|
7
|
+
m.file "douban_init.rb", 'config/initializers/douban_init.rb'
|
8
|
+
m.route :name => :douban_login,:controller => :douban,:action => :new
|
9
|
+
m.route :name => :douban_callback,:controller => :douban,:action => :callback
|
10
|
+
m.route :name => :douban_logout,:controller => :douban,:action => :destroy
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
#为rails genetator添加处理代码
|
15
|
+
module Rails
|
16
|
+
module Generator
|
17
|
+
module Commands
|
18
|
+
class Base
|
19
|
+
def route_code(route_options)
|
20
|
+
"map.#{route_options[:name]} '#{route_options[:name]}', :controller => '#{route_options[:controller]}', :action => '#{route_options[:action]}'"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Here's a readable version of the long string used above in route_code;
|
25
|
+
# but it should be kept on one line to avoid inserting extra whitespace
|
26
|
+
# into routes.rb when the generator is run:
|
27
|
+
# "map.#{route_options[:name]} '#{route_options[:name]}',
|
28
|
+
# :controller => '#{route_options[:controller]}',
|
29
|
+
# :action => '#{route_options[:action]}'"
|
30
|
+
|
31
|
+
class Create
|
32
|
+
def route(route_options)
|
33
|
+
sentinel = 'ActionController::Routing::Routes.draw do |map|'
|
34
|
+
logger.route route_code(route_options)
|
35
|
+
gsub_file 'config/routes.rb', /(#{Regexp.escape(sentinel)})/mi do |m|
|
36
|
+
"#{m}\n #{route_code(route_options)}\n"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Destroy
|
42
|
+
def route(route_options)
|
43
|
+
logger.remove_route route_code(route_options)
|
44
|
+
to_remove = "\n #{route_code(route_options)}"
|
45
|
+
gsub_file 'config/routes.rb', /(#{to_remove})/mi, ''
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
development:
|
2
|
+
key: "your api key from douban"
|
3
|
+
secret: "secret key"
|
4
|
+
url: "http://yoursite.com"
|
5
|
+
#获取单本书籍
|
6
|
+
book_url: "http://api.douban.com/book/subject/"
|
7
|
+
#获取多本书籍
|
8
|
+
books_url: "http://api.douban.com/book/subjects?"
|
9
|
+
production:
|
10
|
+
key: "your api key from douban"
|
11
|
+
secret: "secret key"
|
12
|
+
url: "http://yoursite.com"
|
13
|
+
#获取单本书籍
|
14
|
+
book_url: "http://api.douban.com/book/subject/"
|
15
|
+
#获取多本书籍
|
16
|
+
books_url: "http://api.douban.com/book/subjects?"
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class DoubanController < ApplicationController
|
2
|
+
def new
|
3
|
+
douban = Douban.new
|
4
|
+
douban.callback = douban_callback_url
|
5
|
+
authorize_url = douban.authorize_url
|
6
|
+
|
7
|
+
respond_to do |wants|
|
8
|
+
session[:back] = request.env['HTTP_REFERER'] unless request.env['HTTP_REFERER'].blank?
|
9
|
+
session[:douban] = douban.dump
|
10
|
+
wants.html {redirect_to authorize_url}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def callback
|
15
|
+
if session[:douban]
|
16
|
+
douban = Douban.load(session[:douban])
|
17
|
+
douban.authorize
|
18
|
+
session[:douban] = douban.dump
|
19
|
+
end
|
20
|
+
|
21
|
+
redirect_to(session[:back] || '/')
|
22
|
+
session[:back] = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def destroy
|
26
|
+
return unless douban_authorized?
|
27
|
+
session[:douban] = nil
|
28
|
+
douban.destroy
|
29
|
+
redirect_to '/'
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module DoubanHelper
|
2
|
+
def douban
|
3
|
+
@douban ||= (session[:douban] && session[:douban][:access_token]) ? Douban.load(session[:douban]) : nil
|
4
|
+
end
|
5
|
+
|
6
|
+
def douban_authorized?
|
7
|
+
!douban.nil?
|
8
|
+
end
|
9
|
+
|
10
|
+
def douban_auth_required
|
11
|
+
douban_authorized? || redirect_to(douban_auth_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
def douban_auth_or_login_required
|
15
|
+
douban_authorized? || login_required
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.included(base)
|
19
|
+
base.send :helper_method, :douban_authorized? if base.respond_to? :helper_method
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Include hook code here
|
2
|
+
douban_configs = YAML.load_file(File.join(RAILS_ROOT, 'config/douban.yml'))
|
3
|
+
|
4
|
+
ENV['DOUBAN_APP_KEY'] = douban_configs[RAILS_ENV]['key'].to_s
|
5
|
+
ENV['DOUBAN_APP_SECRET'] = douban_configs[RAILS_ENV]['secret']
|
6
|
+
ENV['DOUBAN_BOOK_URL'] = douban_configs[RAILS_ENV]['book_url']
|
7
|
+
ENV['DOUBAN_BOOKS_URL'] = douban_configs[RAILS_ENV]['books_url']
|
data/lib/douban.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'oauth'
|
2
|
+
|
3
|
+
class Douban
|
4
|
+
attr_accessor :callback, :request_token, :access_token
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def load(data)
|
8
|
+
access_token = data[:access_token]
|
9
|
+
access_token_secret = data[:access_token_secret]
|
10
|
+
|
11
|
+
douban = Douban.new(data[:request_token], data[:request_token_secret])
|
12
|
+
douban.access_token = OAuth::AccessToken.new(api_consumer, access_token, access_token_secret) if access_token
|
13
|
+
douban
|
14
|
+
end
|
15
|
+
|
16
|
+
def auth_consumer
|
17
|
+
@@auth_consumer ||= OAuth::Consumer.new(key, secret, {
|
18
|
+
:signature_method => "HMAC-SHA1",
|
19
|
+
:site => "http://www.douban.com",
|
20
|
+
:scheme => :header,
|
21
|
+
:request_token_path => '/service/auth/request_token',
|
22
|
+
:access_token_path => '/service/auth/access_token',
|
23
|
+
:authorize_path => '/service/auth/authorize',
|
24
|
+
:realm => url
|
25
|
+
})
|
26
|
+
end
|
27
|
+
|
28
|
+
def api_consumer
|
29
|
+
@@api_consumer ||= OAuth::Consumer.new(key, secret,
|
30
|
+
{
|
31
|
+
:site => "http://api.douban.com",
|
32
|
+
:scheme => :header,
|
33
|
+
:signature_method => "HMAC-SHA1",
|
34
|
+
:realm => url
|
35
|
+
})
|
36
|
+
end
|
37
|
+
|
38
|
+
def key; config['key']; end
|
39
|
+
def secret; config['secret']; end
|
40
|
+
def url; config['url']; end
|
41
|
+
|
42
|
+
def config
|
43
|
+
@@config ||= lambda do
|
44
|
+
require 'yaml'
|
45
|
+
filename = "#{Rails.root}/config/douban.yml"
|
46
|
+
file = File.open(filename)
|
47
|
+
yaml = YAML.load(file)
|
48
|
+
return yaml[Rails.env]
|
49
|
+
end.call
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize(request_token = nil, request_token_secret = nil)
|
54
|
+
if request_token && request_token_secret
|
55
|
+
self.request_token = OAuth::RequestToken.new(self.class.auth_consumer, request_token, request_token_secret)
|
56
|
+
else
|
57
|
+
self.request_token = self.class.auth_consumer.get_request_token()
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def authorize_url
|
62
|
+
@authorize_url ||= request_token.authorize_url(:oauth_callback => self.callback)
|
63
|
+
end
|
64
|
+
|
65
|
+
def authorize
|
66
|
+
return unless self.access_token.nil?
|
67
|
+
|
68
|
+
access_token = self.request_token.get_access_token
|
69
|
+
self.access_token ||= OAuth::AccessToken.new(self.class.api_consumer, access_token.token, access_token.secret)
|
70
|
+
end
|
71
|
+
|
72
|
+
def authorized?
|
73
|
+
return false if access_token.nil?
|
74
|
+
response = self.get("/access_token/#{access_token.token}")
|
75
|
+
response.code == '200'
|
76
|
+
end
|
77
|
+
|
78
|
+
def destroy
|
79
|
+
destroy_access_key if !access_token.nil?
|
80
|
+
request_token = access_token = nil
|
81
|
+
end
|
82
|
+
|
83
|
+
def dump
|
84
|
+
{
|
85
|
+
:request_token => request_token.token,
|
86
|
+
:request_token_secret => request_token.secret,
|
87
|
+
:access_token => access_token.nil? ? nil : access_token.token,
|
88
|
+
:access_token_secret => access_token.nil? ? nil : access_token.secret
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
def request(http_method, path, headers = {})
|
93
|
+
access_token.request(http_method, path, headers)
|
94
|
+
end
|
95
|
+
|
96
|
+
def get(path, headers = {})
|
97
|
+
request(:get, path, headers)
|
98
|
+
end
|
99
|
+
|
100
|
+
def post(path, headers = {})
|
101
|
+
request(:post, path, headers)
|
102
|
+
end
|
103
|
+
|
104
|
+
def delete(path, headers = {})
|
105
|
+
request(:delete, path, headers)
|
106
|
+
end
|
107
|
+
|
108
|
+
def put(path, headers = {})
|
109
|
+
request(:put, path, headers)
|
110
|
+
end
|
111
|
+
#使用isbn获取单本书籍信息
|
112
|
+
def get_book(isbn)
|
113
|
+
url = ENV['DOUBAN_BOOK_URL'] + isbn
|
114
|
+
rsp = Net::HTTP.get_response(URI.parse(url))
|
115
|
+
rsp.body
|
116
|
+
end
|
117
|
+
#使用模糊查询获取多本书籍
|
118
|
+
def get_books(params = {})
|
119
|
+
q_str = params.to_query
|
120
|
+
url = ENV['DOUBAN_BOOKS_URL'] + q_str
|
121
|
+
rsp = Net::HTTP.get_response(URI.parse(url))
|
122
|
+
rsp.body
|
123
|
+
end
|
124
|
+
|
125
|
+
protected
|
126
|
+
def destroy_access_key
|
127
|
+
response = delete("/access_token/#{access_token.token}")
|
128
|
+
response.code == '200'
|
129
|
+
end
|
130
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: douban-rails2.3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 6
|
9
|
+
- 4
|
10
|
+
version: 0.6.4
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Yuanyi Zhang chengdh
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-08-14 00:00:00 +08:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: oauth
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
description: "A Ruby wrapper of Douban(\xE8\xB1\x86\xE7\x93\xA3) API"
|
36
|
+
email: cheng.donghui@gmail.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- README
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- MIT-LICENSE
|
46
|
+
- README
|
47
|
+
- Rakefile
|
48
|
+
- VERSION
|
49
|
+
- douban-rails2.3-0.6.0.gem
|
50
|
+
- douban-rails2.3-0.6.1.gem
|
51
|
+
- douban-rails2.3-0.6.2.gem
|
52
|
+
- douban-rails2.3-0.6.3.gem
|
53
|
+
- douban-rails2.3.gemspec
|
54
|
+
- generators/douban/douban_generator.rb
|
55
|
+
- generators/douban/templates/douban.yml
|
56
|
+
- generators/douban/templates/douban_controller.rb
|
57
|
+
- generators/douban/templates/douban_helper.rb
|
58
|
+
- generators/douban/templates/douban_init.rb
|
59
|
+
- lib/douban.rb
|
60
|
+
has_rdoc: true
|
61
|
+
homepage: http://github.com/yzhang/douban
|
62
|
+
licenses: []
|
63
|
+
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options:
|
66
|
+
- --charset=UTF-8
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
hash: 3
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
version: "0"
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
hash: 3
|
84
|
+
segments:
|
85
|
+
- 0
|
86
|
+
version: "0"
|
87
|
+
requirements: []
|
88
|
+
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 1.3.7
|
91
|
+
signing_key:
|
92
|
+
specification_version: 3
|
93
|
+
summary: "A Ruby wrapper of Douban(\xE8\xB1\x86\xE7\x93\xA3) API"
|
94
|
+
test_files: []
|
95
|
+
|