readmill 0.0.0 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: