goodreads 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +1 -0
- data/README.md +1 -1
- data/lib/goodreads/client.rb +11 -2
- data/lib/goodreads/client/reviews.rb +56 -0
- data/lib/goodreads/client/shelves.rb +68 -0
- data/lib/goodreads/request.rb +37 -6
- data/lib/goodreads/version.rb +1 -1
- data/spec/authentication_spec.rb +24 -11
- data/spec/client_spec.rb +185 -1
- data/spec/fixtures/review_create.xml +102 -0
- data/spec/fixtures/review_show_by_user_and_book.xml +144 -0
- data/spec/fixtures/review_update.xml +104 -0
- data/spec/fixtures/shelf_add_to_shelf.xml +24 -0
- data/spec/fixtures/shelf_list.xml +51 -0
- data/spec/goodreads_spec.rb +1 -1
- metadata +13 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7c94efd63197915ee10a6ba023cb810e4fac84c2943f4544e83642f2a002a0ec
|
4
|
+
data.tar.gz: ce3afa10705116414371ac7b21788c6e6114e7d7a691a31fdd7f49fd80d6e266
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58091fa38ec8c80c653e0f50ec46e401e5a5a3eb048354cd11e2b9591a20e2011d401f5816e3dc2ca63107974a084e12af9bf2184103162e61b576a30499afc1
|
7
|
+
data.tar.gz: d602443eae15c2cf6123d21242f5ac68c90314eb15e4b9d45603234aaafc2b814eb2c1ecae1ae57daa289db895ab2fb595f0c223755163d85845ae285b1f292a
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
data/lib/goodreads/client.rb
CHANGED
@@ -31,9 +31,18 @@ module Goodreads
|
|
31
31
|
def initialize(options = {})
|
32
32
|
fail(ArgumentError, "Options hash required.") unless options.is_a?(Hash)
|
33
33
|
|
34
|
-
@api_key
|
35
|
-
@api_secret
|
34
|
+
@api_key = options[:api_key] || Goodreads.configuration[:api_key]
|
35
|
+
@api_secret = options[:api_secret] || Goodreads.configuration[:api_secret]
|
36
36
|
@oauth_token = options[:oauth_token]
|
37
37
|
end
|
38
|
+
|
39
|
+
# Return if this client is configured with OAuth credentials
|
40
|
+
# for a single user
|
41
|
+
#
|
42
|
+
# False when client is instantiated with an api_key and secret,
|
43
|
+
# true when client is instantiated with an oauth_token
|
44
|
+
def oauth_configured?
|
45
|
+
!oauth_token.nil?
|
46
|
+
end
|
38
47
|
end
|
39
48
|
end
|
@@ -31,5 +31,61 @@ module Goodreads
|
|
31
31
|
[]
|
32
32
|
end
|
33
33
|
end
|
34
|
+
|
35
|
+
# Get a user's review for a given book
|
36
|
+
def user_review(user_id, book_id, params = {})
|
37
|
+
data = request('/review/show_by_user_and_book.xml', params.merge(v: "2", user_id: user_id, book_id: book_id))
|
38
|
+
Hashie::Mash.new(data["review"])
|
39
|
+
end
|
40
|
+
|
41
|
+
# Add review for a book
|
42
|
+
#
|
43
|
+
# Params can include :review, :rating, and :shelf
|
44
|
+
#
|
45
|
+
# review: text of the review (optional)
|
46
|
+
# rating: rating (0-5) (optional, default is 0 (no rating))
|
47
|
+
# shelf: Name of shelf to add book to (optional, must exist, see: shelves.list)
|
48
|
+
#
|
49
|
+
# Note that Goodreads API documentation says that this endpoint accepts
|
50
|
+
# the read_at parameter but it does not appear to work as of 2018-06.
|
51
|
+
def create_review(book_id, params = {})
|
52
|
+
params = params.merge(book_id: book_id, v: "2")
|
53
|
+
|
54
|
+
params[:read_at] = params[:read_at].strftime('%Y-%m-%d') if params[:read_at].is_a?(Time)
|
55
|
+
|
56
|
+
params[:'review[review]'] = params.delete(:review) if params[:review]
|
57
|
+
params[:'review[rating]'] = params.delete(:rating) if params[:rating]
|
58
|
+
params[:'review[read_at]'] = params.delete(:read_at) if params[:read_at]
|
59
|
+
|
60
|
+
data = oauth_request_method(:post, '/review.xml', params)
|
61
|
+
|
62
|
+
Hashie::Mash.new(data["review"])
|
63
|
+
end
|
64
|
+
|
65
|
+
# Edit review for a book
|
66
|
+
#
|
67
|
+
# Params can include :review, :rating, :read_at and :shelf, and :finished
|
68
|
+
#
|
69
|
+
# review: text of the review (optional)
|
70
|
+
# rating: rating (0-5) (optional, default is 0 (no rating))
|
71
|
+
# shelf: Name of shelf to add book to (optional, must exist, see: shelves.list)
|
72
|
+
# read_at: Time object or String in YYYY-MM-DD format (optional)
|
73
|
+
# finished: true to mark finished reading (optional)
|
74
|
+
# shelf: Name of shelf to add book to (optional, must exist, see: shelves.list)
|
75
|
+
def edit_review(review_id, params = {})
|
76
|
+
params = params.merge(v: "2")
|
77
|
+
|
78
|
+
params[:read_at] = params[:read_at].strftime('%Y-%m-%d') if params[:read_at].is_a?(Time)
|
79
|
+
|
80
|
+
params[:'review[review]'] = params.delete(:review) if params[:review]
|
81
|
+
params[:'review[rating]'] = params.delete(:rating) if params[:rating]
|
82
|
+
params[:'review[read_at]'] = params.delete(:read_at) if params[:read_at]
|
83
|
+
|
84
|
+
# Documentation says that you should use HTTP PUT, but API returns
|
85
|
+
# 401 Unauthorized when PUT is used instead of POST
|
86
|
+
data = oauth_request_method(:post, "/review/#{review_id}.xml", params)
|
87
|
+
|
88
|
+
Hashie::Mash.new(data["review"])
|
89
|
+
end
|
34
90
|
end
|
35
91
|
end
|
@@ -1,5 +1,36 @@
|
|
1
1
|
module Goodreads
|
2
2
|
module Shelves
|
3
|
+
# Lists shelves for a user
|
4
|
+
def shelves(user_id, options = {})
|
5
|
+
options = options.merge(user_id: user_id, v: 2)
|
6
|
+
data = request("/shelf/list.xml", options)
|
7
|
+
shelves = data["shelves"]
|
8
|
+
|
9
|
+
shelves = data["shelves"]["user_shelf"].map do |s|
|
10
|
+
Hashie::Mash.new({
|
11
|
+
id: s["id"],
|
12
|
+
name: s["name"],
|
13
|
+
book_count: s["book_count"],
|
14
|
+
exclusive: s["exclusive_flag"],
|
15
|
+
description: s["description"],
|
16
|
+
sort: s["sort"],
|
17
|
+
order: s["order"],
|
18
|
+
per_page: s["per_page"],
|
19
|
+
display_fields: s["display_fields"],
|
20
|
+
featured: s["featured"],
|
21
|
+
recommend_for: s["recommend_for"],
|
22
|
+
sticky: s["sticky"],
|
23
|
+
})
|
24
|
+
end
|
25
|
+
|
26
|
+
Hashie::Mash.new(
|
27
|
+
start: data["shelves"]["start"].to_i,
|
28
|
+
end: data["shelves"]["end"].to_i,
|
29
|
+
total: data["shelves"]["total"].to_i,
|
30
|
+
shelves: shelves
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
3
34
|
# Get books from a user's shelf
|
4
35
|
def shelf(user_id, shelf_name, options = {})
|
5
36
|
options = options.merge(shelf: shelf_name, v: 2)
|
@@ -20,5 +51,42 @@ module Goodreads
|
|
20
51
|
books: books
|
21
52
|
)
|
22
53
|
end
|
54
|
+
|
55
|
+
# Add book to a user's shelf
|
56
|
+
#
|
57
|
+
# Returns the user's review for the book, which includes all its current shelves
|
58
|
+
def add_to_shelf(book_id, shelf_name, options = {})
|
59
|
+
options = options.merge(book_id: book_id, name: shelf_name, v: 2)
|
60
|
+
data = oauth_request_method(:post, "/shelf/add_to_shelf.xml", options)
|
61
|
+
|
62
|
+
# when a book is on a single shelf it is a single hash
|
63
|
+
shelves = data["my_review"]["shelves"]["shelf"]
|
64
|
+
shelves = [shelves] unless shelves.instance_of?(Array)
|
65
|
+
shelves = shelves.map do |s|
|
66
|
+
Hashie::Mash.new({
|
67
|
+
id: s["id"].to_i,
|
68
|
+
name: s["name"],
|
69
|
+
exclusive: s["exclusive"] == "true",
|
70
|
+
sortable: s["sortable"] == "true",
|
71
|
+
})
|
72
|
+
end
|
73
|
+
|
74
|
+
Hashie::Mash.new(
|
75
|
+
id: data["my_review"]["id"].to_i,
|
76
|
+
book_id: data["my_review"]["book_id"].to_i,
|
77
|
+
|
78
|
+
rating: data["my_review"]["rating"].to_i,
|
79
|
+
body: data["my_review"]["body"],
|
80
|
+
body_raw: data["my_review"]["body_raw"],
|
81
|
+
spoiler: data["my_review"]["spoiler_flag"] == "true",
|
82
|
+
|
83
|
+
shelves: shelves,
|
84
|
+
|
85
|
+
read_at: data["my_review"]["read_at"],
|
86
|
+
started_at: data["my_review"]["started_at"],
|
87
|
+
date_added: data["my_review"]["date_added"],
|
88
|
+
updated_at: data["my_review"]["updated_at"],
|
89
|
+
)
|
90
|
+
end
|
23
91
|
end
|
24
92
|
end
|
data/lib/goodreads/request.rb
CHANGED
@@ -9,12 +9,26 @@ module Goodreads
|
|
9
9
|
|
10
10
|
protected
|
11
11
|
|
12
|
-
# Perform an API request
|
12
|
+
# Perform an API request using API key or OAuth token
|
13
13
|
#
|
14
14
|
# path - Request path
|
15
15
|
# params - Parameters hash
|
16
16
|
#
|
17
|
+
# Will make a request with the configured API key (application
|
18
|
+
# authentication) or OAuth token (user authentication) if available.
|
17
19
|
def request(path, params = {})
|
20
|
+
if oauth_configured?
|
21
|
+
oauth_request(path, params)
|
22
|
+
else
|
23
|
+
http_request(path, params)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Perform an API request using API key
|
28
|
+
#
|
29
|
+
# path - Request path
|
30
|
+
# params - Parameters hash
|
31
|
+
def http_request(path, params)
|
18
32
|
token = api_key || Goodreads.configuration[:api_key]
|
19
33
|
|
20
34
|
fail(Goodreads::ConfigurationError, "API key required.") if token.nil?
|
@@ -38,18 +52,35 @@ module Goodreads
|
|
38
52
|
parse(resp)
|
39
53
|
end
|
40
54
|
|
55
|
+
# Perform an OAuth API GET request. Goodreads must have been initialized with a valid OAuth access token.
|
56
|
+
#
|
57
|
+
# path - Request path
|
58
|
+
# params - Parameters hash
|
59
|
+
#
|
60
|
+
def oauth_request(path, params = {})
|
61
|
+
oauth_request_method(:get, path, params)
|
62
|
+
end
|
63
|
+
|
41
64
|
# Perform an OAuth API request. Goodreads must have been initialized with a valid OAuth access token.
|
42
65
|
#
|
66
|
+
# http_method - HTTP verb supported by OAuth gem (one of :get, :post, :delete, etc.)
|
43
67
|
# path - Request path
|
44
68
|
# params - Parameters hash
|
45
69
|
#
|
46
|
-
def
|
70
|
+
def oauth_request_method(http_method, path, params = {})
|
47
71
|
fail "OAuth access token required!" unless @oauth_token
|
48
|
-
|
49
|
-
|
50
|
-
|
72
|
+
|
73
|
+
headers = { "Accept" => "application/xml" }
|
74
|
+
|
75
|
+
resp = if http_method == :get || http_method == :delete
|
76
|
+
if params
|
77
|
+
url_params = params.map { |k, v| "#{k}=#{v}" }.join("&")
|
78
|
+
path = "#{path}?#{url_params}"
|
79
|
+
end
|
80
|
+
@oauth_token.request(http_method, path, headers)
|
81
|
+
else
|
82
|
+
@oauth_token.request(http_method, path, params || {}, headers)
|
51
83
|
end
|
52
|
-
resp = @oauth_token.get(path, "Accept" => "application/xml")
|
53
84
|
|
54
85
|
case resp
|
55
86
|
when Net::HTTPUnauthorized
|
data/lib/goodreads/version.rb
CHANGED
data/spec/authentication_spec.rb
CHANGED
@@ -1,24 +1,37 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe Goodreads::Client do
|
4
4
|
before :each do
|
5
5
|
Goodreads.reset_configuration
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
let(:client) do
|
9
|
+
described_class.new(api_key: api_key)
|
10
|
+
end
|
11
|
+
|
12
|
+
context "API key is missing" do
|
13
|
+
let(:api_key) {}
|
10
14
|
|
11
|
-
|
12
|
-
|
15
|
+
it "throws an error" do
|
16
|
+
expect { client.book_by_isbn("0307463745") }
|
17
|
+
.to raise_error(Goodreads::ConfigurationError, "API key required.")
|
18
|
+
end
|
13
19
|
end
|
14
20
|
|
15
|
-
|
16
|
-
|
21
|
+
context "API key is invalid" do
|
22
|
+
let(:api_key) { "INVALID_KEY" }
|
23
|
+
|
24
|
+
before do
|
25
|
+
stub_request(:get, "https://www.goodreads.com/book/isbn?format=xml&isbn=1&key=INVALID_KEY")
|
26
|
+
.to_return(status: 401)
|
17
27
|
|
18
|
-
|
19
|
-
|
28
|
+
stub_request(:get, "https://www.goodreads.com/book/isbn?format=xml&isbn=2&key=INVALID_KEY")
|
29
|
+
.to_return(status: 403)
|
30
|
+
end
|
20
31
|
|
21
|
-
|
22
|
-
.to raise_error(Goodreads::Unauthorized)
|
32
|
+
it "throws errors" do
|
33
|
+
expect { client.book_by_isbn("1") }.to raise_error(Goodreads::Unauthorized)
|
34
|
+
expect { client.book_by_isbn("2") }.to raise_error(Goodreads::Forbidden)
|
35
|
+
end
|
23
36
|
end
|
24
37
|
end
|
data/spec/client_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
require "oauth"
|
3
3
|
|
4
|
-
describe
|
4
|
+
describe Goodreads::Client do
|
5
5
|
let(:client) { Goodreads::Client.new(api_key: "SECRET_KEY") }
|
6
6
|
before(:each) { Goodreads.reset_configuration }
|
7
7
|
|
@@ -17,6 +17,45 @@ describe "Client" do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
describe "#oauth_configured?" do
|
21
|
+
it "is true when OAuth token provided to constructor" do
|
22
|
+
client = Goodreads::Client.new(oauth_token: "a token")
|
23
|
+
expect(client.oauth_configured?).to be true
|
24
|
+
end
|
25
|
+
|
26
|
+
it "is true when oauth token is not provided to constructor" do
|
27
|
+
client = Goodreads::Client.new(api_key: "SECRET_KEY")
|
28
|
+
expect(client.oauth_configured?).to be false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#request" do
|
33
|
+
context "with oauth token" do
|
34
|
+
it "makes an oauth request" do
|
35
|
+
oauth_token = double
|
36
|
+
response = double
|
37
|
+
|
38
|
+
allow(oauth_token).to receive(:request) { response }
|
39
|
+
allow(response).to receive(:body) { fixture("book.xml") }
|
40
|
+
|
41
|
+
client = Goodreads::Client.new(oauth_token: oauth_token)
|
42
|
+
expect(client.book(123)).to be_a Hash
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "without oauth token" do
|
47
|
+
before do
|
48
|
+
allow(client).to receive(:http_request) {
|
49
|
+
Hash.from_xml(fixture("book.xml"))["GoodreadsResponse"]
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
it "makes a request" do
|
54
|
+
expect(client.book(123)).to be_a Hash
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
20
59
|
describe "#book_by_isbn" do
|
21
60
|
before { stub_with_key_get("/book/isbn", { isbn: "0307463745" }, "book.xml") }
|
22
61
|
|
@@ -154,6 +193,26 @@ describe "Client" do
|
|
154
193
|
end
|
155
194
|
end
|
156
195
|
|
196
|
+
describe "#user_review" do
|
197
|
+
let(:consumer) { OAuth::Consumer.new("API_KEY", "SECRET_KEY", site: "https://www.goodreads.com") }
|
198
|
+
let(:token) { OAuth::AccessToken.new(consumer, "ACCESS_TOKEN", "ACCESS_SECRET") }
|
199
|
+
|
200
|
+
it "returns a user's existing review" do
|
201
|
+
stub_request(:get, "https://www.goodreads.com/review/show_by_user_and_book.xml?book_id=50&user_id=1&v=2")
|
202
|
+
.to_return(status: 200, body: fixture("review_show_by_user_and_book.xml"))
|
203
|
+
|
204
|
+
client = Goodreads::Client.new(api_key: "SECRET_KEY", oauth_token: token)
|
205
|
+
review = client.user_review(1, 50)
|
206
|
+
|
207
|
+
expect(review.id).to eq("21")
|
208
|
+
expect(review.book.id).to eq(50)
|
209
|
+
|
210
|
+
expect(review.rating).to eq("5")
|
211
|
+
expect(review.body.strip).to eq("")
|
212
|
+
expect(review.date_added).to eq("Tue Aug 29 11:20:01 -0700 2006")
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
157
216
|
describe "#author" do
|
158
217
|
before { stub_with_key_get("/author/show", { id: "18541" }, "author.xml") }
|
159
218
|
|
@@ -287,6 +346,131 @@ describe "Client" do
|
|
287
346
|
end
|
288
347
|
end
|
289
348
|
|
349
|
+
describe "#add_to_shelf" do
|
350
|
+
let(:consumer) { OAuth::Consumer.new("API_KEY", "SECRET_KEY", site: "https://www.goodreads.com") }
|
351
|
+
let(:token) { OAuth::AccessToken.new(consumer, "ACCESS_TOKEN", "ACCESS_SECRET") }
|
352
|
+
|
353
|
+
it "adds a book to a user's shelf" do
|
354
|
+
stub_request(:post, "https://www.goodreads.com/shelf/add_to_shelf.xml")
|
355
|
+
.with(:body => {"book_id"=>"456", "name"=>"read", "v"=>"2"})
|
356
|
+
.to_return(status: 201, body: fixture("shelf_add_to_shelf.xml"))
|
357
|
+
|
358
|
+
client = Goodreads::Client.new(api_key: "SECRET_KEY", oauth_token: token)
|
359
|
+
review = client.add_to_shelf(456, "read")
|
360
|
+
|
361
|
+
expect(review.id).to eq(2416981504)
|
362
|
+
expect(review.book_id).to eq(456)
|
363
|
+
|
364
|
+
expect(review.rating).to eq(0)
|
365
|
+
expect(review.body).to be nil
|
366
|
+
expect(review.body_raw).to be nil
|
367
|
+
expect(review.spoiler).to be false
|
368
|
+
|
369
|
+
expect(review.shelves.size).to eq(1)
|
370
|
+
expect(review.shelves.first.name).to eq("read")
|
371
|
+
expect(review.shelves.first.id).to eq(269274694)
|
372
|
+
expect(review.shelves.first.exclusive).to be true
|
373
|
+
expect(review.shelves.first.sortable).to be false
|
374
|
+
|
375
|
+
|
376
|
+
expect(review.read_at).to be nil
|
377
|
+
expect(review.started_at).to be nil
|
378
|
+
expect(review.date_added).to eq("Thu Jun 07 19:58:19 -0700 2018")
|
379
|
+
expect(review.updated_at).to eq("Thu Jun 07 19:58:53 -0700 2018")
|
380
|
+
|
381
|
+
expect(review.body).to be nil
|
382
|
+
expect(review.body_raw).to be nil
|
383
|
+
expect(review.spoiler).to be false
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
describe "#create_review" do
|
388
|
+
let(:consumer) { OAuth::Consumer.new("API_KEY", "SECRET_KEY", site: "https://www.goodreads.com") }
|
389
|
+
let(:token) { OAuth::AccessToken.new(consumer, "ACCESS_TOKEN", "ACCESS_SECRET") }
|
390
|
+
|
391
|
+
it "creates a new review for a book" do
|
392
|
+
stub_request(:post, "https://www.goodreads.com/review.xml")
|
393
|
+
.with(:body => {
|
394
|
+
"book_id"=>"456",
|
395
|
+
"review" => {
|
396
|
+
"rating" => "3",
|
397
|
+
"review" => "Good book.",
|
398
|
+
"read_at" => "2018-01-02",
|
399
|
+
},
|
400
|
+
"shelf" => "read",
|
401
|
+
"v"=>"2",
|
402
|
+
})
|
403
|
+
.to_return(status: 201, body: fixture("review_create.xml"))
|
404
|
+
|
405
|
+
client = Goodreads::Client.new(api_key: "SECRET_KEY", oauth_token: token)
|
406
|
+
review = client.create_review(456, {
|
407
|
+
:review => "Good book.",
|
408
|
+
:rating => 3,
|
409
|
+
:read_at => Time.parse('2018-01-02'),
|
410
|
+
:shelf => "read",
|
411
|
+
})
|
412
|
+
|
413
|
+
expect(review.id).to eq("67890")
|
414
|
+
expect(review.book.id).to eq(456)
|
415
|
+
expect(review.rating).to eq("3")
|
416
|
+
expect(review.body).to eq("Good book.")
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
describe "#edit_review" do
|
421
|
+
let(:consumer) { OAuth::Consumer.new("API_KEY", "SECRET_KEY", site: "https://www.goodreads.com") }
|
422
|
+
let(:token) { OAuth::AccessToken.new(consumer, "ACCESS_TOKEN", "ACCESS_SECRET") }
|
423
|
+
|
424
|
+
it "creates a new review for a book" do
|
425
|
+
stub_request(:post, "https://www.goodreads.com/review/67890.xml")
|
426
|
+
.with(:body => {
|
427
|
+
"finished" => "true",
|
428
|
+
"review" => {
|
429
|
+
"rating" => "5",
|
430
|
+
"review" => "Fantastic book.",
|
431
|
+
"read_at" => "2018-04-15",
|
432
|
+
},
|
433
|
+
"shelf" => "read",
|
434
|
+
"v"=>"2",
|
435
|
+
})
|
436
|
+
.to_return(status: 201, body: fixture("review_update.xml"))
|
437
|
+
|
438
|
+
client = Goodreads::Client.new(api_key: "SECRET_KEY", oauth_token: token)
|
439
|
+
review = client.edit_review(67890, {
|
440
|
+
:finished => true,
|
441
|
+
:review => "Fantastic book.",
|
442
|
+
:rating => 5,
|
443
|
+
:read_at => Time.parse('2018-04-15'),
|
444
|
+
:shelf => "read",
|
445
|
+
})
|
446
|
+
|
447
|
+
expect(review.id).to eq("67890")
|
448
|
+
expect(review.book.id).to eq(456)
|
449
|
+
expect(review.rating).to eq("5")
|
450
|
+
expect(review.body).to eq("Fantastic book.")
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
describe "#shelves" do
|
455
|
+
it "returns list of user's shelves" do
|
456
|
+
stub_with_key_get("/shelf/list.xml", { user_id: 123, v: "2" }, "shelf_list.xml")
|
457
|
+
|
458
|
+
response = client.shelves(123)
|
459
|
+
|
460
|
+
expect(response).to respond_to(:start)
|
461
|
+
expect(response).to respond_to(:end)
|
462
|
+
expect(response).to respond_to(:total)
|
463
|
+
expect(response).to respond_to(:shelves)
|
464
|
+
|
465
|
+
expect(response.start).to eq(1)
|
466
|
+
expect(response.end).to eq(3)
|
467
|
+
expect(response.total).to eq(3)
|
468
|
+
expect(response.shelves.length).to eq(3)
|
469
|
+
expect(response.shelves.first.id).to eq(9049904)
|
470
|
+
expect(response.shelves.first.name).to eq("read")
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
290
474
|
describe "#user_id" do
|
291
475
|
let(:consumer) { OAuth::Consumer.new("API_KEY", "SECRET_KEY", site: "https://www.goodreads.com") }
|
292
476
|
let(:token) { OAuth::AccessToken.new(consumer, "ACCESS_TOKEN", "ACCESS_SECRET") }
|
@@ -0,0 +1,102 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<GoodreadsResponse>
|
3
|
+
<Request>
|
4
|
+
<authentication>true</authentication>
|
5
|
+
<key><![CDATA[SECRET_KEY]]></key>
|
6
|
+
<method><![CDATA[review_create]]></method>
|
7
|
+
</Request>
|
8
|
+
|
9
|
+
<review>
|
10
|
+
<id>67890</id>
|
11
|
+
|
12
|
+
<user>
|
13
|
+
<id>123456</id>
|
14
|
+
<uri>kca://profile:goodreads/A25C3Y1SBGK9NK</uri>
|
15
|
+
<name>Test</name>
|
16
|
+
<display_name>Test User</display_name>
|
17
|
+
|
18
|
+
<location>Lafayette, CA</location>
|
19
|
+
|
20
|
+
<link><![CDATA[https://www.goodreads.com/user/show/123456-test-user]]></link>
|
21
|
+
|
22
|
+
<image_url><![CDATA[https://s.gr-assets.com/assets/nophoto/user/u_111x148-9394ebedbb3c6c218f64be9549657029.png]]></image_url>
|
23
|
+
<small_image_url><![CDATA[https://s.gr-assets.com/assets/nophoto/user/u_50x66-632230dc9882b4352d753eedf9396530.png]]></small_image_url>
|
24
|
+
<has_image>false</has_image>
|
25
|
+
|
26
|
+
</user>
|
27
|
+
|
28
|
+
<book>
|
29
|
+
<id type="integer">456</id>
|
30
|
+
<isbn>0195138570</isbn>
|
31
|
+
<isbn13>9780195138573</isbn13>
|
32
|
+
<text_reviews_count type="integer">11</text_reviews_count>
|
33
|
+
<uri>kca://book/amzn1.gr.book.v1.oHwPZrciugo6gPSINsfCaw</uri>
|
34
|
+
<title>Mindware: An Introduction to the Philosophy of Cognitive Science</title>
|
35
|
+
<title_without_series>Mindware: An Introduction to the Philosophy of Cognitive Science</title_without_series>
|
36
|
+
<image_url>https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png</image_url>
|
37
|
+
<small_image_url>https://s.gr-assets.com/assets/nophoto/book/50x75-a91bf249278a81aabab721ef782c4a74.png</small_image_url>
|
38
|
+
<large_image_url/>
|
39
|
+
<link>https://www.goodreads.com/book/show/456.Mindware</link>
|
40
|
+
<num_pages>224</num_pages>
|
41
|
+
<format>Paperback</format>
|
42
|
+
<edition_information>1st edition</edition_information>
|
43
|
+
<publisher>Oxford University Press, USA</publisher>
|
44
|
+
<publication_day>21</publication_day>
|
45
|
+
<publication_year>2000</publication_year>
|
46
|
+
<publication_month>12</publication_month>
|
47
|
+
<average_rating>3.78</average_rating>
|
48
|
+
<ratings_count>210</ratings_count>
|
49
|
+
<description><p><i>Mindware</i> is an introductory text with a difference. In eight short chapters it tells a story and invites the reader to join in some up-to-the-minute conceptual discussion of the key issues, problems, and opportunities in cognitive science. The story is about the search for a cognitive scientific understanding of mind. It is presented as a no-holds-barred journey from early work in Artificial Intelligence, through connectionist (artificial neural network) counter-visions, and onto neuroscience artificial life, dynamics and robotics. The journey ends with some wide-ranging and provacative speculation about the role of technology and the changing nature of the human mind itself.<br />Each chapter is organized as an initial sketch of a research program or theme, followed by a substantial discussion section in which specific problems and issues (both familiear and cutting-edge) are raised and pursued. Discussion topics include mental causation, the hardware/software distinction, the relations between life and mind, the nature of perception, cognition and action, and the continuity (or otherwise) of high-level human intelligence with other forms of adaptive response. Classic topics are treated alongside the newer ones in an integrated treatment of the various discussions. The sketches and discussions are accompanied by numerous figures and boxed sections, and followed by suggestions for futher reading.</p></description>
|
50
|
+
<authors>
|
51
|
+
<author>
|
52
|
+
<id>3445871</id>
|
53
|
+
<name>Andy Clark</name>
|
54
|
+
<role></role>
|
55
|
+
<image_url nophoto='false'>
|
56
|
+
<![CDATA[https://images.gr-assets.com/authors/1269856267p5/3445871.jpg]]>
|
57
|
+
</image_url>
|
58
|
+
<small_image_url nophoto='false'>
|
59
|
+
<![CDATA[https://images.gr-assets.com/authors/1269856267p2/3445871.jpg]]>
|
60
|
+
</small_image_url>
|
61
|
+
<link><![CDATA[https://www.goodreads.com/author/show/3445871.Andy_Clark]]></link>
|
62
|
+
<average_rating>3.89</average_rating>
|
63
|
+
<ratings_count>992</ratings_count>
|
64
|
+
<text_reviews_count>74</text_reviews_count>
|
65
|
+
</author>
|
66
|
+
</authors>
|
67
|
+
<published>2000</published>
|
68
|
+
<work> <id>282613</id>
|
69
|
+
<uri>kca://work/amzn1.gr.work.v1.xCZQesiWRuaIVPV6wsdFGA</uri>
|
70
|
+
</work></book>
|
71
|
+
|
72
|
+
|
73
|
+
<rating>3</rating>
|
74
|
+
<votes>0</votes>
|
75
|
+
<spoiler_flag>false</spoiler_flag>
|
76
|
+
<spoilers_state>none</spoilers_state>
|
77
|
+
|
78
|
+
|
79
|
+
<shelves>
|
80
|
+
<shelf name="read" exclusive="true" id="269274694" review_shelf_id= ""/>
|
81
|
+
|
82
|
+
</shelves>
|
83
|
+
|
84
|
+
<recommended_for></recommended_for>
|
85
|
+
<recommended_by></recommended_by>
|
86
|
+
<started_at></started_at>
|
87
|
+
<read_at></read_at>
|
88
|
+
<date_added>Wed Jun 13 20:52:06 -0700 2018</date_added>
|
89
|
+
<date_updated>Wed Jun 13 20:52:07 -0700 2018</date_updated>
|
90
|
+
<read_count>1</read_count>
|
91
|
+
<body>Good book.</body>
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
<comments_count>0</comments_count>
|
96
|
+
<url><![CDATA[https://www.goodreads.com/review/show/67890]]></url>
|
97
|
+
<link><![CDATA[https://www.goodreads.com/review/show/67890]]></link>
|
98
|
+
<owned>0</owned>
|
99
|
+
</review>
|
100
|
+
|
101
|
+
|
102
|
+
</GoodreadsResponse>
|
@@ -0,0 +1,144 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<GoodreadsResponse>
|
3
|
+
<Request>
|
4
|
+
<authentication>true</authentication>
|
5
|
+
<key><![CDATA[SECRET_KEY]]></key>
|
6
|
+
<method><![CDATA[review_show_by_user_and_book]]></method>
|
7
|
+
</Request>
|
8
|
+
<review>
|
9
|
+
<id>21</id>
|
10
|
+
|
11
|
+
<user>
|
12
|
+
<id>1</id>
|
13
|
+
<uri>kca://profile:goodreads/A2CSQET51X1KEY</uri>
|
14
|
+
<name>Otis</name>
|
15
|
+
<display_name>Otis Chandler</display_name>
|
16
|
+
|
17
|
+
<location>San Francisco, CA</location>
|
18
|
+
|
19
|
+
<link><![CDATA[https://www.goodreads.com/user/show/1-otis-chandler]]></link>
|
20
|
+
|
21
|
+
<image_url><![CDATA[https://images.gr-assets.com/users/1506617226p3/1.jpg]]></image_url>
|
22
|
+
<small_image_url><![CDATA[https://images.gr-assets.com/users/1506617226p2/1.jpg]]></small_image_url>
|
23
|
+
<has_image>true</has_image>
|
24
|
+
|
25
|
+
</user>
|
26
|
+
|
27
|
+
<book>
|
28
|
+
<id type="integer">50</id>
|
29
|
+
<isbn>0689840926</isbn>
|
30
|
+
<isbn13>9780689840920</isbn13>
|
31
|
+
<text_reviews_count type="integer">10396</text_reviews_count>
|
32
|
+
<uri>kca://book/amzn1.gr.book.v1.RXVB3nJhipnhI-zLlVeRTg</uri>
|
33
|
+
<title>Hatchet</title>
|
34
|
+
<title_without_series>Hatchet</title_without_series>
|
35
|
+
<image_url>https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png</image_url>
|
36
|
+
<small_image_url>https://s.gr-assets.com/assets/nophoto/book/50x75-a91bf249278a81aabab721ef782c4a74.png</small_image_url>
|
37
|
+
<large_image_url/>
|
38
|
+
<link>https://www.goodreads.com/book/show/50.Hatchet</link>
|
39
|
+
<num_pages>208</num_pages>
|
40
|
+
<format>Hardcover</format>
|
41
|
+
<edition_information/>
|
42
|
+
<publisher>Atheneum Books for Young Readers: Richard Jackson Books</publisher>
|
43
|
+
<publication_day>1</publication_day>
|
44
|
+
<publication_year>2000</publication_year>
|
45
|
+
<publication_month>4</publication_month>
|
46
|
+
<average_rating>3.69</average_rating>
|
47
|
+
<ratings_count>250763</ratings_count>
|
48
|
+
<description>Brian is on his way to Canada to visit his estranged father when the pilot of his small prop plane suffers a heart attack. Brian is forced to crash-land the plane in a lake--and finds himself stranded in the remote Canadian wilderness with only his clothing and the hatchet his mother gave him as a present before his departure. <br /><br />Brian had been distraught over his parents' impending divorce and the secret he carries about his mother, but now he is truly desolate and alone. Exhausted, terrified, and hungry, Brian struggles to find food and make a shelter for himself. He has no special knowledge of the woods, and he must find a new kind of awareness and patience as he meets each day's challenges. Is the water safe to drink? Are the berries he finds poisonous? <br /><br />Slowly, Brian learns to turn adversity to his advantage--an invading porcupine unexpectedly shows him how to make fire, a devastating tornado shows him how to retrieve supplies from the submerged airplane. Most of all, Brian leaves behind the self-pity he has felt about his predicament as he summons the courage to stay alive. <br /><br />A story of survival and of transformation, this riveting book has sparked many a reader's interest in venturing into the wild.</description>
|
49
|
+
<authors>
|
50
|
+
<author>
|
51
|
+
<id>18</id>
|
52
|
+
<name>Gary Paulsen</name>
|
53
|
+
<role></role>
|
54
|
+
<image_url nophoto='false'>
|
55
|
+
<![CDATA[https://images.gr-assets.com/authors/1309159225p5/18.jpg]]>
|
56
|
+
</image_url>
|
57
|
+
<small_image_url nophoto='false'>
|
58
|
+
<![CDATA[https://images.gr-assets.com/authors/1309159225p2/18.jpg]]>
|
59
|
+
</small_image_url>
|
60
|
+
<link><![CDATA[https://www.goodreads.com/author/show/18.Gary_Paulsen]]></link>
|
61
|
+
<average_rating>3.76</average_rating>
|
62
|
+
<ratings_count>399462</ratings_count>
|
63
|
+
<text_reviews_count>28012</text_reviews_count>
|
64
|
+
</author>
|
65
|
+
</authors>
|
66
|
+
<published>2000</published>
|
67
|
+
<work> <id>1158125</id>
|
68
|
+
<uri>kca://work/amzn1.gr.work.v1.r_sm_y7tG-b00YGE5HqhQQ</uri>
|
69
|
+
</work></book>
|
70
|
+
|
71
|
+
|
72
|
+
<read_statuses>
|
73
|
+
<read_status>
|
74
|
+
<id type="integer">1610038200</id>
|
75
|
+
<old_status></old_status>
|
76
|
+
<status>read</status>
|
77
|
+
<updated_at type="datetime">Fri Dec 09 22:55:21 -0800 2016</updated_at>
|
78
|
+
<ratings_count>0</ratings_count>
|
79
|
+
<comments_count>0</comments_count>
|
80
|
+
</read_status>
|
81
|
+
</read_statuses>
|
82
|
+
<rating>5</rating>
|
83
|
+
<votes>1</votes>
|
84
|
+
<spoiler_flag>false</spoiler_flag>
|
85
|
+
<spoilers_state>none</spoilers_state>
|
86
|
+
|
87
|
+
|
88
|
+
<shelves>
|
89
|
+
<shelf name="read" exclusive="true" id="5625761" review_shelf_id= ""/>
|
90
|
+
|
91
|
+
<shelf exclusive='false' id='343477' name='childrensbooks' review_shelf_id='175' sortable='false'></shelf>
|
92
|
+
|
93
|
+
<shelf exclusive='false' id='348056' name='fiction' review_shelf_id='687' sortable='false'></shelf>
|
94
|
+
|
95
|
+
<shelf exclusive='false' id='348035' name='fiction' review_shelf_id='209' sortable='false'></shelf>
|
96
|
+
|
97
|
+
</shelves>
|
98
|
+
|
99
|
+
<recommended_for></recommended_for>
|
100
|
+
<recommended_by></recommended_by>
|
101
|
+
<started_at></started_at>
|
102
|
+
<read_at></read_at>
|
103
|
+
<date_added>Tue Aug 29 11:20:01 -0700 2006</date_added>
|
104
|
+
<date_updated>Wed Mar 22 11:44:07 -0700 2017</date_updated>
|
105
|
+
<read_count>1</read_count>
|
106
|
+
<body>
|
107
|
+
</body>
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
<comments_count>1</comments_count>
|
112
|
+
<comments start="1" end="1" total="1">
|
113
|
+
<comment>
|
114
|
+
<id>161860175</id>
|
115
|
+
<body><![CDATA[love this book i read it in sixth grade and we had journals about it]]></body>
|
116
|
+
|
117
|
+
<user>
|
118
|
+
<id>64170165</id>
|
119
|
+
<uri>kca://profile:goodreads/A2PCDUCFEEK4OB</uri>
|
120
|
+
<name>Alise</name>
|
121
|
+
<display_name>Alise</display_name>
|
122
|
+
|
123
|
+
<location>The United States</location>
|
124
|
+
|
125
|
+
<link><![CDATA[https://www.goodreads.com/user/show/64170165-alise]]></link>
|
126
|
+
|
127
|
+
<image_url><![CDATA[https://s.gr-assets.com/assets/nophoto/user/u_111x148-9394ebedbb3c6c218f64be9549657029.png]]></image_url>
|
128
|
+
<small_image_url><![CDATA[https://s.gr-assets.com/assets/nophoto/user/u_50x66-632230dc9882b4352d753eedf9396530.png]]></small_image_url>
|
129
|
+
<has_image>false</has_image>
|
130
|
+
|
131
|
+
</user>
|
132
|
+
|
133
|
+
<created_at>Sun Jan 22 22:49:10 -0800 2017</created_at>
|
134
|
+
<updated_at>Sun Jan 22 22:49:10 -0800 2017</updated_at>
|
135
|
+
</comment>
|
136
|
+
|
137
|
+
</comments>
|
138
|
+
<url><![CDATA[https://www.goodreads.com/review/show/21]]></url>
|
139
|
+
<link><![CDATA[https://www.goodreads.com/review/show/21]]></link>
|
140
|
+
<owned>0</owned>
|
141
|
+
</review>
|
142
|
+
|
143
|
+
|
144
|
+
</GoodreadsResponse>
|
@@ -0,0 +1,104 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<GoodreadsResponse>
|
3
|
+
<Request>
|
4
|
+
<authentication>true</authentication>
|
5
|
+
<key><![CDATA[SECRET_KEY]]></key>
|
6
|
+
<method><![CDATA[review_update_xml]]></method>
|
7
|
+
</Request>
|
8
|
+
<review>
|
9
|
+
<id>67890</id>
|
10
|
+
|
11
|
+
<user>
|
12
|
+
<id>123456</id>
|
13
|
+
<uri>kca://profile:goodreads/A25C3Y1SBGK9NK</uri>
|
14
|
+
<name>Test</name>
|
15
|
+
<display_name>Test User</display_name>
|
16
|
+
|
17
|
+
<location>Lafayette, CA</location>
|
18
|
+
|
19
|
+
<link><![CDATA[https://www.goodreads.com/user/show/123456-test-user]]></link>
|
20
|
+
|
21
|
+
<image_url><![CDATA[https://s.gr-assets.com/assets/nophoto/user/u_111x148-9394ebedbb3c6c218f64be9549657029.png]]></image_url>
|
22
|
+
<small_image_url><![CDATA[https://s.gr-assets.com/assets/nophoto/user/u_50x66-632230dc9882b4352d753eedf9396530.png]]></small_image_url>
|
23
|
+
<has_image>false</has_image>
|
24
|
+
|
25
|
+
</user>
|
26
|
+
|
27
|
+
<book>
|
28
|
+
<id type="integer">456</id>
|
29
|
+
<isbn>0195138570</isbn>
|
30
|
+
<isbn13>9780195138573</isbn13>
|
31
|
+
<text_reviews_count type="integer">11</text_reviews_count>
|
32
|
+
<uri>kca://book/amzn1.gr.book.v1.oHwPZrciugo6gPSINsfCaw</uri>
|
33
|
+
<title>Mindware: An Introduction to the Philosophy of Cognitive Science</title>
|
34
|
+
<title_without_series>Mindware: An Introduction to the Philosophy of Cognitive Science</title_without_series>
|
35
|
+
<image_url>https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png</image_url>
|
36
|
+
<small_image_url>https://s.gr-assets.com/assets/nophoto/book/50x75-a91bf249278a81aabab721ef782c4a74.png</small_image_url>
|
37
|
+
<large_image_url/>
|
38
|
+
<link>https://www.goodreads.com/book/show/456.Mindware</link>
|
39
|
+
<num_pages>224</num_pages>
|
40
|
+
<format>Paperback</format>
|
41
|
+
<edition_information>1st edition</edition_information>
|
42
|
+
<publisher>Oxford University Press, USA</publisher>
|
43
|
+
<publication_day>21</publication_day>
|
44
|
+
<publication_year>2000</publication_year>
|
45
|
+
<publication_month>12</publication_month>
|
46
|
+
<average_rating>3.78</average_rating>
|
47
|
+
<ratings_count>210</ratings_count>
|
48
|
+
<description><p><i>Mindware</i> is an introductory text with a difference. In eight short chapters it tells a story and invites the reader to join in some up-to-the-minute conceptual discussion of the key issues, problems, and opportunities in cognitive science. The story is about the search for a cognitive scientific understanding of mind. It is presented as a no-holds-barred journey from early work in Artificial Intelligence, through connectionist (artificial neural network) counter-visions, and onto neuroscience artificial life, dynamics and robotics. The journey ends with some wide-ranging and provacative speculation about the role of technology and the changing nature of the human mind itself.<br />Each chapter is organized as an initial sketch of a research program or theme, followed by a substantial discussion section in which specific problems and issues (both familiear and cutting-edge) are raised and pursued. Discussion topics include mental causation, the hardware/software distinction, the relations between life and mind, the nature of perception, cognition and action, and the continuity (or otherwise) of high-level human intelligence with other forms of adaptive response. Classic topics are treated alongside the newer ones in an integrated treatment of the various discussions. The sketches and discussions are accompanied by numerous figures and boxed sections, and followed by suggestions for futher reading.</p></description>
|
49
|
+
<authors>
|
50
|
+
<author>
|
51
|
+
<id>3445871</id>
|
52
|
+
<name>Andy Clark</name>
|
53
|
+
<role></role>
|
54
|
+
<image_url nophoto='false'>
|
55
|
+
<![CDATA[https://images.gr-assets.com/authors/1269856267p5/3445871.jpg]]>
|
56
|
+
</image_url>
|
57
|
+
<small_image_url nophoto='false'>
|
58
|
+
<![CDATA[https://images.gr-assets.com/authors/1269856267p2/3445871.jpg]]>
|
59
|
+
</small_image_url>
|
60
|
+
<link><![CDATA[https://www.goodreads.com/author/show/3445871.Andy_Clark]]></link>
|
61
|
+
<average_rating>3.89</average_rating>
|
62
|
+
<ratings_count>992</ratings_count>
|
63
|
+
<text_reviews_count>74</text_reviews_count>
|
64
|
+
</author>
|
65
|
+
</authors>
|
66
|
+
<published>2000</published>
|
67
|
+
<work> <id>282613</id>
|
68
|
+
<uri>kca://work/amzn1.gr.work.v1.xCZQesiWRuaIVPV6wsdFGA</uri>
|
69
|
+
</work></book>
|
70
|
+
|
71
|
+
|
72
|
+
<rating>5</rating>
|
73
|
+
<votes>0</votes>
|
74
|
+
<spoiler_flag>false</spoiler_flag>
|
75
|
+
<spoilers_state>none</spoilers_state>
|
76
|
+
|
77
|
+
|
78
|
+
<shelves>
|
79
|
+
<shelf name="read" exclusive="true" id="269274694" review_shelf_id= ""/>
|
80
|
+
|
81
|
+
</shelves>
|
82
|
+
|
83
|
+
<recommended_for></recommended_for>
|
84
|
+
<recommended_by></recommended_by>
|
85
|
+
<started_at></started_at>
|
86
|
+
<read_at>Fri Aug 20 00:00:00 -0700 2004</read_at>
|
87
|
+
<date_added>Wed Jun 13 20:52:06 -0700 2018</date_added>
|
88
|
+
<date_updated>Wed Jun 13 20:52:08 -0700 2018</date_updated>
|
89
|
+
<read_count>1</read_count>
|
90
|
+
<body>Fantastic book.</body>
|
91
|
+
<body_raw>
|
92
|
+
|
93
|
+
</body_raw>
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
<comments_count>0</comments_count>
|
98
|
+
<url><![CDATA[https://www.goodreads.com/review/show/67890]]></url>
|
99
|
+
<link><![CDATA[https://www.goodreads.com/review/show/67890]]></link>
|
100
|
+
<owned>0</owned>
|
101
|
+
</review>
|
102
|
+
|
103
|
+
|
104
|
+
</GoodreadsResponse>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<GoodreadsResponse>
|
2
|
+
<Request>
|
3
|
+
<authentication>true</authentication>
|
4
|
+
<key><![CDATA[SECRET_KEY]]></key>
|
5
|
+
<method><![CDATA[shelf_add_to_shelf]]></method>
|
6
|
+
</Request>
|
7
|
+
<my_review>
|
8
|
+
<id>2416981504</id>
|
9
|
+
<book_id>456</book_id>
|
10
|
+
<rating>0</rating>
|
11
|
+
<updated_at>Thu Jun 07 19:58:53 -0700 2018</updated_at>
|
12
|
+
|
13
|
+
<shelves>
|
14
|
+
<shelf name="read" exclusive="true" id="269274694" review_shelf_id= ""/>
|
15
|
+
</shelves>
|
16
|
+
|
17
|
+
<body></body>
|
18
|
+
<body_raw></body_raw>
|
19
|
+
<spoiler_flag>false</spoiler_flag>
|
20
|
+
<started_at></started_at>
|
21
|
+
<read_at></read_at>
|
22
|
+
<date_added>Thu Jun 07 19:58:19 -0700 2018</date_added>
|
23
|
+
</my_review>
|
24
|
+
</GoodreadsResponse>
|
@@ -0,0 +1,51 @@
|
|
1
|
+
<GoodreadsResponse>
|
2
|
+
<Request>
|
3
|
+
<authentication>true</authentication>
|
4
|
+
<key><![CDATA[SECRET_KEY]]></key>
|
5
|
+
<method><![CDATA[ shelf_list ]]></method>
|
6
|
+
</Request>
|
7
|
+
<shelves start="1" end="3" total="3">
|
8
|
+
<user_shelf>
|
9
|
+
<id type="integer">9049904</id>
|
10
|
+
<name>read</name>
|
11
|
+
<book_count type="integer">0</book_count>
|
12
|
+
<exclusive_flag type="boolean">true</exclusive_flag>
|
13
|
+
<description nil="true"/>
|
14
|
+
<sort nil="true"/>
|
15
|
+
<order nil="true"/>
|
16
|
+
<per_page type="integer" nil="true"/>
|
17
|
+
<display_fields/>
|
18
|
+
<featured type="boolean">true</featured>
|
19
|
+
<recommend_for type="boolean">true</recommend_for>
|
20
|
+
<sticky type="boolean" nil="true"/>
|
21
|
+
</user_shelf>
|
22
|
+
<user_shelf>
|
23
|
+
<id type="integer">3701</id>
|
24
|
+
<name>currently-reading</name>
|
25
|
+
<book_count type="integer">0</book_count>
|
26
|
+
<exclusive_flag type="boolean">true</exclusive_flag>
|
27
|
+
<description nil="true"/>
|
28
|
+
<sort nil="true"/>
|
29
|
+
<order nil="true"/>
|
30
|
+
<per_page type="integer" nil="true"/>
|
31
|
+
<display_fields/>
|
32
|
+
<featured type="boolean">false</featured>
|
33
|
+
<recommend_for type="boolean">true</recommend_for>
|
34
|
+
<sticky type="boolean" nil="true"/>
|
35
|
+
</user_shelf>
|
36
|
+
<user_shelf>
|
37
|
+
<id type="integer">3700</id>
|
38
|
+
<name>to-read</name>
|
39
|
+
<book_count type="integer">0</book_count>
|
40
|
+
<exclusive_flag type="boolean">true</exclusive_flag>
|
41
|
+
<description nil="true"/>
|
42
|
+
<sort nil="true"/>
|
43
|
+
<order>a</order>
|
44
|
+
<per_page type="integer" nil="true"/>
|
45
|
+
<display_fields/>
|
46
|
+
<featured type="boolean">false</featured>
|
47
|
+
<recommend_for type="boolean">true</recommend_for>
|
48
|
+
<sticky type="boolean" nil="true"/>
|
49
|
+
</user_shelf>
|
50
|
+
</shelves>
|
51
|
+
</GoodreadsResponse>
|
data/spec/goodreads_spec.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: goodreads
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Sosedoff
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: webmock
|
@@ -192,9 +192,14 @@ files:
|
|
192
192
|
- spec/fixtures/oauth_response.xml
|
193
193
|
- spec/fixtures/recent_reviews.xml
|
194
194
|
- spec/fixtures/review.xml
|
195
|
+
- spec/fixtures/review_create.xml
|
196
|
+
- spec/fixtures/review_show_by_user_and_book.xml
|
197
|
+
- spec/fixtures/review_update.xml
|
195
198
|
- spec/fixtures/reviews.xml
|
196
199
|
- spec/fixtures/reviews_empty.xml
|
197
200
|
- spec/fixtures/search_books_by_name.xml
|
201
|
+
- spec/fixtures/shelf_add_to_shelf.xml
|
202
|
+
- spec/fixtures/shelf_list.xml
|
198
203
|
- spec/fixtures/to-read-p2.xml
|
199
204
|
- spec/fixtures/to-read.xml
|
200
205
|
- spec/fixtures/user.xml
|
@@ -220,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
220
225
|
version: '0'
|
221
226
|
requirements: []
|
222
227
|
rubyforge_project:
|
223
|
-
rubygems_version: 2.
|
228
|
+
rubygems_version: 2.7.7
|
224
229
|
signing_key:
|
225
230
|
specification_version: 4
|
226
231
|
summary: Goodreads API wrapper
|
@@ -237,9 +242,14 @@ test_files:
|
|
237
242
|
- spec/fixtures/oauth_response.xml
|
238
243
|
- spec/fixtures/recent_reviews.xml
|
239
244
|
- spec/fixtures/review.xml
|
245
|
+
- spec/fixtures/review_create.xml
|
246
|
+
- spec/fixtures/review_show_by_user_and_book.xml
|
247
|
+
- spec/fixtures/review_update.xml
|
240
248
|
- spec/fixtures/reviews.xml
|
241
249
|
- spec/fixtures/reviews_empty.xml
|
242
250
|
- spec/fixtures/search_books_by_name.xml
|
251
|
+
- spec/fixtures/shelf_add_to_shelf.xml
|
252
|
+
- spec/fixtures/shelf_list.xml
|
243
253
|
- spec/fixtures/to-read-p2.xml
|
244
254
|
- spec/fixtures/to-read.xml
|
245
255
|
- spec/fixtures/user.xml
|