readmill 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 48bff31a9f54c336b4b7acb0d74505005c48c306
4
- data.tar.gz: 6806f9b999353fc3303d9a250e22d69f0c95c584
3
+ metadata.gz: f35c2ae9772b9f8842eb4df1bcee5bd376c30638
4
+ data.tar.gz: aed7f792b72a72241fc10a8fd8c46c08bcb10512
5
5
  SHA512:
6
- metadata.gz: 3616e009ac80142054347a28a5f7c77480e69347a2c676a617ce28e3bac767c7ef59941f8d87dfda843ed7cbb4e52b8b162b638ed58ee65acb1a7c0efcd1e627
7
- data.tar.gz: 20b98b919e34608fb4580472773fb516d8dfcb8ede22e63f90f21b6f86fedc9bd6fad4130becd5d2213a2873c67aab5fd64303c415af6b4f4469fbda32b08f94
6
+ metadata.gz: d1f11152644b7e4632f7c8739d5c06b2dcbf6af1a156c7e83c012f353ab92ff914f4c6e9340454ace05c88bdfc7355e50b1144fc88512d552c819d4834aba59e
7
+ data.tar.gz: 7fa1db95bb331efceaff34b92c2688995ac17d9ac009789418b60724b393e61299c06aeebb3f7529e45b907699f337a13594cc2868ec5554ee01e85424af8aad
@@ -0,0 +1,57 @@
1
+ require 'faraday'
2
+ require 'multi_json'
3
+
4
+ # Internal: Faraday module that the response error middleware is added to.
5
+ module Faraday
6
+
7
+ # Internal: Faraday Middleware that deals with errors coming back from the API.
8
+ #
9
+ # Examples
10
+ #
11
+ # connection = Faraday.new({}) do |conn|
12
+ # conn.use Faraday::Response::RaiseReadmillError
13
+ # end
14
+ class Response::RaiseReadmillError < Response::Middleware
15
+
16
+ # Internal: Hook into the complete callback for the client. When the result
17
+ # comes back, if it is a status code that we want to raise an error for, we
18
+ # will do that.
19
+ #
20
+ # Returns nothing.
21
+ def on_complete(response)
22
+ return if response[:body].nil?
23
+
24
+ case response[:body][:status].to_i
25
+ when 400
26
+ raise Readmill::BadRequest, error_message(response)
27
+ when 401
28
+ raise Readmill::Unauthorized, error_message(response)
29
+ when 403
30
+ raise Readmill::Forbidden, error_message(response)
31
+ when 404
32
+ raise Readmill::NotFound, error_message(response)
33
+ when 500
34
+ raise Readmill::InternalServerError, error_message(response)
35
+ when 504
36
+ raise Readmill::GatewayTimeout, error_message(response)
37
+ end
38
+ end
39
+
40
+ # Internal: Parse the response and return a human friendly String
41
+ # representing the error that we received.
42
+ #
43
+ # Returns a String.
44
+ def error_message(response)
45
+ method = response[:method].to_s.upcase
46
+ url = response[:url].to_s
47
+ status = response[:body][:status]
48
+ error = response[:body][:error]
49
+ "#{method} #{url}: #{status} - #{error}"
50
+ end
51
+ end
52
+
53
+ # Internal: Register this middleware for faraday as response.
54
+ Faraday.register_middleware :response,
55
+ :readmill_errors => lambda { Faraday::Response::RaiseReadmillError }
56
+
57
+ end
@@ -1,2 +1,34 @@
1
+ require 'readmill/client'
2
+ require 'readmill/configuration'
3
+ require 'readmill/error'
4
+
1
5
  module Readmill
6
+
7
+ class << self
8
+
9
+ # Public: An alias for Readmill::Client.new.
10
+ #
11
+ # Returns an Readmill::Client.
12
+ def new(options={})
13
+ Readmill::Client.new(options)
14
+ end
15
+
16
+ # Public: Delegate methods to Readmill::Client.new. If a Readmill::Client
17
+ # does not respond_to? the :method, pass it up the chain.
18
+ #
19
+ # Returns nothing.
20
+ def method_missing(method, *args, &block)
21
+ return super unless new.respond_to?(method)
22
+ new.send(method, *args, &block)
23
+ end
24
+
25
+ # Public: Delegate to Readmill::Client.new respond_to?
26
+ #
27
+ # Returns nothing.
28
+ def respond_to?(method, include_private=false)
29
+ new.respond_to?(method, include_private) || super(method, include_private)
30
+ end
31
+
32
+ end
33
+
2
34
  end
@@ -0,0 +1,41 @@
1
+ require 'readmill/request'
2
+ require 'readmill/configuration'
3
+ require 'readmill/client/books'
4
+
5
+ module Readmill
6
+
7
+ # Public: The Client is what wraps all of the Readmill API. You will use this
8
+ # class to handle the majority of your interaction with Readmill.
9
+ class Client
10
+
11
+ # Public: Set instance level configuration values.
12
+ attr_accessor *Readmill::Configuration::VALID_CONFIGURATION_KEYS
13
+
14
+ # Public: Constructor for a Readmill::Client.
15
+ #
16
+ # opts - A Hash of options to modify the client (default: {}).
17
+ def initialize(opts={})
18
+
19
+ # TODO: Extract this, move it elsewhere. If this hasn't been configured,
20
+ # I'm wondering if we raise an exception and move on?
21
+ Readmill.configuration ||= Readmill::Configuration.new
22
+
23
+ config = Readmill.configuration.values.merge(opts)
24
+ Readmill::Configuration::VALID_CONFIGURATION_KEYS.each do |k|
25
+ send("#{k}=", config[k])
26
+ end
27
+ end
28
+
29
+ # Public: Get the base URL for accessing the Readmill API.
30
+ #
31
+ # Returns a String.
32
+ def api_url
33
+ "https://api.readmill.com/v2/"
34
+ end
35
+
36
+ include Readmill::Request
37
+ include Readmill::Client::Books
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,33 @@
1
+ module Readmill
2
+ class Client
3
+
4
+ # Public: This module will bring all of the methods from the book section
5
+ # of the API.
6
+ module Books
7
+
8
+ # Public: Get all books from readmill.
9
+ #
10
+ # opts - A Hash of options used to modify the results. All of the values
11
+ # of this Hash will be forwarded to the API as parameters
12
+ # (default: {}).
13
+ #
14
+ # Returns an Array.
15
+ def books(opts={})
16
+ get('books', opts).items
17
+ end
18
+
19
+ # Public: Get a specific book from readmill.
20
+ #
21
+ # id - The id of a book to get from readmill.
22
+ # opts - A Hash of options used to modify the results. All of the values
23
+ # of this Hash will be forwarded to the API as parameters
24
+ # (default: {}).
25
+ #
26
+ # Returns a Hashie::Mash.
27
+ def book(id, opts={})
28
+ get("books/#{id}", opts)
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,46 @@
1
+ module Readmill
2
+
3
+ class << self
4
+ attr_accessor :configuration
5
+ end
6
+
7
+ # Public: Configure a Readmill client.
8
+ #
9
+ # Examples
10
+ #
11
+ # Readmill.configure do |r|
12
+ # r.client_id = 'abc123'
13
+ # end
14
+ def self.configure
15
+ self.configuration ||= Configuration.new
16
+ yield(configuration)
17
+ end
18
+
19
+ # Internal: Store all of the configurable options inside of a Configuration
20
+ # class.
21
+ class Configuration
22
+
23
+ # Public: An Array of all keys that can be configured. This allows us to
24
+ # set instance keys, knowing what can and cannot be modified.
25
+ VALID_CONFIGURATION_KEYS = [:client_id, :timeout, :open_timeout, :adapter]
26
+
27
+ # Internal: Create a get/set method for each valid key.
28
+ attr_accessor *VALID_CONFIGURATION_KEYS
29
+
30
+ # Internal: Default all of the keys to valid defaults.
31
+ def initialize
32
+ self.client_id = nil
33
+ self.timeout = 10
34
+ self.open_timeout = 10
35
+ self.adapter = Faraday.default_adapter
36
+ end
37
+
38
+ # Public: Return all of the current values.
39
+ #
40
+ # Returns a Hash.
41
+ def values
42
+ VALID_CONFIGURATION_KEYS.inject({}){|o,k| o.merge!(k => send(k)) }
43
+ end
44
+ end
45
+
46
+ end
@@ -0,0 +1,24 @@
1
+ module Readmill
2
+
3
+ # Public: Custom error class for rescuing from all Readmill errors
4
+ class Error < StandardError; end
5
+
6
+ # Public: 400 HTTP Status Code
7
+ class BadRequest < Error; end
8
+
9
+ # Public: 401 HTTP Status Code
10
+ class Unauthorized < Error; end
11
+
12
+ # Public: 403 HTTP Status Code
13
+ class Forbidden < Error; end
14
+
15
+ # Public: 404 HTTP Status Code
16
+ class NotFound < Error; end
17
+
18
+ # Public: 500 HTTP Status Code
19
+ class InternalServerError < Error; end
20
+
21
+ # Public: 504 HTTP Status Code
22
+ class GatewayTimeout < Error; end
23
+
24
+ end
@@ -0,0 +1,64 @@
1
+ require 'multi_json'
2
+ require 'faraday_middleware'
3
+ require 'faraday/response/raise_readmill_error'
4
+
5
+ module Readmill
6
+
7
+ module Request
8
+
9
+ # Public: Make an HTTP GET Request to the path, passing the opts as params
10
+ # in the query.
11
+ #
12
+ # path - The path to request.
13
+ # opts - A Hash to send as query parameters (default: {}).
14
+ #
15
+ # Returns a String.
16
+ def get(path, opts={})
17
+ request(:get, path, opts)
18
+ end
19
+
20
+ private
21
+
22
+ # Internal: Use the Faraday::Connection from lib/espn/connection.rb and
23
+ # make the HTTP Request to the path.
24
+ #
25
+ # method - A Symbol specifying the HTTP method to use.
26
+ # path - The URL to send the request to.
27
+ # opts - The Hash options to send as query parameters.
28
+ #
29
+ # Returns a String.
30
+ def request(method, path, opts)
31
+ response = connection.send(method) do |request|
32
+ request.url(path, opts)
33
+ request.options[:timeout] = timeout
34
+ request.options[:open_timeout] = open_timeout
35
+
36
+ unless client_id.nil?
37
+ request.headers['Authorization'] = "Client #{client_id}"
38
+ end
39
+ end
40
+
41
+ response.body
42
+ end
43
+
44
+ # Internal: Build a new instance of Faraday with some default options and
45
+ # return it.
46
+ #
47
+ # Returns a Faraday::Connection.
48
+ def connection
49
+ options = { url: api_url, ssl: { verify: false } }
50
+
51
+ connection = Faraday.new(options) do |conn|
52
+ conn.response :readmill_errors
53
+ conn.response :mashify
54
+ conn.response :json
55
+
56
+ conn.adapter adapter
57
+ end
58
+
59
+ connection
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -1,6 +1,6 @@
1
1
  module Readmill
2
2
 
3
3
  # Public: The version of the Readmill gem.
4
- VERSION = '0.0.0'.freeze
4
+ VERSION = '0.0.1'.freeze
5
5
 
6
6
  end
@@ -0,0 +1,72 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.readmill.com/v2/books/1
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.8.8
12
+ Authorization:
13
+ - Client READMILL_CLIENT_ID
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ Accept:
17
+ - '*/*'
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Cache-Control:
24
+ - must-revalidate, private, max-age=0
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Date:
28
+ - Mon, 16 Dec 2013 02:33:14 GMT
29
+ Etag:
30
+ - '"d6b8fcef7531c80136b0539e78042926"'
31
+ Server:
32
+ - nginx/1.0.12
33
+ Status:
34
+ - 200 OK
35
+ X-Rack-Cache:
36
+ - miss
37
+ X-Request-Id:
38
+ - 1c23d7b8a812a1e03f6da245ca4a35f3
39
+ X-Runtime:
40
+ - '0.104400'
41
+ X-Ua-Compatible:
42
+ - IE=Edge,chrome=1
43
+ Content-Length:
44
+ - '2428'
45
+ Connection:
46
+ - keep-alive
47
+ body:
48
+ encoding: UTF-8
49
+ string: '{"book":{"id":1,"title":"Do More Faster: TechStars Lessons to Accelerate
50
+ Your Startup","author":"Cohen, David, Feld, Brad","identifier":"0470929839","story":"Practical
51
+ advice from some of today''s top early stage investors and entrepreneurs TechStars
52
+ is a mentorship-driven startup accelerator with operations in three U.S. cities.
53
+ Once a year in each city, it funds about ten Internet startups with a small
54
+ amount of capital and surrounds them with around fifty top Internet entrepreneurs
55
+ and investors. Historically, about seventy-five percent of the companies that
56
+ go through TechStars raise a meaningful amount of angel or venture capital.
57
+ Do More Faster: TechStars Lessons to Accelerate Your Startup is a collection
58
+ of advice that comes from individuals who have passed through, or are part
59
+ of, this proven program. Each vignette is an exploration of information often
60
+ heard during the TechStars program and provides practical insights into early
61
+ stage entrepreneurship. Contains seven sections, each focusing on a major
62
+ theme within the TechStars program, including idea and vision, fundraising,
63
+ legal and structure, and work/life balance Created by two highly regarded
64
+ experts in the world of early stage investing Essays in each section come
65
+ from the experienced author team as well as TechStar mentors, entrepreneurs,
66
+ and founders of companies While you''ll ultimately have to make your own
67
+ decisions about what''s right for your business, Do More Faster: TechStars
68
+ Lessons to Accelerate Your Startup can get your entrepreneurial endeavor headed
69
+ in the right direction.","published_at":"2010-10-19","language":"en","permalink":"do-more-faster-techstars-lessons-to-accelerate-your-startup","permalink_url":"https://readmill.com/books/do-more-faster-techstars-lessons-to-accelerate-your-startup","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Freadmill-assets.s3.amazonaws.com%252Fcovers%252F4c22fed8ffc2f4a651ab3dd994eb452403e12cf4-original.png&width=120","cover_metadata":{"original_width":300,"original_height":452},"assets":{"items":[{"asset":{"vendor":"","uri":"http://www.feedbooks.com/item/217887/do-more-faster-techstars-lessons-to-accelerate-your-startup","acquisition_type":"store"}}]},"readings_count":98,"recommended_readings_count":0,"active_and_finished_readings_count":24,"average_duration":214,"featured":false,"price_segment":null},"status":200}'
70
+ http_version:
71
+ recorded_at: Mon, 16 Dec 2013 02:33:13 GMT
72
+ recorded_with: VCR 2.8.0
@@ -0,0 +1,72 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.readmill.com/v2/books/1
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.8.8
12
+ Authorization:
13
+ - Client READMILL_CLIENT_ID
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ Accept:
17
+ - '*/*'
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Cache-Control:
24
+ - must-revalidate, private, max-age=0
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Date:
28
+ - Mon, 16 Dec 2013 03:37:29 GMT
29
+ Etag:
30
+ - '"d6b8fcef7531c80136b0539e78042926"'
31
+ Server:
32
+ - nginx/1.0.12
33
+ Status:
34
+ - 200 OK
35
+ X-Rack-Cache:
36
+ - miss
37
+ X-Request-Id:
38
+ - 78fe3796424215c04a878304b69a2453
39
+ X-Runtime:
40
+ - '0.096865'
41
+ X-Ua-Compatible:
42
+ - IE=Edge,chrome=1
43
+ Content-Length:
44
+ - '2428'
45
+ Connection:
46
+ - keep-alive
47
+ body:
48
+ encoding: UTF-8
49
+ string: '{"book":{"id":1,"title":"Do More Faster: TechStars Lessons to Accelerate
50
+ Your Startup","author":"Cohen, David, Feld, Brad","identifier":"0470929839","story":"Practical
51
+ advice from some of today''s top early stage investors and entrepreneurs TechStars
52
+ is a mentorship-driven startup accelerator with operations in three U.S. cities.
53
+ Once a year in each city, it funds about ten Internet startups with a small
54
+ amount of capital and surrounds them with around fifty top Internet entrepreneurs
55
+ and investors. Historically, about seventy-five percent of the companies that
56
+ go through TechStars raise a meaningful amount of angel or venture capital.
57
+ Do More Faster: TechStars Lessons to Accelerate Your Startup is a collection
58
+ of advice that comes from individuals who have passed through, or are part
59
+ of, this proven program. Each vignette is an exploration of information often
60
+ heard during the TechStars program and provides practical insights into early
61
+ stage entrepreneurship. Contains seven sections, each focusing on a major
62
+ theme within the TechStars program, including idea and vision, fundraising,
63
+ legal and structure, and work/life balance Created by two highly regarded
64
+ experts in the world of early stage investing Essays in each section come
65
+ from the experienced author team as well as TechStar mentors, entrepreneurs,
66
+ and founders of companies While you''ll ultimately have to make your own
67
+ decisions about what''s right for your business, Do More Faster: TechStars
68
+ Lessons to Accelerate Your Startup can get your entrepreneurial endeavor headed
69
+ in the right direction.","published_at":"2010-10-19","language":"en","permalink":"do-more-faster-techstars-lessons-to-accelerate-your-startup","permalink_url":"https://readmill.com/books/do-more-faster-techstars-lessons-to-accelerate-your-startup","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Freadmill-assets.s3.amazonaws.com%252Fcovers%252F4c22fed8ffc2f4a651ab3dd994eb452403e12cf4-original.png&width=120","cover_metadata":{"original_width":300,"original_height":452},"assets":{"items":[{"asset":{"vendor":"","uri":"http://www.feedbooks.com/item/217887/do-more-faster-techstars-lessons-to-accelerate-your-startup","acquisition_type":"store"}}]},"readings_count":98,"recommended_readings_count":0,"active_and_finished_readings_count":24,"average_duration":214,"featured":false,"price_segment":null},"status":200}'
70
+ http_version:
71
+ recorded_at: Mon, 16 Dec 2013 03:37:28 GMT
72
+ recorded_with: VCR 2.8.0
@@ -0,0 +1,61 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.readmill.com/v2/books
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.8.8
12
+ Authorization:
13
+ - Client READMILL_CLIENT_ID
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ Accept:
17
+ - '*/*'
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Cache-Control:
24
+ - must-revalidate, private, max-age=0
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Date:
28
+ - Mon, 16 Dec 2013 02:33:13 GMT
29
+ Etag:
30
+ - '"ca284445bdd40d8b1fe6bee2486e61aa"'
31
+ Server:
32
+ - nginx/1.0.12
33
+ Status:
34
+ - 200 OK
35
+ X-Rack-Cache:
36
+ - miss
37
+ X-Request-Id:
38
+ - c24e1a4e70d02f099bbe94bebcd9cc1f
39
+ X-Runtime:
40
+ - '0.131691'
41
+ X-Ua-Compatible:
42
+ - IE=Edge,chrome=1
43
+ Content-Length:
44
+ - '15340'
45
+ Connection:
46
+ - keep-alive
47
+ body:
48
+ encoding: UTF-8
49
+ string: '{"pagination":{"next":"https://api.readmill.com/v2/books?offset=0&order=created_at&to=2013-12-16+02%3A30%3A19+UTC"},"items":[{"book":{"id":360624,"title":"\u51c9\u751f\uff0c\u6211\u4eec\u53ef\u4e0d\u53ef\u4ee5\u4e0d\u5fe7\u4f241","author":"\u4e50\u5c0f\u7c73","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"liang-sheng-wo-men-ke-bu-ke-yi-bu-you-shang-1","permalink_url":"https://readmill.com/books/liang-sheng-wo-men-ke-bu-ke-yi-bu-you-shang-1","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360623,"title":"Cavalier
50
+ Case","author":"Antonia Fraser","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"cavalier-case","permalink_url":"https://readmill.com/books/cavalier-case","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360622,"title":"\u8721\u7b14\u5c0f\u65b0[49\u5377]-\u7b2c01\u5377","author":"\u81fc\u4e95\u4eea\u4eba","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"zha-bi-xiao-xin-49juan-di-01juan","permalink_url":"https://readmill.com/books/zha-bi-xiao-xin-49juan-di-01juan","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360621,"title":"Quinnell
51
+ - 01 - Man on Fire","author":"Dads","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"quinnell-01-man-on-fire","permalink_url":"https://readmill.com/books/quinnell-01-man-on-fire","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360620,"title":"\u6bd2","author":"\u97e9\u5bd2","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"du-1","permalink_url":"https://readmill.com/books/du-1","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360619,"title":"02
52
+ - Drop Shot","author":"Harlan Coben","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"02-drop-shot","permalink_url":"https://readmill.com/books/02-drop-shot","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360618,"title":"\u6bd4\u5c14\u30fb\u76d6\u8328\u5168\u4f20","author":"\u4e8e\u6210\u9f99","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"bi-er-gai-ci-quan-chuan","permalink_url":"https://readmill.com/books/bi-er-gai-ci-quan-chuan","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360617,"title":"Creepers
53
+ (2006)","author":"David - Frank Balenger 01 Morrell","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"creepers-2006","permalink_url":"https://readmill.com/books/creepers-2006","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360616,"title":"Foundations
54
+ and Concepts - vCloud","author":"VMware, Inc.","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"foundations-and-concepts-vcloud","permalink_url":"https://readmill.com/books/foundations-and-concepts-vcloud","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360615,"title":"\u90ce\u54b8\u5e73\u6587\u5b57\u5168\u96c6","author":"\u90ce\u54b8\u5e73","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"lang-xian-ping-wen-zi-quan-ji","permalink_url":"https://readmill.com/books/lang-xian-ping-wen-zi-quan-ji","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360614,"title":"Foundations
55
+ and Concepts - vCloud\n Automation Center 6.0","author":"VMware, Inc.","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"foundations-and-concepts-vcloud-automation-center-6-dot-0","permalink_url":"https://readmill.com/books/foundations-and-concepts-vcloud-automation-center-6-dot-0","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":1,"recommended_readings_count":0,"active_and_finished_readings_count":1,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360613,"title":"\u4e09\u6bdb\u5168\u96c612
56
+ \u968f\u60f3","author":"\u4e09\u6bdb\uff08\u53f0\uff09","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"san-mao-quan-ji-12-sui-xiang","permalink_url":"https://readmill.com/books/san-mao-quan-ji-12-sui-xiang","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360612,"title":"\u97e9\u5bd2\u6700\u65b0\u535a\u6587\u7cbe\u9009\uff1a\u53ef\u7231\u7684\u6d2a\u6c34\u731b\u517d","author":"\u97e9\u5bd2","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"han-han-zui-xin-bo-wen-jing-xuan-ke-ai-de-hong-shui-meng-shou","permalink_url":"https://readmill.com/books/han-han-zui-xin-bo-wen-jing-xuan-ke-ai-de-hong-shui-meng-shou","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360611,"title":"\u4e2d\u56fd\u7ecf\u5178\u8425\u9500\u6848\u4f8b\u5927\u5168\u548c\u4e16\u754c\u8425\u9500\u7edd\u5999\u70b9\u5b50","author":"\u4e0d\u8be6","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"zhong-guo-jing-dian-ying-xiao-an-li-da-quan-he-shi-jie-ying-xiao-jue-miao-dian-zi","permalink_url":"https://readmill.com/books/zhong-guo-jing-dian-ying-xiao-an-li-da-quan-he-shi-jie-ying-xiao-jue-miao-dian-zi","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360610,"title":"\u6b27\u6d32\u5927\u9646\u7684\u5de8\u4eba\uff1a\u5927\u56fd\u5d1b\u8d77\u00b7\u5fb7\u56fd","author":"COAY.COM","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"ou-zhou-da-lu-de-ju-ren-da-guo-jue-qi-star-de-guo","permalink_url":"https://readmill.com/books/ou-zhou-da-lu-de-ju-ren-da-guo-jue-qi-star-de-guo","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360609,"title":"\u704c\u7bee\u9ad8\u624b[\u5b8c]-\u7b2c01\u5377","author":"\u4e95\u4e0a\u96c4\u5f66","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"guan-lan-gao-shou-wan-di-01juan","permalink_url":"https://readmill.com/books/guan-lan-gao-shou-wan-di-01juan","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360608,"title":"JC01
57
+ - Birdman","author":"Mo Hayder","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"jc01-birdman","permalink_url":"https://readmill.com/books/jc01-birdman","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360607,"title":"\u505a\u6700\u597d\u7684\u81ea\u5df1\uff1a\u505a\u4eba\u4e0d\u8981\u592a\u8001\u5b9e","author":"\u6c34\u4e2d\u9c7c","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"zuo-zui-hao-de-zi-ji-zuo-ren-bu-yao-tai-lao-shi","permalink_url":"https://readmill.com/books/zuo-zui-hao-de-zi-ji-zuo-ren-bu-yao-tai-lao-shi","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360606,"title":"\u4e0e\u9886\u5bfc\u5403\u996d\u7684\u6280\u5de7","author":"\u5a01\u950bqweasdzxc6","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"yu-ling-dao-chi-fan-de-ji-qiao-1","permalink_url":"https://readmill.com/books/yu-ling-dao-chi-fan-de-ji-qiao-1","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360605,"title":"The
58
+ Eye in the Door","author":"Pat Barker","identifier":"9780141906447","story":null,"published_at":null,"language":null,"permalink":"the-eye-in-the-door","permalink_url":"https://readmill.com/books/the-eye-in-the-door","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}}],"status":200}'
59
+ http_version:
60
+ recorded_at: Mon, 16 Dec 2013 02:33:12 GMT
61
+ recorded_with: VCR 2.8.0
@@ -0,0 +1,92 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.readmill.com/v2/books
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.8.8
12
+ Authorization:
13
+ - Client READMILL_CLIENT_ID
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ Accept:
17
+ - '*/*'
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Cache-Control:
24
+ - must-revalidate, private, max-age=0
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Date:
28
+ - Mon, 16 Dec 2013 03:35:14 GMT
29
+ Etag:
30
+ - '"63c3547bfbe2bac2bfdb26d0d5929376"'
31
+ Server:
32
+ - nginx/1.0.12
33
+ Status:
34
+ - 200 OK
35
+ X-Rack-Cache:
36
+ - miss
37
+ X-Request-Id:
38
+ - 382d5a631212d178be472aed493af446
39
+ X-Runtime:
40
+ - '0.162167'
41
+ X-Ua-Compatible:
42
+ - IE=Edge,chrome=1
43
+ Content-Length:
44
+ - '16069'
45
+ Connection:
46
+ - keep-alive
47
+ body:
48
+ encoding: UTF-8
49
+ string: '{"pagination":{"next":"https://api.readmill.com/v2/books?offset=0&order=created_at&to=2013-12-16+03%3A06%3A08+UTC"},"items":[{"book":{"id":360767,"title":"Wave
50
+ (2013)","author":"Deraniyagala, Sonali","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"wave-2013","permalink_url":"https://readmill.com/books/wave-2013","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Freadmill-assets.s3.amazonaws.com%252Fcovers%252Facf504a58ad1d1974e9eea3001cdb5119eb98e62-original.png&width=120","cover_metadata":{"original_width":525,"original_height":700},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360766,"title":"We
51
+ All Scream","author":"Nona Wesley","identifier":"9781606595480","story":null,"published_at":null,"language":null,"permalink":"we-all-scream","permalink_url":"https://readmill.com/books/we-all-scream","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360765,"title":"AVENGING
52
+ ANGEL","author":"Tara Janzen","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"avenging-angel-2","permalink_url":"https://readmill.com/books/avenging-angel-2","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360764,"title":"AC.BOW.06
53
+ BLACK FLAG","author":"Assassin''s Creed","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"ac-dot-bow-dot-06-black-flag","permalink_url":"https://readmill.com/books/ac-dot-bow-dot-06-black-flag","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360763,"title":"First
54
+ Thing I See","author":"Keeland, Vi","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"first-thing-i-see","permalink_url":"https://readmill.com/books/first-thing-i-see","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Freadmill-assets.s3.amazonaws.com%252Fcovers%252Ff2a7b3aea7430a65c85535a46959651db3d7f1c7-original.png&width=120","cover_metadata":{"original_width":500,"original_height":751},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360762,"title":"ASOIAF.MAR.99
55
+ THE A SONG OF ICE AND FIRE SERIES","author":"George R. R. Martin","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"asoiaf-dot-mar-dot-99-the-a-song-of-ice-and-fire-series","permalink_url":"https://readmill.com/books/asoiaf-dot-mar-dot-99-the-a-song-of-ice-and-fire-series","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360761,"title":"Richelle''s
56
+ Tale","author":"Kelli Wolfe","identifier":null,"story":"Princess Richelle
57
+ is given to the human priests of the Five Gods and enslaved. To preserve her
58
+ life she must submit to High Priest Lucan and his friends and serve them body
59
+ and soul. Will she bow to them and allow them to sate their lusts on her innocence,
60
+ or will she feed the hunger of their dark gods?","published_at":null,"language":null,"permalink":"richelles-tale","permalink_url":"https://readmill.com/books/richelles-tale","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Freadmill-assets.s3.amazonaws.com%252Fcovers%252F0a9d41d66a85b3e3d95bd171894c91a08565d52c-original.png&width=120","cover_metadata":{"original_width":546,"original_height":819},"assets":{"items":[]},"readings_count":1,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360760,"title":"Fall
61
+ From Love","author":"Heather London","identifier":null,"story":"Struggling
62
+ to put her life back together after a tragic mountaineering accident kills
63
+ her college sweetheart, twenty-one-year-old Holly Treadwell is trying to set
64
+ aside her grief, forge ahead in school, and find herself again.When Carter
65
+ Hansen, a guy who brings back horrible memories from the night of the accident,
66
+ finds his way back into her life, Holly\u2019s unsure if she should let him
67
+ in. He terrifies her in more ways than one and invokes feelings in her that
68
+ she thought were buried forever. Regardless of her fears, she knows she must
69
+ face him in order for her heart to heal. Everyone tells Carter that what happened
70
+ on the mountain that night was just a terrible accident, but even then, he
71
+ can\u2019t help but carry around the guilt and is unable to forgive himself.
72
+ He\u2019s drawn to Holly and being near her helps ease his conscience and
73
+ gives him the release he needs.As Holly and Carter\u2019s relationship grows,
74
+ they begin to realize that the more time they spend with one another, the
75
+ more their wounds begin to heal\u2014her grief and his guilt. But when Holly
76
+ learns the details about the night of the accident\u2014what everyone has
77
+ been keeping from her\u2014it will rip open old wounds and tear apart what
78
+ they\u2019ve both worked so hard to overcome\u2026","published_at":null,"language":null,"permalink":"fall-from-love","permalink_url":"https://readmill.com/books/fall-from-love","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Freadmill-assets.s3.amazonaws.com%252Fcovers%252F1788abbfe4951913a6f3824f7f299471e3ee7566-original.png&width=120","cover_metadata":{"original_width":491,"original_height":751},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360759,"title":"Getting
79
+ It Right","author":"Kaje Harper","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"getting-it-right-1","permalink_url":"https://readmill.com/books/getting-it-right-1","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":1,"recommended_readings_count":0,"active_and_finished_readings_count":1,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360758,"title":"The
80
+ Christian in Complete Armour","author":"William Gurnall","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"the-christian-in-complete-armour","permalink_url":"https://readmill.com/books/the-christian-in-complete-armour","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Freadmill-assets.s3.amazonaws.com%252Fcovers%252Fc886f9d040060e59c6d2b63e8e42e38b70b665ee-original.png&width=120","cover_metadata":{"original_width":200,"original_height":304},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360757,"title":"i
81
+ e38186562a84eac0","author":"Unknown","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"i-e38186562a84eac0","permalink_url":"https://readmill.com/books/i-e38186562a84eac0","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":1,"recommended_readings_count":0,"active_and_finished_readings_count":1,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360756,"title":"i
82
+ 721547deeb95f2ba","author":"intern","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"i-721547deeb95f2ba","permalink_url":"https://readmill.com/books/i-721547deeb95f2ba","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360755,"title":"Echoes
83
+ from the Orient","author":"Chiqui Morrow","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"echoes-from-the-orient","permalink_url":"https://readmill.com/books/echoes-from-the-orient","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":1,"recommended_readings_count":0,"active_and_finished_readings_count":1,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360754,"title":"Microsoft
84
+ Word - book_4 - edit - 7 - two paragraphs inserted.doc","author":"Ian","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"microsoft-word-book-4-edit-7-two-paragraphs-inserted-dot-doc","permalink_url":"https://readmill.com/books/microsoft-word-book-4-edit-7-two-paragraphs-inserted-dot-doc","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360753,"title":"Microsoft
85
+ Word - book_5 - edit - 6.doc","author":"Ian","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"microsoft-word-book-5-edit-6-dot-doc","permalink_url":"https://readmill.com/books/microsoft-word-book-5-edit-6-dot-doc","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360752,"title":"AC.BOW.05
86
+ FORSAKEN","author":"Assassin''s Creed","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"ac-dot-bow-dot-05-forsaken","permalink_url":"https://readmill.com/books/ac-dot-bow-dot-05-forsaken","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360751,"title":"subway_web_map_Sep12.eps","author":"Chuck","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"subway-web-map-sep12-dot-eps","permalink_url":"https://readmill.com/books/subway-web-map-sep12-dot-eps","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360750,"title":"NFT
87
+ Guide April 2008.cwk","author":"Craig Elevitch1","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"nft-guide-april-2008-dot-cwk","permalink_url":"https://readmill.com/books/nft-guide-april-2008-dot-cwk","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":1,"recommended_readings_count":0,"active_and_finished_readings_count":1,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360749,"title":"Mowers","author":"Jordan
88
+ B","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"mowers","permalink_url":"https://readmill.com/books/mowers","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":1,"recommended_readings_count":0,"active_and_finished_readings_count":1,"average_duration":null,"featured":false,"price_segment":null}},{"book":{"id":360748,"title":"Anthropology:
89
+ Appreciating Human Diversity","author":"Conrad P Kottak","identifier":null,"story":null,"published_at":null,"language":null,"permalink":"anthropology-appreciating-human-diversity","permalink_url":"https://readmill.com/books/anthropology-appreciating-human-diversity","cover_url":"https://d26cmntuippvfl.cloudfront.net/?action=shrink-w&format=png&origin=https%253A%252F%252Fd15fum6h02z48v.cloudfront.net%252Fassets%252Fdefault-cover-original-a8cdd3ce01730b6af1039cff21184295.png&width=120","cover_metadata":{"original_width":1200,"original_height":1800},"assets":{"items":[]},"readings_count":0,"recommended_readings_count":0,"active_and_finished_readings_count":0,"average_duration":null,"featured":false,"price_segment":null}}],"status":200}'
90
+ http_version:
91
+ recorded_at: Mon, 16 Dec 2013 03:35:14 GMT
92
+ recorded_with: VCR 2.8.0
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe Faraday::Response::RaiseReadmillError do
4
+ before do
5
+ @class = described_class.new
6
+ end
7
+
8
+ context 'when used' do
9
+ before do
10
+ @response = Hashie::Mash.new(method: :get, url: 'http://test')
11
+ @response.body = Hashie::Mash.new(status: 'error', error: 'foobar')
12
+ end
13
+
14
+ it 'does not raise an error if the response has no body' do
15
+ @response.body = nil
16
+ lambda {
17
+ @class.on_complete(@response)
18
+ }.should_not raise_error
19
+ end
20
+
21
+ it 'does not raise an error for HTTP 200' do
22
+ @response.body.status = 200
23
+ lambda {
24
+ @class.on_complete(@response)
25
+ }.should_not raise_error
26
+ end
27
+
28
+ it 'raises an error for HTTP 400' do
29
+ @response.body.status = 400
30
+ lambda {
31
+ @class.on_complete(@response)
32
+ }.should raise_error(Readmill::BadRequest)
33
+ end
34
+
35
+ it 'raises an error for HTTP 401' do
36
+ @response.body.status = 401
37
+ lambda {
38
+ @class.on_complete(@response)
39
+ }.should raise_error(Readmill::Unauthorized)
40
+ end
41
+
42
+ it 'raises an error for HTTP 403' do
43
+ @response.body.status = 403
44
+ lambda {
45
+ @class.on_complete(@response)
46
+ }.should raise_error(Readmill::Forbidden)
47
+ end
48
+
49
+ it 'raises an error for HTTP 404' do
50
+ @response.body.status = 404
51
+ lambda {
52
+ @class.on_complete(@response)
53
+ }.should raise_error(Readmill::NotFound)
54
+ end
55
+
56
+ it 'raises an error for HTTP 500' do
57
+ @response.body.status = 500
58
+ lambda {
59
+ @class.on_complete(@response)
60
+ }.should raise_error(Readmill::InternalServerError)
61
+ end
62
+
63
+ it 'raises an error fro HTTP 504' do
64
+ @response.body.status = 504
65
+ lambda {
66
+ @class.on_complete(@response)
67
+ }.should raise_error(Readmill::GatewayTimeout)
68
+ end
69
+ end
70
+
71
+ describe '#error_message' do
72
+ it 'should be formatted correctly' do
73
+ response = Hashie::Mash.new(method: :get, url: 'http://test')
74
+ response.body = Hashie::Mash.new(status: '404', error: 'Not Found')
75
+ result = @class.error_message(response)
76
+ result.should eq('GET http://test: 404 - Not Found')
77
+ end
78
+ end
79
+
80
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Readmill::Client::Books do
4
+ let (:client) { Readmill::Client.new }
5
+
6
+ describe '.books' do
7
+ let! (:result) { client.books }
8
+
9
+ it 'should request all books from readmill' do
10
+ assert_requested :get, readmill_url('books')
11
+ end
12
+
13
+ it 'should return an array of books' do
14
+ expect(result).to be_a(Array)
15
+ expect(result.first).to respond_to(:book)
16
+ end
17
+ end
18
+
19
+ describe '.book' do
20
+ let! (:result) { client.book(1) }
21
+
22
+ it 'should request a book from readmill' do
23
+ assert_requested :get, readmill_url('books/1')
24
+ end
25
+
26
+ it 'should return a book' do
27
+ expect(result).to respond_to(:book)
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Readmill::Client do
4
+ let (:client) { Readmill::Client.new }
5
+
6
+ describe '.initialize' do
7
+ it 'should pass valid keys to the client' do
8
+ client = Readmill::Client.new(client_id: 'abc123')
9
+ expect(client.client_id).to eq('abc123')
10
+ end
11
+
12
+ it 'should override global configurations' do
13
+ client = Readmill::Client.new(timeout: 15)
14
+ expect(client.timeout).to eq(15)
15
+ end
16
+
17
+ it 'should not delete unaltered global configurations' do
18
+ client = Readmill::Client.new(timeout: 15)
19
+ expect(client.open_timeout).to eq(10)
20
+ end
21
+ end
22
+
23
+ describe '#api_url' do
24
+ it 'should return the correct url' do
25
+ expect(client.api_url).to eq('https://api.readmill.com/v2/')
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Readmill do
4
+
5
+ describe '.methods' do
6
+ describe '.configure' do
7
+ it 'should allow you to set global configuration options' do
8
+ Readmill.configure do |c|
9
+ c.client_id = 'somerandomkey'
10
+ end
11
+ expect(Readmill.configuration.client_id).to eq('somerandomkey')
12
+ end
13
+ end
14
+ end
15
+
16
+ describe Readmill::Configuration do
17
+ let (:config) { Readmill::Configuration.new }
18
+
19
+ describe '.defaults' do
20
+ { client_id: nil, timeout: 10, open_timeout: 10,
21
+ adapter: Faraday.default_adapter }.each do |k, v|
22
+ it "should default #{k} to #{v}" do
23
+ expect(config.send(k)).to eq(v)
24
+ end
25
+ end
26
+ end
27
+
28
+ describe '#methods' do
29
+ describe '#values' do
30
+ before do
31
+ config.client_id = 'abc123'
32
+ end
33
+
34
+ describe '#values' do
35
+ it 'should return a hash of configuration settings' do
36
+ expect(config.values).to eq({
37
+ client_id: 'abc123',
38
+ timeout: 10,
39
+ open_timeout: 10,
40
+ adapter: Faraday.default_adapter
41
+ })
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Readmill::Request do
4
+ let (:client) { Readmill::Client.new }
5
+
6
+ describe '#get' do
7
+ it 'should call request' do
8
+ opts = { foo: 'bar' }
9
+ pattern = '/foo/bar'
10
+ client.should_receive(:request).with(:get, pattern, opts)
11
+ client.get(pattern, opts)
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,46 @@
1
+ require 'readmill'
2
+ require 'rspec'
3
+ require 'webmock/rspec'
4
+ require 'hashie'
5
+ require 'vcr'
6
+ require 'dotenv'
7
+
8
+ # Monkeypatch String to add the underscore method
9
+ class String
10
+ def underscore
11
+ self.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
12
+ .gsub(/([a-z\d])([A-Z])/,'\1_\2').tr("-", "_").downcase
13
+ end
14
+ end
15
+
16
+ # Load all ENV variables from .env
17
+ Dotenv.load
18
+
19
+ Readmill.configure do |c|
20
+ c.client_id = ENV['READMILL_CLIENT_ID']
21
+ end
22
+
23
+ VCR.configure do |c|
24
+ c.cassette_library_dir = 'spec/cassettes'
25
+ c.filter_sensitive_data('READMILL_CLIENT_ID') { ENV['READMILL_CLIENT_ID'] }
26
+ c.hook_into :webmock
27
+ end
28
+
29
+ RSpec.configure do |config|
30
+
31
+ # Add VCR to all tests
32
+ config.around(:each) do |example|
33
+ options = example.metadata[:vcr] || {}
34
+ if options[:record] == :skip
35
+ VCR.turned_off(&example)
36
+ else
37
+ name = example.metadata[:full_description].split(/\s+/, 2).join("/")
38
+ .underscore.gsub(/[^\w\/]+/, "_")
39
+ VCR.use_cassette(name, options, &example)
40
+ end
41
+ end
42
+ end
43
+
44
+ def readmill_url(url)
45
+ "https://api.readmill.com/v2/#{url}"
46
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: readmill
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Thorp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-12 00:00:00.000000000 Z
11
+ date: 2013-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -106,8 +106,24 @@ files:
106
106
  - LICENSE.md
107
107
  - README.md
108
108
  - readmill.gemspec
109
+ - lib/faraday/response/raise_readmill_error.rb
110
+ - lib/readmill/client/books.rb
111
+ - lib/readmill/client.rb
112
+ - lib/readmill/configuration.rb
113
+ - lib/readmill/error.rb
114
+ - lib/readmill/request.rb
109
115
  - lib/readmill/version.rb
110
116
  - lib/readmill.rb
117
+ - spec/cassettes/readmill/client/books_book/should_request_a_book_from_readmill.yml
118
+ - spec/cassettes/readmill/client/books_book/should_return_a_book.yml
119
+ - spec/cassettes/readmill/client/books_books/should_request_all_books_from_readmill.yml
120
+ - spec/cassettes/readmill/client/books_books/should_return_an_array_of_books.yml
121
+ - spec/faraday/response/raise_readmill_error_spec.rb
122
+ - spec/readmill/client/books_spec.rb
123
+ - spec/readmill/client_spec.rb
124
+ - spec/readmill/configuration_spec.rb
125
+ - spec/readmill/request_spec.rb
126
+ - spec/spec_helper.rb
111
127
  homepage: http://github.com/andrewpthorp/readmill
112
128
  licenses: []
113
129
  metadata: {}
@@ -131,5 +147,15 @@ rubygems_version: 2.0.3
131
147
  signing_key:
132
148
  specification_version: 4
133
149
  summary: Simple wrapper for the Readmill API.
134
- test_files: []
150
+ test_files:
151
+ - spec/cassettes/readmill/client/books_book/should_request_a_book_from_readmill.yml
152
+ - spec/cassettes/readmill/client/books_book/should_return_a_book.yml
153
+ - spec/cassettes/readmill/client/books_books/should_request_all_books_from_readmill.yml
154
+ - spec/cassettes/readmill/client/books_books/should_return_an_array_of_books.yml
155
+ - spec/faraday/response/raise_readmill_error_spec.rb
156
+ - spec/readmill/client/books_spec.rb
157
+ - spec/readmill/client_spec.rb
158
+ - spec/readmill/configuration_spec.rb
159
+ - spec/readmill/request_spec.rb
160
+ - spec/spec_helper.rb
135
161
  has_rdoc: