librarything-api 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.rdoc +29 -1
- data/VERSION +1 -1
- data/lib/librarything/author.rb +11 -0
- data/lib/librarything/resource.rb +31 -6
- data/lib/librarything/work.rb +15 -0
- data/spec/librarything/author_spec.rb +2 -2
- data/spec/librarything/work_spec.rb +1 -1
- metadata +1 -1
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
@@ -1,6 +1,34 @@
|
|
1
1
|
= librarything-api
|
2
2
|
|
3
|
-
|
3
|
+
This is a Ruby wrapper for the LibraryThing API.
|
4
|
+
|
5
|
+
== Accessing LibraryThing APIs
|
6
|
+
In order to use the LT Web Services API (and this library), you need to register for a developer key on librarything.com
|
7
|
+
|
8
|
+
* Sign into your LT account at http://www.librarything.com
|
9
|
+
* Go to http://www.librarything.com/services/keys.php and fill out the form to receive a developer key
|
10
|
+
* Documentation for the LT Web Services API can be found at http://www.librarything.com/services/webservices.php
|
11
|
+
|
12
|
+
== Using the Library
|
13
|
+
The gem uses HTTParty and Nokogiri for fetching and processing responses. Both of the gems must be installed.
|
14
|
+
|
15
|
+
$ gem install httparty nokogiri
|
16
|
+
|
17
|
+
$ irb -r rubygems
|
18
|
+
require 'librarything'
|
19
|
+
LibraryThing::DEVELOPER_KEY = 'abcdef0123456789abcdef'
|
20
|
+
strange = LibraryThing::Work.get(:name => 'Jonathan Strange')
|
21
|
+
strange['url']
|
22
|
+
# "http://www.librarything.com/work/1060"
|
23
|
+
|
24
|
+
== To Do
|
25
|
+
* Improve code documentation
|
26
|
+
|
27
|
+
== Other LT APIs to Add
|
28
|
+
|
29
|
+
* Helpers for accessing LT JSON APIs (Books, Works) (No server-side fetching allowed.)
|
30
|
+
* Helper for generating LT Covers URLs
|
31
|
+
* See: http://www.librarything.com/wiki/index.php/LibraryThing_APIs
|
4
32
|
|
5
33
|
== Note on Patches/Pull Requests
|
6
34
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
data/lib/librarything/author.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + "/shared_requires")
|
2
2
|
|
3
3
|
module LibraryThing
|
4
|
+
|
5
|
+
#
|
6
|
+
# Provides access to the LT Author API
|
7
|
+
# Authors can be loaded by id, authorcode, or name
|
8
|
+
#
|
9
|
+
# # author = LibraryThing::Author.get(:id => 216)
|
10
|
+
# # author = LibraryThing::Author.get(:authorcode => 'clarkesusanna')
|
11
|
+
# author = LibraryThing::Author.get(:name => 'Clarke, Susanna')
|
12
|
+
# author['url]
|
13
|
+
# => "http://www.librarything.com/author/216"
|
14
|
+
#
|
4
15
|
class Author < LibraryThing::Resource
|
5
16
|
get_method 'librarything.ck.getauthor'
|
6
17
|
end
|
@@ -1,19 +1,28 @@
|
|
1
|
-
require 'httparty'
|
2
|
-
|
3
1
|
module LibraryThing
|
4
2
|
|
3
|
+
# Helper class to wrap a Nokogiri node. It includes a simplified method for accessing DOM content.
|
5
4
|
class NodeWrapper
|
6
5
|
|
7
6
|
attr_reader :node
|
8
7
|
|
8
|
+
# Creates a new wrapped XML node
|
9
9
|
def initialize(node)
|
10
10
|
@node = node
|
11
11
|
end
|
12
12
|
|
13
|
+
# Returns the content of the node
|
13
14
|
def content
|
14
15
|
@node.content
|
15
16
|
end
|
16
17
|
|
18
|
+
# Extracts values from the node.
|
19
|
+
#
|
20
|
+
# * If the name matches the name of an attribute, the value of that attribute will be returned
|
21
|
+
# * If the name matches the name of a single child element, that element is returned.
|
22
|
+
# * If the matching child element only contains text data, the text data is returned.
|
23
|
+
# * If the matching child element is named xxxList, an array of the children of the element is returned
|
24
|
+
# * If there is more that one matching child element, they are returned as an array.
|
25
|
+
#
|
17
26
|
def [](name)
|
18
27
|
# Check for attributes first. Why? It works for the LT xml (for now).
|
19
28
|
if @node.attributes.has_key?(name)
|
@@ -21,12 +30,13 @@ module LibraryThing
|
|
21
30
|
end
|
22
31
|
|
23
32
|
# Find child elements with that name
|
24
|
-
children = @node.xpath("lt:#{name}")
|
33
|
+
children = @node.xpath("./lt:#{name}")
|
25
34
|
if children.size == 1
|
26
35
|
child = children.first
|
27
|
-
|
28
|
-
|
29
|
-
|
36
|
+
if self.text_element?(child)
|
37
|
+
return child.children.first.content
|
38
|
+
elsif child.name =~ /^[\w]*List$/
|
39
|
+
# LT-specific hack to simplify access to lists. Ill-advised?
|
30
40
|
return wrap_children(child.children)
|
31
41
|
else
|
32
42
|
return NodeWrapper.new(child)
|
@@ -40,11 +50,18 @@ module LibraryThing
|
|
40
50
|
|
41
51
|
protected
|
42
52
|
|
53
|
+
# Checks whether the node is an element with no attributes and a single text child
|
54
|
+
def text_element?(node)
|
55
|
+
node.element? && node.attributes.empty? && node.children.size == 1 && node.children.first.text?
|
56
|
+
end
|
57
|
+
|
58
|
+
# Creates and returns an array of wrapped nodes for each element in the NodeSet
|
43
59
|
def wrap_children(children)
|
44
60
|
children.map { |c| NodeWrapper.new(c) if c.element? }.compact
|
45
61
|
end
|
46
62
|
end
|
47
63
|
|
64
|
+
# Base class for fetching and parsing data from the LT WebServices APIs
|
48
65
|
class Resource
|
49
66
|
include HTTParty
|
50
67
|
base_uri 'http://www.librarything.com/services/rest/1.0'
|
@@ -53,12 +70,15 @@ module LibraryThing
|
|
53
70
|
attr_reader :document
|
54
71
|
attr_reader :item_node
|
55
72
|
|
73
|
+
# Accepts xml from an LT API request and creates a wrapper object. If there is a problem with the format of the
|
74
|
+
# xml, a LibraryThing::Error will be raised.
|
56
75
|
def initialize(xml)
|
57
76
|
@xml = xml
|
58
77
|
@document = self.parse_response(@xml)
|
59
78
|
@item_node = self.find_item_node(@document)
|
60
79
|
end
|
61
80
|
|
81
|
+
# See: LibraryThing::NodeWrapper#[](name)
|
62
82
|
def [](name)
|
63
83
|
@item_node[name]
|
64
84
|
end
|
@@ -95,6 +115,9 @@ module LibraryThing
|
|
95
115
|
end
|
96
116
|
|
97
117
|
class << self
|
118
|
+
|
119
|
+
# Gets or sets the method name that will be passed to the LT web service.
|
120
|
+
# Generally, this will be specified in a sub-class.
|
98
121
|
def get_method(method_name = nil)
|
99
122
|
if method_name
|
100
123
|
@get_method = method_name
|
@@ -105,6 +128,8 @@ module LibraryThing
|
|
105
128
|
end
|
106
129
|
end
|
107
130
|
|
131
|
+
# Accepts a hash of query params, and generates a request to the LT API. Returns a wrapped response object. If
|
132
|
+
# there is a problem with the request, a LibraryThing::Error will be raised.
|
108
133
|
def get(query)
|
109
134
|
raise LibraryThing::Error.new("Missing developer key. Please define LibraryThing::DEVELOPER_KEY") unless defined?(LibraryThing::DEVELOPER_KEY)
|
110
135
|
|
data/lib/librarything/work.rb
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + "/shared_requires")
|
2
2
|
|
3
3
|
module LibraryThing
|
4
|
+
|
5
|
+
#
|
6
|
+
# Provides access to the LT Work API
|
7
|
+
# Works can be loaded by id, isbn, lccn, oclc or name
|
8
|
+
#
|
9
|
+
# # work = LibraryThing::Work.get(:id => 1060)
|
10
|
+
# # work = LibraryThing::Work.get(:isbn => '0765356155')
|
11
|
+
# # work = LibraryThing::Work.get(:lccn => 'PR6103.L375J65')
|
12
|
+
# # work = LibraryThing::Work.get(:oclc => '185392674')
|
13
|
+
# work = LibraryThing::Work.get(:name => 'Jonathon Strange')
|
14
|
+
# work['url]
|
15
|
+
# => "http://www.librarything.com/work/1060"
|
16
|
+
#
|
17
|
+
# Note: lccn amd oclc access wasn't working while I was testing. (13-Mar-2010)
|
18
|
+
#
|
4
19
|
class Work < LibraryThing::Resource
|
5
20
|
get_method 'librarything.ck.getwork'
|
6
21
|
end
|
@@ -44,13 +44,13 @@ describe LibraryThing::Author do
|
|
44
44
|
def check_author_response(author)
|
45
45
|
author.should_not be_nil
|
46
46
|
author['id'].should == '216'
|
47
|
-
author['url'].
|
47
|
+
author['url'].should == 'http://www.librarything.com/author/216'
|
48
48
|
|
49
49
|
author_element = author['author']
|
50
50
|
author_element.should_not be_nil
|
51
51
|
author_element['id'].should == '216'
|
52
52
|
author_element['authorcode'].should == 'clarkesusanna'
|
53
|
-
author_element['name'].
|
53
|
+
author_element['name'].should == 'Susanna Clarke'
|
54
54
|
|
55
55
|
field_list = author['commonknowledge']['fieldList']
|
56
56
|
field_list.size.should == 8
|
@@ -44,7 +44,7 @@ describe LibraryThing::Work do
|
|
44
44
|
def check_work_response(work)
|
45
45
|
work.should_not be_nil
|
46
46
|
work['id'].should == '1060'
|
47
|
-
work['url'].
|
47
|
+
work['url'].should == 'http://www.librarything.com/work/1060'
|
48
48
|
|
49
49
|
author = work['author']
|
50
50
|
author.should_not be_nil
|