dnz-client 0.0.9 → 0.1.0
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.
- data/History.txt +5 -0
- data/lib/dnz.rb +1 -1
- data/lib/dnz/client.rb +12 -0
- data/lib/dnz/facet.rb +36 -2
- data/lib/dnz/results.rb +5 -1
- data/spec/dnz/client_spec.rb +153 -116
- metadata +3 -3
data/History.txt
CHANGED
data/lib/dnz.rb
CHANGED
data/lib/dnz/client.rb
CHANGED
@@ -15,6 +15,18 @@ module DNZ
|
|
15
15
|
# Copyright:: Copyright (c) 2009 Boost New Media
|
16
16
|
# License:: MIT
|
17
17
|
class Client
|
18
|
+
cattr_accessor :connection
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def connect(*args)
|
22
|
+
self.connection = self.new(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(method, *args, &block)
|
26
|
+
self.connection.send(method, *args, &block)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
18
30
|
# The dnz API key
|
19
31
|
attr_reader :api_key
|
20
32
|
# The base URL (defaults to http://api.digitalnz.org)
|
data/lib/dnz/facet.rb
CHANGED
@@ -1,12 +1,43 @@
|
|
1
1
|
require 'dnz/attributes'
|
2
2
|
|
3
3
|
module DNZ
|
4
|
+
# A facet retrieved from DigitalNZ search results. The facet has a name and an array of
|
5
|
+
# FacetValue objects.
|
4
6
|
class Facet
|
7
|
+
# The facet name
|
5
8
|
attr_reader :name
|
6
|
-
|
9
|
+
|
10
|
+
# The search that orginally ran to produce this facet
|
7
11
|
attr_reader :search
|
8
12
|
|
9
13
|
include Enumerable
|
14
|
+
|
15
|
+
# Find a facet and return it. This is a convienence method for running
|
16
|
+
# Client.search('search', :facets => facet).facets[facet].
|
17
|
+
#
|
18
|
+
# * <tt>facet</tt> - The name of the facet.
|
19
|
+
# * <tt>search_text</tt> - Optional search text. Defaults to everything (*:*).
|
20
|
+
# * <tt>num_results</tt> - Optional maximum number of facet values to return in the
|
21
|
+
# facet. This defaults to -1 which means no limit.
|
22
|
+
def self.find(facet, search_text = '*:*', num_results = -1)
|
23
|
+
options = {:facets => facet, :facet_num_results => num_results, :num_results => 0}
|
24
|
+
Client.search(search_text, options).facets[facet]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Find related facet values. This is a convienence method for running
|
28
|
+
# Client.search('parent_facet:value', :facets => facet).facets[facet]. It will
|
29
|
+
# return the facet and facet values for results scoped to another facet.
|
30
|
+
#
|
31
|
+
# * <tt>facet</tt> - The name of the facet.
|
32
|
+
# * <tt>parent_facet</tt> - The name of the facet to scope results to.
|
33
|
+
# * <tt>value</tt> - The facet value to scope the results to.
|
34
|
+
# * <tt>search_text</tt> - Optional search text. Defaults to everything (*:*).
|
35
|
+
# * <tt>num_results</tt> - Optional maximum number of facet values to return in the
|
36
|
+
# facet. This defaults to -1 which means no limit.
|
37
|
+
def self.find_related(facet, parent_facet, value, search_text = '*:*', num_results = -1)
|
38
|
+
search_text = [search_text, '%s:"%s"' % [parent_facet, value]].join(' AND ')
|
39
|
+
self.find(facet, search_text, num_results)
|
40
|
+
end
|
10
41
|
|
11
42
|
def initialize(client, search, doc)
|
12
43
|
@name = doc.xpath('facet-field').text
|
@@ -19,14 +50,17 @@ module DNZ
|
|
19
50
|
end
|
20
51
|
end
|
21
52
|
|
53
|
+
# An array of FacetValue objects
|
22
54
|
def values
|
23
55
|
@values.values
|
24
56
|
end
|
25
|
-
|
57
|
+
|
58
|
+
# Retrieve a FacetValue by name
|
26
59
|
def [](index)
|
27
60
|
@values[index]
|
28
61
|
end
|
29
62
|
|
63
|
+
# Enumerate the FacetValue objects
|
30
64
|
def each
|
31
65
|
@values.each {|key, value| yield value }
|
32
66
|
end
|
data/lib/dnz/results.rb
CHANGED
@@ -54,6 +54,10 @@ module DNZ
|
|
54
54
|
def pages
|
55
55
|
num_results_requested < result_count ? (result_count.to_f / num_results_requested).ceil : 1
|
56
56
|
end
|
57
|
+
|
58
|
+
def per_page
|
59
|
+
num_results_requested < 1 ? 1 : num_results_requested
|
60
|
+
end
|
57
61
|
|
58
62
|
# The number of results requested via the :num_results option (see <tt>Client.search</tt>).
|
59
63
|
def num_results_requested
|
@@ -76,7 +80,7 @@ module DNZ
|
|
76
80
|
|
77
81
|
# Replace the results array with a paginated array
|
78
82
|
def paginate_results
|
79
|
-
@results = WillPaginate::Collection.create(self.page,
|
83
|
+
@results = WillPaginate::Collection.create(self.page, per_page, self.result_count) do |pager|
|
80
84
|
pager.replace @results
|
81
85
|
end
|
82
86
|
end
|
data/spec/dnz/client_spec.rb
CHANGED
@@ -4,151 +4,188 @@ require 'dnz/client'
|
|
4
4
|
include DNZ
|
5
5
|
|
6
6
|
describe Client do
|
7
|
-
|
8
|
-
|
9
|
-
@client.stub!(:open) # make sure open is never called
|
10
|
-
@search = mock(:search)
|
11
|
-
DNZ::Search.stub!(:new).and_return(@search)
|
12
|
-
end
|
13
|
-
|
14
|
-
describe 'APIs' do
|
15
|
-
describe 'v1' do
|
7
|
+
describe 'class' do
|
8
|
+
describe '::connect' do
|
16
9
|
before do
|
17
|
-
@
|
18
|
-
|
19
|
-
@client.stub!(:open) # make sure open is never called
|
10
|
+
@mock_client = mock(:client)
|
11
|
+
Client.stub!(:new).and_return(@mock_client)
|
20
12
|
end
|
21
13
|
|
22
|
-
|
23
|
-
|
24
|
-
it "should allow #{option}" do
|
25
|
-
lambda do
|
26
|
-
@client.send(:fetch, :search, {option => "test"})
|
27
|
-
end.should_not raise_error(ArgumentError)
|
28
|
-
end
|
29
|
-
end
|
14
|
+
it 'should have no connection to begin with' do
|
15
|
+
Client.connection.should be_nil
|
30
16
|
end
|
31
17
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
it "should allow #{option}" do
|
41
|
-
lambda do
|
42
|
-
@client.send(:fetch, :custom_search, {:custom_search => "test", option => "test"})
|
43
|
-
end.should_not raise_error(ArgumentError)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
[:facets,:facet_num_results,:facet_start].each do |option|
|
47
|
-
it "should not allow #{option}" do
|
48
|
-
lambda do
|
49
|
-
@client.send(:fetch, :custom_search, {:custom_search => "test", option => "test"})
|
50
|
-
end.should raise_error(ArgumentError)
|
51
|
-
end
|
52
|
-
end
|
18
|
+
it 'should create a new client' do
|
19
|
+
Client.should_receive(:new).with('abc').and_return(@mock_client)
|
20
|
+
Client.connect('abc').should == @mock_client
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should assign the new client to connection' do
|
24
|
+
Client.connect('abc')
|
25
|
+
Client.connection.should == @mock_client
|
53
26
|
end
|
54
27
|
end
|
55
28
|
|
56
|
-
describe '
|
29
|
+
describe 'proxy methods' do
|
57
30
|
before do
|
58
|
-
@
|
59
|
-
|
60
|
-
@client.stub!(:open) # make sure open is never called
|
31
|
+
@mock_client = mock(:client)
|
32
|
+
Client.stub!(:connection).and_return(@mock_client)
|
61
33
|
end
|
62
34
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
lambda do
|
67
|
-
@client.send(:fetch, :search, {})
|
68
|
-
end.should_not raise_error(ArgumentError)
|
69
|
-
end
|
70
|
-
end
|
35
|
+
it 'should pass methods to client instance' do
|
36
|
+
@mock_client.should_receive(:test_method).with('test_argument')
|
37
|
+
Client.test_method('test_argument')
|
71
38
|
end
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'instance' do
|
43
|
+
before(:each) do
|
44
|
+
@client = Client.new('abc')
|
45
|
+
@client.stub!(:open) # make sure open is never called
|
46
|
+
@search = mock(:search)
|
47
|
+
DNZ::Search.stub!(:new).and_return(@search)
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'APIs' do
|
51
|
+
describe 'v1' do
|
52
|
+
before do
|
53
|
+
@version = 'v1'
|
54
|
+
@client = Client.new('abc', @version)
|
55
|
+
@client.stub!(:open) # make sure open is never called
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'search' do
|
59
|
+
[:search_text,:api_key,:num_results,:start,:sort,:direction,:facets,:facet_num_results,:facet_start].each do |option|
|
60
|
+
it "should allow #{option}" do
|
61
|
+
lambda do
|
62
|
+
@client.send(:fetch, :search, {option => "test"})
|
63
|
+
end.should_not raise_error(ArgumentError)
|
64
|
+
end
|
65
|
+
end
|
78
66
|
end
|
79
|
-
|
80
|
-
|
81
|
-
it
|
67
|
+
|
68
|
+
describe 'custom_search' do
|
69
|
+
it 'should require custom_search' do
|
82
70
|
lambda do
|
83
|
-
@client.send(:fetch, :custom_search, {
|
84
|
-
end.
|
71
|
+
@client.send(:fetch, :custom_search, {})
|
72
|
+
end.should raise_error(ArgumentError, "Required argument missing: custom_search")
|
85
73
|
end
|
74
|
+
|
75
|
+
[:search_text,:api_key,:num_results,:start,:sort,:direction].each do |option|
|
76
|
+
it "should allow #{option}" do
|
77
|
+
lambda do
|
78
|
+
@client.send(:fetch, :custom_search, {:custom_search => "test", option => "test"})
|
79
|
+
end.should_not raise_error(ArgumentError)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
[:facets,:facet_num_results,:facet_start].each do |option|
|
83
|
+
it "should not allow #{option}" do
|
84
|
+
lambda do
|
85
|
+
@client.send(:fetch, :custom_search, {:custom_search => "test", option => "test"})
|
86
|
+
end.should raise_error(ArgumentError)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe 'v2' do
|
93
|
+
before do
|
94
|
+
@version = 'v2'
|
95
|
+
@client = Client.new('abc', @version)
|
96
|
+
@client.stub!(:open) # make sure open is never called
|
97
|
+
end
|
98
|
+
|
99
|
+
describe 'search' do
|
100
|
+
[:search_text,:api_key,:num_results,:start,:sort,:direction,:facets,:facet_num_results,:facet_start].each do |option|
|
101
|
+
it "should allow #{option}" do
|
102
|
+
lambda do
|
103
|
+
@client.send(:fetch, :search, {})
|
104
|
+
end.should_not raise_error(ArgumentError)
|
105
|
+
end
|
106
|
+
end
|
86
107
|
end
|
87
|
-
|
88
|
-
|
108
|
+
|
109
|
+
describe 'custom_search' do
|
110
|
+
it 'should require custom_search' do
|
89
111
|
lambda do
|
90
|
-
@client.send(:fetch, :custom_search, {
|
91
|
-
end.
|
112
|
+
@client.send(:fetch, :custom_search, {})
|
113
|
+
end.should raise_error(ArgumentError, "Required argument missing: custom_search")
|
114
|
+
end
|
115
|
+
|
116
|
+
[:search_text,:api_key,:num_results,:start,:sort,:direction].each do |option|
|
117
|
+
it "should allow #{option}" do
|
118
|
+
lambda do
|
119
|
+
@client.send(:fetch, :custom_search, {:custom_search => "test", option => "test"})
|
120
|
+
end.should_not raise_error(ArgumentError)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
[:facets,:facet_num_results,:facet_start].each do |option|
|
124
|
+
it "should allow #{option}" do
|
125
|
+
lambda do
|
126
|
+
@client.send(:fetch, :custom_search, {:custom_search => "test", option => "test"})
|
127
|
+
end.should_not raise_error(ArgumentError)
|
128
|
+
end
|
92
129
|
end
|
93
130
|
end
|
94
131
|
end
|
95
132
|
end
|
96
|
-
end
|
97
|
-
|
98
133
|
|
99
|
-
describe '#search' do
|
100
|
-
it 'should create a new search object and return it' do
|
101
|
-
@client.search('*:*').should be(@search)
|
102
|
-
end
|
103
|
-
end
|
104
134
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
end.should raise_error(ArgumentError)
|
135
|
+
describe '#search' do
|
136
|
+
it 'should create a new search object and return it' do
|
137
|
+
@client.search('*:*').should be(@search)
|
138
|
+
end
|
110
139
|
end
|
111
140
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
141
|
+
describe '#fetch' do
|
142
|
+
it 'should raise an error an invalid option is set' do
|
143
|
+
lambda do
|
144
|
+
@client.fetch(:search, :blahblah => 'dlfkgj')
|
145
|
+
end.should raise_error(ArgumentError)
|
117
146
|
end
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
147
|
+
|
148
|
+
it 'should call open with query string arguments' do
|
149
|
+
@client.should_receive(:open).with do |url|
|
150
|
+
url.should include('http://api.digitalnz.org/records/v1.xml/?')
|
151
|
+
url.should include('api_key=abc')
|
152
|
+
url.should include('search_text=%2A%3A%2A')
|
153
|
+
end
|
124
154
|
@client.fetch(:search, :search_text => '*:*')
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
describe '#categories' do
|
130
|
-
before do
|
131
|
-
@categories = mock(:categories)
|
132
|
-
@category = mock(:facet)
|
133
|
-
@category.stub!(:values).and_return(@categories)
|
134
|
-
@facets = mock(:facets)
|
135
|
-
@facets.stub!(:[]).with('category').and_return(@category)
|
136
|
-
@search.stub!(:facets).and_return(@facets)
|
137
|
-
@client.stub!(:search).and_return(@search)
|
138
|
-
end
|
139
|
-
|
140
|
-
it 'should run a search for categories facet' do
|
141
|
-
@client.should_receive(:search).with('*:*', :facets => 'category', :facet_num_results => 100).and_return(@search)
|
142
|
-
@client.categories
|
143
|
-
end
|
155
|
+
end
|
144
156
|
|
145
|
-
|
146
|
-
|
147
|
-
|
157
|
+
it 'should raise an InvalidApiKey error if the status is 401' do
|
158
|
+
@client.should_receive(:open).and_raise(OpenURI::HTTPError.new('401 Unauthorized', nil))
|
159
|
+
lambda do
|
160
|
+
@client.fetch(:search, :search_text => '*:*')
|
161
|
+
end.should raise_error(InvalidApiKeyError)
|
162
|
+
end
|
148
163
|
end
|
149
|
-
|
150
|
-
|
151
|
-
|
164
|
+
|
165
|
+
describe '#categories' do
|
166
|
+
before do
|
167
|
+
@categories = mock(:categories)
|
168
|
+
@category = mock(:facet)
|
169
|
+
@category.stub!(:values).and_return(@categories)
|
170
|
+
@facets = mock(:facets)
|
171
|
+
@facets.stub!(:[]).with('category').and_return(@category)
|
172
|
+
@search.stub!(:facets).and_return(@facets)
|
173
|
+
@client.stub!(:search).and_return(@search)
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'should run a search for categories facet' do
|
177
|
+
@client.should_receive(:search).with('*:*', :facets => 'category', :facet_num_results => 100).and_return(@search)
|
178
|
+
@client.categories
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should run a search with custom_search' do
|
182
|
+
@client.should_receive(:search).with('*:*', :facets => 'category', :facet_num_results => 100, :custom_search => 'test').and_return(@search)
|
183
|
+
@client.categories(:custom_search => 'test')
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'should return the categories facet' do
|
187
|
+
@client.categories.should == @categories
|
188
|
+
end
|
152
189
|
end
|
153
190
|
end
|
154
191
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
|
9
|
-
version: 0.0.9
|
9
|
+
version: 0.1.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jeremy Wells
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-05-13 00:00:00 +12:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|