mroch-campusbooks 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Marshall Roch
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,7 @@
1
+ = campusbooks
2
+
3
+ Description goes here.
4
+
5
+ == Copyright
6
+
7
+ Copyright (c) 2009 Marshall Roch. See LICENSE for details.
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 0
3
+ :major: 0
4
+ :minor: 1
@@ -0,0 +1,15 @@
1
+ module CampusBooks
2
+ class Error < StandardError ; end
3
+
4
+ def self.api_key
5
+ @api_key
6
+ end
7
+
8
+ def self.api_key=(key)
9
+ @api_key = key
10
+ end
11
+ end
12
+
13
+ require 'campusbooks/base'
14
+ require 'campusbooks/book'
15
+ require 'campusbooks/offer'
@@ -0,0 +1,25 @@
1
+ require 'httparty'
2
+
3
+ module CampusBooks
4
+ class Base
5
+ include HTTParty
6
+ base_uri 'http://api.campusbooks.com/3/rest'
7
+ format :xml
8
+
9
+ protected
10
+ def self.get_response(path, options={})
11
+ res = self.get(path, options)
12
+ case res['response']['status']
13
+ when 'ok'
14
+ return res['response']
15
+
16
+ when 'error'
17
+ err_count = res['response']['errors']['error'].length
18
+ raise Error, err_count == 1 ? 'An error' : "#{err_count} errors" +
19
+ " occured while getting path '#{path}' with options #{options.inspect}:\n " +
20
+ res['response']['errors']['error'].join("\n ")
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,83 @@
1
+ require 'isbn/tools'
2
+
3
+ module CampusBooks
4
+ class Book < Base
5
+ SUPPORTED_PARAMS = [
6
+ :isbn10, # Ten-Digit ISBN for this book
7
+ :isbn13, # Thirteen-Digit ISBN for this book
8
+ :title, # Book Title
9
+ :author, # Book Author
10
+ :binding, # Book Binding
11
+ :msrp, # List price for the book
12
+ :pages, # Number of pages in the book
13
+ :publisher, # Book Publisher
14
+ :published_date, # Published Date
15
+ :edition, # Edition
16
+ :description # A text description for the book
17
+ ]
18
+ attr_reader *SUPPORTED_PARAMS
19
+ alias_method :isbn, :isbn13
20
+
21
+ def self.find(isbn, opts = {})
22
+ isbn = isbn.to_s
23
+ canonical_isbn = (ISBN_Tools.is_valid_isbn13?(isbn) ? isbn : ISBN_Tools.isbn10_to_isbn13(isbn)) or raise ArgumentError.new('isbn is invalid')
24
+
25
+ include_prices = opts[:include] && [*opts[:include]].include?(:prices)
26
+
27
+ raw_result = get_response(include_prices ? '/bookprices' : '/bookinfo', :query => {
28
+ :isbn => canonical_isbn, :key => CampusBooks.api_key
29
+ })
30
+
31
+ book_params = include_prices ? raw_result['page']['book'] : raw_result['page']
32
+
33
+ if raw_result['page']['offers']
34
+ book_params['offers'] = flatten_offers(raw_result['page']['offers'])
35
+ end
36
+
37
+ new(book_params)
38
+ end
39
+
40
+ def initialize(params = {})
41
+ create_offers(params.delete('offers')) if params.key?('offers')
42
+
43
+ SUPPORTED_PARAMS.each do |param|
44
+ instance_variable_set("@#{param}", params[param.to_s]) if params.key?(param.to_s)
45
+ end
46
+ end
47
+
48
+ def published_date
49
+ @parsed_published_date ||= Date.parse(@published_date)
50
+ end
51
+
52
+ def offers
53
+ if !@offers_loaded
54
+ raw_offers = get_response('/prices', :query => { :isbn => @isbn, :key => CampusBooks.api_key })['page']
55
+ create_offers(self.class.flatten_offers(raw_offers))
56
+ end
57
+ @offers
58
+ end
59
+
60
+ private
61
+ def self.flatten_offers(data)
62
+ result = []
63
+ data['condition'].each do |condition|
64
+ if condition['offer']
65
+ if condition['offer'].is_a?(Array)
66
+ condition['offer'].each do |offer|
67
+ result.push(offer)
68
+ end
69
+ else
70
+ result.push(condition['offer'])
71
+ end
72
+ end
73
+ end
74
+ result
75
+ end
76
+
77
+ def create_offers(offer_hashes)
78
+ @offers = offer_hashes.inject([]) { |ary, offer_hash| ary.push(Offer.new(offer_hash)) }
79
+ @offers_loaded = true
80
+ return @offers
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,35 @@
1
+ module CampusBooks
2
+ class Offer < Base
3
+ SUPPORTED_PARAMS = [
4
+ :isbn, # The ISBN for this offer
5
+ :isbn13, # The thirteen digit ISBN for this offer
6
+ :isbn10, # The ten digit ISBN for this offer
7
+ :merchant_id, # A numeric merchant ID (Note, this value may be signed)
8
+ :merchant_name, # The Name of the merchant (looked up from the defined constants)
9
+ :price, # The price that this merchant is listing this item for
10
+ :shipping_ground, # The cost to ship to an address in the US via ground services
11
+ :total_price, # Seller price plus the ground shipping price
12
+ :link, # Link to purchase the book
13
+ :condition_id, # Numeric representation of the condition (see constants)
14
+ :condition_text, # Text representation of the condition
15
+ :availability_id, # Numeric representation of the availability (how long it takes for the seller to ship it)
16
+ :availability_text, # Text representation of the availability
17
+ :location, # Geographic location where this item ships from (not always present)
18
+ :their_id, # The merchant's id for this offer (not always present)
19
+ :comments, # Comments about this offering
20
+ :condition_text # Text representation of the condition
21
+ ]
22
+ attr_reader *SUPPORTED_PARAMS
23
+
24
+ def initialize(params = {})
25
+ SUPPORTED_PARAMS.each do |param|
26
+ instance_variable_set("@#{param}", params[param.to_s]) if params.key?(param.to_s)
27
+ end
28
+ end
29
+
30
+ # Fall back on ISBN13 or ISBN10 if @isbn isn't set
31
+ def isbn
32
+ @isbn || @isbn13 || @isbn10
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,20 @@
1
+ Copyright 2006, Thierry Godfroid
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ * The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16
+ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
17
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,60 @@
1
+ == ISBN-Tools for Ruby
2
+
3
+ This library provides the ability to manipulate ISBN numbers.
4
+ It knows about ISBN-10 and ISBN-13 numbers, has the ability to
5
+ check if they are valid and convert from one format to the other.
6
+ It can, of course, compute the check digit of both formats.
7
+
8
+ Finally, it has the ability to hyphenate ISBN numbers for the
9
+ following group identifiers: 0, 1 and 2. Note that only hyphenation
10
+ methods need to know about ranges, so all others methods (validity,
11
+ checksum computations and number conversions) can be used with ISBN
12
+ numbers from any group.
13
+
14
+ Other ranges could be added on request but I would need samples
15
+ ISBN to check the result.
16
+
17
+ == Usage
18
+
19
+ require 'rubygems'
20
+ require 'isbn/tools'
21
+
22
+ isbn_good = "2800107766"
23
+ isbn_bad = "2810107766"
24
+
25
+ def check_and_hyphenate(isbn)
26
+ if ISBN_Tools.is_valid?(isbn)
27
+ puts ISBN_Tools.hyphenate(isbn)
28
+ else
29
+ cksum = ISBN_Tools.compute_check_digit(isbn)
30
+ puts "Invalid ISBN number [#{isbn}]. Checksum should be #{cksum}"
31
+ end
32
+ end
33
+
34
+ check_and_hyphenate isbn_good # => 2-8001-0776-6
35
+ check_and_hyphenate isbn_bad # => Invalid ISBN number [2810107766]. Checksum should be 9
36
+
37
+ == Copyright
38
+
39
+ Copyright:: 2006, Thierry Godfroid
40
+
41
+ The following sources were used in order to understand ISBN numbers and
42
+ how to manipulate them. No books were harmed in the process.
43
+ - http://www.isbn-international.org
44
+ - "Are You Ready for ISBN-13?" http://www.isbn.org/standards/home/isbn/transition.asp. Note that at the bottom of this page, you can find a link towards a small book "ISBN-13 for Dummies", available as PDF (http://www.bisg.org/isbn-13/ISBN13_For_Dummies.pdf)
45
+ - Structure of an ISBN number http://www.isbn.org/standards/home/isbn/international/html/usm4.htm
46
+
47
+ Ranges information was found at http://www.isbn-international.org/en/identifiers.html.
48
+
49
+ == LICENCE NOTE
50
+
51
+ MIT-Style license. See LICENCE file in this distribution.
52
+
53
+ == Requirements
54
+
55
+ ISBN-Tools requires Ruby 1.8.2 or better.
56
+
57
+ == Known bugs/Limitations
58
+
59
+ - This release code only allows for one-digit groups.
60
+ - See also the TODO file in this distribution
@@ -0,0 +1,173 @@
1
+ #--
2
+ # Copyright 2006, Thierry Godfroid
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # * The name of the author may not be used to endorse or promote products derived
12
+ # from this software without specific prior written permission.
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in all
15
+ # copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19
+ # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ #++
24
+
25
+ # This module provides all the methods of the ISBN-Tools library.
26
+ # Methods have no state but the library reads the file data/ranges.dat
27
+ # and fills up the RNG hash when loaded.
28
+ module ISBN_Tools
29
+ # Supported groups and associated ranges. Data is read from data/ranges.dat
30
+ # (provided in gem) at module load.
31
+ RNG = {}
32
+
33
+ File.open(File.join(File.dirname(__FILE__), "../../data/ranges.dat")) do |file|
34
+ file.each do |line|
35
+ line.chomp!
36
+ break if line.empty?
37
+ ar_line = line.split(/,/)
38
+ ndx = ar_line.delete_at(0)
39
+ RNG[ndx] = []
40
+ ar_line.each { |item|
41
+ r = item.split(/\.\./)
42
+ RNG[ndx].push(Range.new(r[0],r[1]))
43
+ }
44
+ end
45
+ end
46
+
47
+ # Clear all useless characters from an ISBN number and upcase the 'X' sign when
48
+ # present. Also does the basic check that 'X' must be the last sign of the number,
49
+ # if present. Returns nil if provided string is nil or X is not at the last position.
50
+ #
51
+ # No length check is done: no matter what string is passed in, all characters that
52
+ # not in the range [0-9xX] are removed.
53
+ def ISBN_Tools.cleanup(isbn_)
54
+ isbn_.gsub(/[^0-9xX]/,'').gsub(/x/,'X') unless isbn_.nil? or isbn_.scan(/([xX])/).length > 1
55
+ end
56
+
57
+ # Same as cleanup but alters the argument.
58
+ def ISBN_Tools.cleanup!(isbn_)
59
+ isbn_.replace(cleanup(isbn_))
60
+ end
61
+
62
+ # Check that the value is a valid ISBN-10 number. Returns true if it is, false otherwise.
63
+ # The method will check that the number is exactly 10 digits long and that the tenth digit is
64
+ # the correct checksum for the number.
65
+ def ISBN_Tools.is_valid_isbn10?(isbn_)
66
+ isbn = cleanup(isbn_)
67
+ return false if isbn.nil? or isbn.match(/^[0-9]{9}[0-9X]$/).nil?
68
+ sum = 0;
69
+ 0.upto(9) { |ndx| sum += (isbn[ndx]!= 88 ? isbn[ndx].chr.to_i : 10) * (10-ndx) } # 88 is ascii of X
70
+ sum % 11 == 0
71
+ end
72
+
73
+ # Check that the value is a valid ISBN-13 number. Returns true if it is, false otherwise.
74
+ # The method will check that the number is exactly 13 digits long and that the thirteenth digit is
75
+ # the correct checksum for the number.
76
+ def ISBN_Tools.is_valid_isbn13?(isbn_)
77
+ isbn = cleanup(isbn_)
78
+ return false if isbn.nil? or isbn.length!=13 or isbn.match(/^97[8|9][0-9]{10}$/).nil?
79
+ sum = 0
80
+ 0.upto(12) { |ndx| sum += isbn[ndx].chr.to_i * (ndx % 2 == 0 ? 1 : 3) }
81
+ sum.remainder(10) == 0
82
+ end
83
+
84
+ # Check that an ISBN is valid or not. Returns true if is, false otherwise. This method will
85
+ # first call is_valid_isbn10() and, on failure, try is_valid_isbn13(). Returns true if it is
86
+ # a valid number, false otherwise.
87
+ # This method is handy if you don't want to be bothered by checking the length of your
88
+ # isbn before checking its validity. It is a bit slower since cleanup will be called twice.
89
+ def ISBN_Tools.is_valid?(isbn_)
90
+ is_valid_isbn10?(isbn_) || is_valid_isbn13?(isbn_)
91
+ end
92
+
93
+ # Computes the check digit of an ISBN-10 number. It will ignore the tenth sign if present
94
+ # and accepts a number with only 9 digits. Returns the checksum digit or nil. Please note
95
+ # that the checksum digit of an ISBN-10 may be the character 'X'.
96
+ def ISBN_Tools.compute_isbn10_check_digit(isbn_)
97
+ isbn = cleanup(isbn_)
98
+ return nil if isbn.nil? or isbn.length > 10 or isbn.length < 9
99
+ sum = 0;
100
+ 0.upto(8) { |ndx| sum += isbn[ndx].chr.to_i * (10-ndx) }
101
+ (11-sum) % 11 == 10 ? "X" : ((11-sum) % 11).to_s
102
+ end
103
+
104
+ # Computes the check digit of an ISBN-13 number. It will ignore the thirteenth sign if present
105
+ # and accepts a number with only 12 digits. Returns the checksum digit or nil. Please note
106
+ # that the checksum digit of an ISBN-13 is always in the range [0-9].
107
+ def ISBN_Tools.compute_isbn13_check_digit(isbn_)
108
+ isbn = cleanup(isbn_)
109
+ return nil if isbn.nil? or isbn.length > 13 or isbn.length < 12
110
+ sum = 0
111
+ 0.upto(11) { |ndx| sum += isbn[ndx].chr.to_i * (ndx % 2 == 0 ? 1 : 3) }
112
+ (10-sum.remainder(10)) == 10 ? "0" : (10-sum.remainder(10)).to_s
113
+ end
114
+
115
+ # Compute the check digit of an ISBN number. Try as an ISBN-10 number
116
+ # first, and if it failed, as an ISBN-13 number. Returns the check digit or
117
+ # nil if a processing error occured.
118
+ # This method is a helper for compute_isbn10_check_digit and
119
+ # compute_isbn13_check_digit.
120
+ def ISBN_Tools.compute_check_digit(isbn_)
121
+ compute_isbn10_check_digit(isbn_) || compute_isbn13_check_digit(isbn_)
122
+ end
123
+
124
+ # Convert an ISBN-10 number to its equivalent ISBN-13 number. Returns the converted number or nil
125
+ # if the provided ISBN-10 number is nil or non valid.
126
+ def ISBN_Tools.isbn10_to_isbn13(isbn_)
127
+ isbn = cleanup(isbn_)
128
+ "978" + isbn[0..8] + compute_isbn13_check_digit("978" + isbn[0..8]) unless isbn.nil? or ! is_valid_isbn10?(isbn)
129
+ end
130
+
131
+ # Convert an ISBN-13 number to its equivalent ISBN-10 number. Returns the converted number or nil
132
+ # if the provided ISBN-13 number is nil or non valid. Please note that only ISBN-13 numbers starting
133
+ # with 978 can be converted.
134
+ def ISBN_Tools.isbn13_to_isbn10(isbn_)
135
+ isbn = cleanup(isbn_)
136
+ isbn[3..11] + compute_isbn10_check_digit(isbn[3..11]) unless isbn.nil? or ! is_valid_isbn13?(isbn) or ! isbn_.match(/^978.*/)
137
+ end
138
+
139
+ # Hyphenate a valid ISBN-10 number. Returns nil if the number is invalid or if the group range is
140
+ # unknown. Works only for groups 0,1 and 2.
141
+ def ISBN_Tools.hyphenate_isbn10(isbn_)
142
+ isbn = cleanup(isbn_)
143
+ group = isbn[0..0]
144
+ if RNG.has_key?(group) and is_valid_isbn10?(isbn)
145
+ RNG[group].each { |r| return isbn.sub(Regexp.new("(.{1})(.{#{r.last.length}})(.{#{8-r.last.length}})(.)"),'\1-\2-\3-\4') if r.member?(isbn[1..r.last.length]) }
146
+ end
147
+ end
148
+
149
+ # Hyphenate a valid ISBN-13 number. Returns nil if the number is invalid or if the group range is
150
+ # unknown. Works only for groups 0,1 and 2.
151
+ def ISBN_Tools.hyphenate_isbn13(isbn_)
152
+ isbn = cleanup(isbn_)
153
+ if is_valid_isbn13?(isbn)
154
+ group = isbn[3..3]
155
+ if RNG.has_key?(group)
156
+ RNG[group].each { |r| return isbn.sub(Regexp.new("(.{3})(.{1})(.{#{r.last.length}})(.{#{8-r.last.length}})(.)"),'\1-\2-\3-\4-\5') if r.member?(isbn[1..r.last.length]) }
157
+ end
158
+ end
159
+ end
160
+
161
+ # This method takes an ISBN then tries to hyphenate it as an ISBN 10 then an ISBN 13. A bit slower
162
+ # than calling the right one directly but saves you the length checking. Returns an hyphenated value
163
+ # or nil.
164
+ def ISBN_Tools.hyphenate(isbn_)
165
+ hyphenate_isbn10(isbn_) || hyphenate_isbn13(isbn_)
166
+ end
167
+
168
+ # Same as hyphenate() but alters the argument.
169
+ def ISBN_Tools.hyphenate!(isbn_)
170
+ isbn_.replace(hyphenate(isbn_))
171
+ end
172
+
173
+ end
@@ -0,0 +1,67 @@
1
+ require 'test_helper'
2
+
3
+ class BaseTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ CampusBooks.api_key = 'SmT8KuLkGvy7SexotRTB'
7
+ end
8
+
9
+ should "parse OK response and return just the response" do
10
+ expected_response = {
11
+ "status"=>"ok",
12
+ "version"=>"1",
13
+ "page" => {
14
+ "name"=>"bookinfo",
15
+ "rating"=>"5.0",
16
+ "category"=>nil,
17
+ "title"=>"The Ruby Programming Language",
18
+ "isbn10"=>"0596516177",
19
+ "tried_amazon"=>"1",
20
+ "author"=>"David Flanagan - Yukihiro Matsumoto",
21
+ "msrp"=>"39.99",
22
+ "rank"=>"19257",
23
+ "isbn13"=>"9780596516178",
24
+ "publisher"=>"O'Reilly Media, Inc.",
25
+ "pages"=>"446",
26
+ "edition"=>"Paperback",
27
+ "binding"=>"Paperback",
28
+ "published_date"=>"2008-01-25",
29
+ "image"=>"http://ecx.images-amazon.com/images/I/41n-JSlBHkL._SL75_.jpg"
30
+ },
31
+ "label"=>{
32
+ "name"=>"Scheduleman Tartan",
33
+ "plid"=>"1709"
34
+ }
35
+ }
36
+ CampusBooks::Base.expects(:get).once.returns({
37
+ "response" => expected_response
38
+ })
39
+ actual_response = CampusBooks::Base.get_response('/bookinfo', :query => { :isbn => '9780596516178' })
40
+ assert_equal expected_response, actual_response
41
+ end
42
+
43
+ should "raise an exception when an API error occurs" do
44
+ CampusBooks::Base.expects(:get).once.returns({
45
+ "response" => {
46
+ "status" => "error",
47
+ "errors" => {
48
+ "error" => [
49
+ "Permission Denied - Invalid or missing API Key",
50
+ "'isbn' parameter is required",
51
+ "'' is not a valid ISBN",
52
+ "Unable to create a book with isbn "
53
+ ]
54
+ },
55
+ "version" => "3"
56
+ }
57
+ })
58
+ exception = assert_raise CampusBooks::Error do
59
+ CampusBooks::Base.get_response('/bookinfo', :query => { :isbn => '' })
60
+ end
61
+ assert_equal %Q{4 errors occured while getting path '/bookinfo' with options {:query=>{:isbn=>""}}:
62
+ Permission Denied - Invalid or missing API Key
63
+ 'isbn' parameter is required
64
+ '' is not a valid ISBN
65
+ Unable to create a book with isbn }, exception.message
66
+ end
67
+ end
@@ -0,0 +1,100 @@
1
+ require 'test_helper'
2
+
3
+ class BookTest < Test::Unit::TestCase
4
+ VALID_ISBN13 = '9780596516178'
5
+ VALID_ISBN10 = '0596516177'
6
+
7
+ def setup
8
+ CampusBooks.api_key = 'SmT8KuLkGvy7SexotRTB' # 'AbC123dEFG4H5jkl6MNO'
9
+ end
10
+
11
+ should "store ISBN from constructor" do
12
+ mock_successful_request
13
+ book = CampusBooks::Book.find(VALID_ISBN13)
14
+ assert_equal VALID_ISBN13, book.isbn
15
+ end
16
+
17
+ should "convert ISBN10 to ISBN13" do
18
+ mock_successful_request
19
+ book = CampusBooks::Book.find(VALID_ISBN10)
20
+ assert_equal VALID_ISBN13, book.isbn
21
+ end
22
+
23
+ should "validate ISBN during construction" do
24
+ assert_nothing_raised do
25
+ mock_successful_request
26
+ CampusBooks::Book.find(VALID_ISBN10)
27
+ end
28
+ assert_raise ArgumentError, 'isbn is invalid' do
29
+ CampusBooks::Book.find('0-596-51617-8')
30
+ end
31
+ end
32
+
33
+ should "get valid values" do
34
+ mock_successful_request
35
+ book = CampusBooks::Book.find(VALID_ISBN13)
36
+ assert_equal VALID_ISBN10, book.isbn10
37
+ assert_equal VALID_ISBN13, book.isbn13
38
+ assert_equal VALID_ISBN13, book.isbn
39
+ assert_equal 'The Ruby Programming Language', book.title
40
+ assert_equal 'David Flanagan - Yukihiro Matsumoto', book.author
41
+ assert_equal 'Paperback', book.binding
42
+ assert_equal '39.99', book.msrp
43
+ assert_equal '446', book.pages
44
+ assert_equal "O'Reilly Media, Inc.", book.publisher
45
+ assert_equal Date.parse('2008-01-25'), book.published_date
46
+ assert_equal 'Paperback', book.edition
47
+ assert_equal 'Foo bar', book.description
48
+ end
49
+
50
+ should "include prices" do
51
+ book = CampusBooks::Book.find(VALID_ISBN13, :include => :prices)
52
+ end
53
+
54
+ private
55
+ def mock_successful_request
56
+ CampusBooks::Book.expects(:get).once.returns({
57
+ "response" => {
58
+ "status"=>"ok",
59
+ "version"=>"1",
60
+ "page" => {
61
+ "name"=>"bookinfo",
62
+ "rating"=>"5.0",
63
+ "category"=>nil,
64
+ "title"=>"The Ruby Programming Language",
65
+ "isbn10"=>"0596516177",
66
+ "tried_amazon"=>"1",
67
+ "author"=>"David Flanagan - Yukihiro Matsumoto",
68
+ "msrp"=>"39.99",
69
+ "rank"=>"19257",
70
+ "isbn13"=>"9780596516178",
71
+ "publisher"=>"O'Reilly Media, Inc.",
72
+ "pages"=>"446",
73
+ "edition"=>"Paperback",
74
+ "binding"=>"Paperback",
75
+ "published_date"=>"2008-01-25",
76
+ "image"=>"http://ecx.images-amazon.com/images/I/41n-JSlBHkL._SL75_.jpg",
77
+ "description" => 'Foo bar'
78
+ },
79
+ "label"=>{
80
+ "name"=>"Scheduleman Tartan",
81
+ "plid"=>"1709"
82
+ }
83
+ }
84
+ })
85
+ end
86
+
87
+ def mock_failed_request(isbn = '0-596-51617-8')
88
+ CampusBooks::Book.expects(:get).once.returns({
89
+ "response" => {
90
+ "status" => "error",
91
+ "errors" => {
92
+ "error" => [
93
+ "'#{isbn}' is not a valid ISBN"
94
+ ]
95
+ },
96
+ "version" => "3"
97
+ }
98
+ })
99
+ end
100
+ end
@@ -0,0 +1,41 @@
1
+ require 'test_helper'
2
+
3
+ class OfferTest < Test::Unit::TestCase
4
+
5
+ should "set params in constructor" do
6
+ offer = CampusBooks::Offer.new({
7
+ "merchant_id" => "24",
8
+ "price"=>"11.93",
9
+ "shipping_ground"=>"3.99",
10
+ "condition_id"=>"2",
11
+ "availability_id"=>"2",
12
+ "comments"=>"Good condition. Absolutely no highlighting or markings inside the books. Decent covers subject to prior use.",
13
+ "isbn10"=>"0596516177",
14
+ "total_price"=>"15.92",
15
+ "isbn13"=>"9780596516178",
16
+ "merchant_name"=>"Amazon Marketplace",
17
+ "availability_text"=>"Ready to ship",
18
+ "link"=>"http://partners.campusbooks.com/link.php?params=ABCDEF",
19
+ "condition_text"=>"Used"
20
+ })
21
+ #assert_equal '9780596516178', offer.isbn
22
+ assert_equal '9780596516178', offer.isbn13
23
+ assert_equal '0596516177', offer.isbn10
24
+ assert_equal '24', offer.merchant_id
25
+ assert_equal 'Amazon Marketplace', offer.merchant_name
26
+ assert_equal '11.93', offer.price
27
+ assert_equal '3.99', offer.shipping_ground
28
+ assert_equal '15.92', offer.total_price
29
+ assert_equal 'http://partners.campusbooks.com/link.php?params=ABCDEF', offer.link
30
+ assert_equal '2', offer.condition_id
31
+ assert_equal 'Used', offer.condition_text
32
+ assert_equal '2', offer.availability_id
33
+ assert_equal 'Ready to ship', offer.availability_text
34
+
35
+ # FIXME: Need an example of these
36
+ # assert_equal 'foo', offer.location
37
+ # assert_equal 'foo', offer.their_id
38
+ # assert_equal 'foo', offer.comments
39
+ end
40
+
41
+ end
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ begin
4
+ require 'shoulda'
5
+ rescue LoadError
6
+ puts "Shoulda not available. Install it with: sudo gem install thoughtbot-shoulda -s http://gems.github.com"
7
+ end
8
+ begin
9
+ require 'mocha'
10
+ rescue LoadError
11
+ puts "Mocha not available. Install it with: sudo gem install mocha"
12
+ end
13
+
14
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
15
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
16
+ require 'campusbooks'
17
+
18
+ class Test::Unit::TestCase
19
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mroch-campusbooks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Marshall Roch
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-27 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: httparty
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: A Ruby library for accessing the CampusBooks.com API
26
+ email: marshall@mroch.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.rdoc
33
+ - LICENSE
34
+ files:
35
+ - README.rdoc
36
+ - VERSION.yml
37
+ - lib/campusbooks
38
+ - lib/campusbooks/base.rb
39
+ - lib/campusbooks/book.rb
40
+ - lib/campusbooks/offer.rb
41
+ - lib/campusbooks.rb
42
+ - lib/isbn
43
+ - lib/isbn/LICENCE
44
+ - lib/isbn/README
45
+ - lib/isbn/tools.rb
46
+ - test/base_test.rb
47
+ - test/book_test.rb
48
+ - test/offer_test.rb
49
+ - test/test_helper.rb
50
+ - LICENSE
51
+ has_rdoc: true
52
+ homepage: http://github.com/mroch/campusbooks
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --inline-source
56
+ - --charset=UTF-8
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ requirements: []
72
+
73
+ rubyforge_project:
74
+ rubygems_version: 1.2.0
75
+ signing_key:
76
+ specification_version: 2
77
+ summary: CampusBooks API for Ruby
78
+ test_files: []
79
+