oai 0.4.0 → 1.0.0.beta1
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 +5 -5
- data/README.md +36 -10
- data/Rakefile +19 -52
- data/lib/oai/client.rb +3 -3
- data/lib/oai/provider.rb +47 -9
- data/lib/oai/provider/model.rb +17 -17
- data/lib/oai/provider/model/activerecord_caching_wrapper.rb +9 -10
- data/lib/oai/provider/model/activerecord_wrapper.rb +16 -9
- data/lib/oai/provider/response.rb +1 -1
- data/lib/oai/provider/response/record_response.rb +2 -1
- data/test/activerecord_provider/config/connection.rb +18 -1
- data/test/activerecord_provider/database/0001_oaipmh_tables.rb +1 -1
- data/test/activerecord_provider/helpers/providers.rb +16 -0
- data/test/activerecord_provider/models/exclusive_set_dc_field.rb +1 -1
- data/test/activerecord_provider/tc_ar_provider.rb +30 -6
- data/test/activerecord_provider/tc_ar_sets_provider.rb +1 -1
- data/test/activerecord_provider/tc_caching_paging_provider.rb +1 -1
- data/test/activerecord_provider/tc_simple_paging_provider.rb +1 -1
- data/test/activerecord_provider/{test_helper.rb → test_helper_ar_provider.rb} +0 -7
- data/test/client/helpers/provider.rb +8 -8
- data/test/client/tc_exception.rb +4 -4
- data/test/client/tc_get_record.rb +5 -6
- data/test/client/tc_http_client.rb +1 -1
- data/test/client/tc_identify.rb +1 -1
- data/test/client/tc_libxml.rb +4 -4
- data/test/client/tc_list_identifiers.rb +1 -1
- data/test/client/tc_list_metadata_formats.rb +3 -3
- data/test/client/tc_list_records.rb +1 -1
- data/test/client/tc_list_sets.rb +1 -1
- data/test/client/tc_low_resolution_dates.rb +5 -5
- data/test/client/tc_utf8_escaping.rb +2 -2
- data/test/client/tc_xpath.rb +2 -2
- data/test/client/test_helper_client.rb +5 -0
- data/test/provider/tc_exceptions.rb +8 -6
- data/test/provider/tc_functional_tokens.rb +2 -2
- data/test/provider/tc_provider.rb +1 -1
- data/test/provider/tc_resumption_tokens.rb +2 -2
- data/test/provider/tc_simple_provider.rb +8 -8
- data/test/provider/{test_helper.rb → test_helper_provider.rb} +0 -7
- metadata +42 -10
- data/test/client/test_helper.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a21ec21fadefca115987b42ef91f851406c9893ca6f0efc4bd2a1dfa71282514
|
4
|
+
data.tar.gz: c3ef94d3b809c4cba4d3ea0a02cfc9cc2db370eadc86f06ea3d259b0e4f8571b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6eba80e5c7c3b2b1ea7512b316796217fbeb45ebf11ec33b22d61790587b84f8a4c78db669eec9bbc38980c6b8a33dd59de3b3f4d5861010aea0c3f737c3c02
|
7
|
+
data.tar.gz: bb188698b9e5e5eddb1df8c87db491e312396547e3a8179ee1d4720c96aa4567391e602b93c4f2c33aa28c33134dda585035884e1c0a5f333b34b02f8071ed35
|
data/README.md
CHANGED
@@ -1,17 +1,21 @@
|
|
1
1
|
ruby-oai
|
2
2
|
========
|
3
3
|
|
4
|
+
[](https://travis-ci.org/code4lib/ruby-oai)
|
5
|
+
|
6
|
+
[](https://badge.fury.io/rb/oai)
|
7
|
+
|
4
8
|
ruby-oai is a Open Archives Protocol for Metadata Harvesting (OAI-PMH)
|
5
|
-
library for Ruby. [OAI-PMH](http://openarchives.org) is a somewhat
|
6
|
-
archaic protocol for sharing metadata between digital library repositories.
|
9
|
+
library for Ruby. [OAI-PMH](http://openarchives.org) is a somewhat
|
10
|
+
archaic protocol for sharing metadata between digital library repositories.
|
7
11
|
If you are looking to share metadata on the web you are probably better off
|
8
|
-
using a feed format like [RSS](http://www.rssboard.org/rss-specification) or
|
9
|
-
[Atom](http://www.atomenabled.org/). If have to work with a backwards
|
10
|
-
digital repository that only offers OAI-PMH access then ruby-oai is your
|
12
|
+
using a feed format like [RSS](http://www.rssboard.org/rss-specification) or
|
13
|
+
[Atom](http://www.atomenabled.org/). If have to work with a backwards
|
14
|
+
digital repository that only offers OAI-PMH access then ruby-oai is your
|
11
15
|
friend.
|
12
16
|
|
13
|
-
The [OAI-PMH](http://openarchives.org) spec defines six verbs
|
14
|
-
(`Identify`, `ListIdentifiers`, `ListRecords`,
|
17
|
+
The [OAI-PMH](http://openarchives.org) spec defines six verbs
|
18
|
+
(`Identify`, `ListIdentifiers`, `ListRecords`,
|
15
19
|
`GetRecords`, `ListSets`, `ListMetadataFormat`) used for discovery and sharing of
|
16
20
|
metadata.
|
17
21
|
|
@@ -21,7 +25,7 @@ a interactive harvesting shell.
|
|
21
25
|
Client
|
22
26
|
------
|
23
27
|
|
24
|
-
The OAI client library is used for harvesting metadata from repositories.
|
28
|
+
The OAI client library is used for harvesting metadata from repositories.
|
25
29
|
For example to initiate a ListRecords request to pubmed you can:
|
26
30
|
|
27
31
|
```ruby
|
@@ -29,7 +33,7 @@ For example to initiate a ListRecords request to pubmed you can:
|
|
29
33
|
client = OAI::Client.new 'http://www.pubmedcentral.gov/oai/oai.cgi', :headers => { "From" => "oai@example.com" }
|
30
34
|
response = client.list_records
|
31
35
|
# Get the first page of records
|
32
|
-
response.each do |record|
|
36
|
+
response.each do |record|
|
33
37
|
puts record.metadata
|
34
38
|
end
|
35
39
|
# Get the second page of records
|
@@ -60,7 +64,7 @@ The OAI provider library handles serving local content to other clients. Here's
|
|
60
64
|
end
|
61
65
|
```
|
62
66
|
|
63
|
-
See
|
67
|
+
See comment docs at top of [OAI::Provider](./lib/oai/provider.rb) for more details, including discussion of the `OAI::Provider::ActiveRecordWrapper` class for quich setup of an OAI provider for an ActiveRecord model class (single database table)
|
64
68
|
|
65
69
|
Interactive Harvester
|
66
70
|
---------------------
|
@@ -81,6 +85,28 @@ Alternately it can be installed globally using RubyGems:
|
|
81
85
|
|
82
86
|
$ gem install oai
|
83
87
|
|
88
|
+
Running tests
|
89
|
+
-------------
|
90
|
+
|
91
|
+
Tests are with Test::Unit, in a somewhat archaic/legacy style. Test setup especially is not how we would do things today. Run all tests with:
|
92
|
+
|
93
|
+
$ bundle exec rake test
|
94
|
+
|
95
|
+
There are also convenience tasks to run subsets of tests.
|
96
|
+
|
97
|
+
We use [appraisal](https://github.com/thoughtbot/appraisal) to test ActiveRecord-related functionality under multiple versions of ActiveRecord. While the above commands will test with latest ActiveRecord (allowed in our .gemspec development dependency), you can test under a particular version defined in the [Appraisals](./Appraisals) file like so:
|
98
|
+
|
99
|
+
$ bundle exec appraisal rails-52 rake test
|
100
|
+
$ bundle exec appraisal rails-60 rake test
|
101
|
+
|
102
|
+
If you run into trouble with appraisal's gemfiles getting out of date and bundler complaining,
|
103
|
+
try:
|
104
|
+
|
105
|
+
$ bundle exec appraisal clean
|
106
|
+
$ appraisal generate
|
107
|
+
|
108
|
+
That may make changes to appraisal gemfiles that you should commit to repo.
|
109
|
+
|
84
110
|
License
|
85
111
|
-------
|
86
112
|
|
data/Rakefile
CHANGED
@@ -14,73 +14,40 @@ require 'yard'
|
|
14
14
|
|
15
15
|
task :default => ["test", "yard"]
|
16
16
|
|
17
|
-
|
17
|
+
Rake::TestTask.new('test') do |t|
|
18
|
+
t.description = "Run all Test::Unit tests"
|
18
19
|
|
20
|
+
t.libs << ['lib', 'test/client', 'test/provider', 'test/activerecord_provider']
|
21
|
+
|
22
|
+
t.pattern = 'test/{client,provider,activerecord_provider}/tc_*.rb'
|
23
|
+
#t.verbose = true
|
24
|
+
t.warning = false
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
# To run just subsets of tests
|
19
29
|
namespace :test do
|
20
30
|
Rake::TestTask.new('client') do |t|
|
21
31
|
t.libs << ['lib', 'test/client']
|
22
32
|
t.pattern = 'test/client/tc_*.rb'
|
23
|
-
t.verbose = true
|
33
|
+
#t.verbose = true
|
34
|
+
t.warning = false
|
24
35
|
end
|
25
36
|
|
26
37
|
Rake::TestTask.new('provider') do |t|
|
27
38
|
t.libs << ['lib', 'test/provider']
|
28
39
|
t.pattern = 'test/provider/tc_*.rb'
|
29
|
-
t.verbose = true
|
40
|
+
#t.verbose = true
|
41
|
+
t.warning = false
|
30
42
|
end
|
31
43
|
|
32
|
-
desc "Active Record base Provider Tests"
|
33
44
|
Rake::TestTask.new('activerecord_provider') do |t|
|
45
|
+
t.description = "Active Record base Provider Tests"
|
46
|
+
|
34
47
|
t.libs << ['lib', 'test/activerecord_provider']
|
35
48
|
t.pattern = 'test/activerecord_provider/tc_*.rb'
|
36
|
-
t.verbose = true
|
37
|
-
|
38
|
-
|
39
|
-
desc 'Measures test coverage'
|
40
|
-
# borrowed from here: http://clarkware.com/cgi/blosxom/2007/01/05#RcovRakeTask
|
41
|
-
task :coverage do
|
42
|
-
rm_f "coverage"
|
43
|
-
rm_f "coverage.data"
|
44
|
-
if RUBY_VERSION =~ /^1.8/
|
45
|
-
Rake::Task['rcov:client'].invoke
|
46
|
-
Rake::Task['rcov:provider'].invoke
|
47
|
-
Rake::Task['rcov:activerecord_provider'].invoke
|
48
|
-
else
|
49
|
-
ENV['COVERAGE'] = 'true'
|
50
|
-
Rake::Task['test:client'].invoke
|
51
|
-
Rake::Task['test:provider'].invoke
|
52
|
-
Rake::Task['test:activerecord_provider'].invoke
|
53
|
-
end
|
54
|
-
|
55
|
-
system("open coverage/index.html") if (PLATFORM['darwin'] if Kernel.const_defined? :PLATFORM) || (RUBY_PLATFORM =~ /darwin/ if Kernel.const_defined? :RUBY_PLATFORM)
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
if RUBY_VERSION =~ /^1.8/
|
61
|
-
require 'rcov/rcovtask'
|
62
|
-
namespace :rcov do
|
63
|
-
Rcov::RcovTask.new do |t|
|
64
|
-
t.name = 'client'
|
65
|
-
t.libs << ['lib', 'test/client']
|
66
|
-
t.pattern = 'test/client/tc_*.rb'
|
67
|
-
t.verbose = true
|
68
|
-
t.rcov_opts = ['--aggregate coverage.data', '--text-summary']
|
69
|
-
end
|
70
|
-
|
71
|
-
Rcov::RcovTask.new('provider') do |t|
|
72
|
-
t.libs << ['lib', 'test/provider']
|
73
|
-
t.pattern = 'test/provider/tc_*.rb'
|
74
|
-
t.verbose = true
|
75
|
-
t.rcov_opts = ['--aggregate coverage.data', '--text-summary']
|
76
|
-
end
|
77
|
-
|
78
|
-
Rcov::RcovTask.new('activerecord_provider') do |t|
|
79
|
-
t.libs << ['lib', 'test/activerecord_provider']
|
80
|
-
t.pattern = 'test/activerecord_provider/tc_*.rb'
|
81
|
-
t.verbose = true
|
82
|
-
t.rcov_opts = ['--aggregate coverage.data', '--text-summary']
|
83
|
-
end
|
49
|
+
#t.verbose = true
|
50
|
+
t.warning = false
|
84
51
|
end
|
85
52
|
end
|
86
53
|
|
data/lib/oai/client.rb
CHANGED
@@ -92,11 +92,11 @@ module OAI
|
|
92
92
|
@http_client = options.fetch(:http) do
|
93
93
|
Faraday.new(:url => @base.clone) do |builder|
|
94
94
|
follow_redirects = options.fetch(:redirects, true)
|
95
|
-
if follow_redirects
|
96
|
-
count = follow_redirects.is_a?(Fixnum) ? follow_redirects : 5
|
95
|
+
follow_redirects = 5 if follow_redirects == true
|
97
96
|
|
97
|
+
if follow_redirects
|
98
98
|
require 'faraday_middleware'
|
99
|
-
builder.response :follow_redirects, :limit =>
|
99
|
+
builder.response :follow_redirects, :limit => follow_redirects.to_i
|
100
100
|
end
|
101
101
|
builder.adapter :net_http
|
102
102
|
end
|
data/lib/oai/provider.rb
CHANGED
@@ -58,7 +58,9 @@ end
|
|
58
58
|
# repository_url 'http://localhost/provider'
|
59
59
|
# record_prefix 'oai:localhost'
|
60
60
|
# admin_email 'root@localhost'
|
61
|
-
#
|
61
|
+
# # record_prefix will be automatically prepended to sample_id, so in this
|
62
|
+
# # case it becomes: oai:localhost:13900
|
63
|
+
# sample_id '13900'
|
62
64
|
# source_model MyModel.new
|
63
65
|
# end
|
64
66
|
# ```
|
@@ -107,7 +109,7 @@ end
|
|
107
109
|
# record_prefix 'oai:blog'
|
108
110
|
# admin_email 'root@localhost'
|
109
111
|
# source_model OAI::Provider::ActiveRecordWrapper.new(Post)
|
110
|
-
#
|
112
|
+
# sample_id '13900' # record prefix used, so becomes oai:blog:13900
|
111
113
|
# end
|
112
114
|
# ```
|
113
115
|
#
|
@@ -116,15 +118,25 @@ end
|
|
116
118
|
# ```ruby
|
117
119
|
# class OaiController < ApplicationController
|
118
120
|
# def index
|
119
|
-
# # Remove controller and action from the options. Rails adds them automatically.
|
120
|
-
# options = params.delete_if { |k,v| %w{controller action}.include?(k) }
|
121
121
|
# provider = BlogProvider.new
|
122
|
-
# response = provider.process_request(
|
123
|
-
# render :
|
122
|
+
# response = provider.process_request(oai_params.to_h)
|
123
|
+
# render :body => response, :content_type => 'text/xml'
|
124
|
+
# end
|
125
|
+
#
|
126
|
+
# private
|
127
|
+
#
|
128
|
+
# def oai_params
|
129
|
+
# params.permit(:verb, :identifier, :metadataPrefix, :set, :from, :until, :resumptionToken)
|
124
130
|
# end
|
125
131
|
# end
|
126
132
|
# ```
|
127
133
|
#
|
134
|
+
# And route to it in your `config/routes.rb` file:
|
135
|
+
#
|
136
|
+
# ```ruby
|
137
|
+
# match 'oai', to: "oai#index", via: [:get, :post]
|
138
|
+
# ```
|
139
|
+
#
|
128
140
|
# Special thanks to Jose Hales-Garcia for this solution.
|
129
141
|
#
|
130
142
|
# ## Supporting custom metadata formats
|
@@ -137,13 +149,19 @@ end
|
|
137
149
|
# It takes one required paramater, the class name of the AR class to wrap,
|
138
150
|
# and optional hash of options.
|
139
151
|
#
|
152
|
+
# As of `oai` gem 1.0.0, Rails 5.2.x and Rails 6.0.x are supported.
|
153
|
+
# Please check the .travis.yml file at root of repo to see what versions of ruby/rails
|
154
|
+
# are being tested, in case this is out of date.
|
155
|
+
#
|
140
156
|
# Valid options include:
|
141
157
|
#
|
142
|
-
# * `timestamp_field` - Specifies the model field to use as the update
|
158
|
+
# * `timestamp_field` - Specifies the model field/method to use as the update
|
143
159
|
# filter. Defaults to `updated_at`.
|
160
|
+
# * `identifier_field` -- specifies the model field/method to use to get value to use
|
161
|
+
# as oai identifier (method return value should not include prefix)
|
144
162
|
# * `limit` - Maximum number of records to return in each page/set.
|
145
|
-
# Defaults to 100.
|
146
|
-
#
|
163
|
+
# Defaults to 100, set to `nil` for all records in one page. Otherwise
|
164
|
+
# the wrapper will paginate the result via resumption tokens.
|
147
165
|
# _Caution: specifying too large a limit will adversely affect performance._
|
148
166
|
#
|
149
167
|
# Mapping from a ActiveRecord object to a specific metadata format follows
|
@@ -197,6 +215,26 @@ end
|
|
197
215
|
# end
|
198
216
|
# end
|
199
217
|
# ```
|
218
|
+
# ### Scopes for restrictions or eager-loading
|
219
|
+
#
|
220
|
+
# Instead of passing in a Model class to OAI::Provider::ActiveRecordWrapper, you can actually
|
221
|
+
# pass in any scope (or ActiveRecord::Relation). This means you can use it for restrictions:
|
222
|
+
#
|
223
|
+
# OAI::Provider::ActiveRecordWrapper.new(Post.where(published: true))
|
224
|
+
#
|
225
|
+
# Or eager-loading an association you will need to create serialization, to avoid n+1 query
|
226
|
+
# performance problems:
|
227
|
+
#
|
228
|
+
# OAI::Provider::ActiveRecordWrapper.new(Post.includes(:categories))
|
229
|
+
#
|
230
|
+
# Or both of those in combination, or anything else that returns an ActiveRecord::Relation,
|
231
|
+
# including using custom scopes, etc.
|
232
|
+
#
|
233
|
+
# ### Sets?
|
234
|
+
#
|
235
|
+
# There is some code written to support oai-pmh "sets" in the ActiveRecord::Wrapper, but
|
236
|
+
# it's somewhat inflexible, and not well-documented, and as I write this I don't understand
|
237
|
+
# it enough to say more. See https://github.com/code4lib/ruby-oai/issues/67
|
200
238
|
#
|
201
239
|
module OAI::Provider
|
202
240
|
class Base
|
data/lib/oai/provider/model.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
module OAI::Provider
|
2
2
|
# = OAI::Provider::Model
|
3
3
|
#
|
4
|
-
# Model implementers should subclass OAI::Provider::Model and override
|
4
|
+
# Model implementers should subclass OAI::Provider::Model and override
|
5
5
|
# Model#earliest, Model#latest, and Model#find. Optionally Model#sets and
|
6
|
-
# Model#deleted? can be used to support sets and record deletions. It
|
7
|
-
# is also the responsibility of the model implementer to account for
|
8
|
-
# resumption tokens if support is required. Models that don't support
|
9
|
-
# resumption tokens should raise an exception if a limit is requested
|
6
|
+
# Model#deleted? can be used to support sets and record deletions. It
|
7
|
+
# is also the responsibility of the model implementer to account for
|
8
|
+
# resumption tokens if support is required. Models that don't support
|
9
|
+
# resumption tokens should raise an exception if a limit is requested
|
10
10
|
# during initialization.
|
11
11
|
#
|
12
12
|
# earliest - should return the earliest update time in the repository.
|
@@ -14,8 +14,8 @@ module OAI::Provider
|
|
14
14
|
# sets - should return an array of sets supported by the repository.
|
15
15
|
# deleted? - individual records returned should respond true or false
|
16
16
|
# when sent the deleted? message.
|
17
|
-
# available_formats - if overridden, individual records should return an
|
18
|
-
# array of prefixes for all formats in which that record is available,
|
17
|
+
# available_formats - if overridden, individual records should return an
|
18
|
+
# array of prefixes for all formats in which that record is available,
|
19
19
|
# if other than ["oai_dc"]
|
20
20
|
# about - if overridden, should return a String or Array of XML Strings to
|
21
21
|
# insert into the OAI Record <about> chunks.
|
@@ -28,12 +28,12 @@ module OAI::Provider
|
|
28
28
|
# There are several helper models for dealing with resumption tokens please
|
29
29
|
# see the ResumptionToken class for more details.
|
30
30
|
#
|
31
|
-
|
32
31
|
class Model
|
33
|
-
attr_reader :timestamp_field
|
34
|
-
|
35
|
-
def initialize(limit = nil, timestamp_field = 'updated_at')
|
32
|
+
attr_reader :timestamp_field, :identifier_field
|
33
|
+
|
34
|
+
def initialize(limit = nil, timestamp_field = 'updated_at', identifier_field = 'id')
|
36
35
|
@limit = limit
|
36
|
+
@identifier_field = identifier_field
|
37
37
|
@timestamp_field = timestamp_field
|
38
38
|
end
|
39
39
|
|
@@ -41,16 +41,16 @@ module OAI::Provider
|
|
41
41
|
def earliest
|
42
42
|
raise NotImplementedError.new
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
# should return the latest timestamp available from this model.
|
46
46
|
def latest
|
47
47
|
raise NotImplementedError.new
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
def sets
|
51
51
|
nil
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
# find is the core method of a model, it returns records from the model
|
55
55
|
# bases on the parameters passed in.
|
56
56
|
#
|
@@ -61,12 +61,12 @@ module OAI::Provider
|
|
61
61
|
# * :from => earliest timestamp to be included in the results
|
62
62
|
# * :until => latest timestamp to be included in the results
|
63
63
|
# * :set => the set from which to retrieve the results
|
64
|
-
# * :metadata_prefix => type of metadata requested (this may be useful if
|
64
|
+
# * :metadata_prefix => type of metadata requested (this may be useful if
|
65
65
|
# not all records are available in all formats)
|
66
66
|
def find(selector, options={})
|
67
67
|
raise NotImplementedError.new
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
def deleted?
|
71
71
|
false
|
72
72
|
end
|
@@ -76,5 +76,5 @@ module OAI::Provider
|
|
76
76
|
nil
|
77
77
|
end
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
end
|
@@ -90,17 +90,16 @@ module OAI::Provider
|
|
90
90
|
# select a subset of the result set, and return it with a
|
91
91
|
# resumption token to get the next subset
|
92
92
|
def select_partial(token)
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
93
|
+
oaitoken = OaiToken.find_by(token: token.to_s)
|
94
|
+
|
95
|
+
if 0 == token.last && oaitoken.nil?
|
96
|
+
oaitoken = OaiToken.create!(token: token.to_s)
|
97
|
+
OaiToken.connection.execute("insert into " +
|
98
|
+
"#{OaiEntry.table_name} (oai_token_id, record_id) " +
|
99
|
+
"select #{oaitoken.id}, id from #{model.table_name} where " +
|
100
|
+
"#{OaiToken.sanitize_sql(token_conditions(token))}")
|
101
101
|
end
|
102
102
|
|
103
|
-
oaitoken = OaiToken.find_by_token(token.to_s)
|
104
103
|
raise ResumptionTokenException.new unless oaitoken
|
105
104
|
|
106
105
|
PartialResult.new(
|
@@ -111,7 +110,7 @@ module OAI::Provider
|
|
111
110
|
end
|
112
111
|
|
113
112
|
def sweep_cache
|
114
|
-
OaiToken.
|
113
|
+
OaiToken.where(["created_at < ?", Time.now - expire]).destroy_all
|
115
114
|
end
|
116
115
|
|
117
116
|
def hydrate_records(records)
|
@@ -10,12 +10,19 @@ module OAI::Provider
|
|
10
10
|
#
|
11
11
|
class ActiveRecordWrapper < Model
|
12
12
|
|
13
|
-
attr_reader :model, :timestamp_field
|
14
|
-
|
13
|
+
attr_reader :model, :timestamp_field, :identifier_field
|
14
|
+
|
15
|
+
# If custom 'timestamp_field' is used, be aware this will be an ActiveRecord
|
16
|
+
# attribute that we will limit on, so perhaps should be indexe appropriately.
|
17
|
+
#
|
18
|
+
# If custom `identifier_field` is used, be aware this will be an ActiveRecord
|
19
|
+
# attribute that we will sort on, and use in WHERE clauses with `=` as well as
|
20
|
+
# greater than/less than, so should be indexed appropriately.
|
15
21
|
def initialize(model, options={})
|
16
22
|
@model = model
|
17
23
|
@timestamp_field = options.delete(:timestamp_field) || 'updated_at'
|
18
|
-
@
|
24
|
+
@identifier_field = options.delete(:identifier_field) || model.primary_key || "id"
|
25
|
+
@limit = options.delete(:limit) || 100
|
19
26
|
|
20
27
|
unless options.empty?
|
21
28
|
raise ArgumentError.new(
|
@@ -54,7 +61,7 @@ module OAI::Provider
|
|
54
61
|
find_scope.where(conditions)
|
55
62
|
end
|
56
63
|
else
|
57
|
-
find_scope.where(conditions).
|
64
|
+
find_scope.where(conditions).find_by!(identifier_field => selector)
|
58
65
|
end
|
59
66
|
end
|
60
67
|
|
@@ -105,7 +112,7 @@ module OAI::Provider
|
|
105
112
|
model.where(set: options[:set])
|
106
113
|
else
|
107
114
|
# Default to empty set, as we've tried everything else
|
108
|
-
model.
|
115
|
+
model.none
|
109
116
|
end
|
110
117
|
end
|
111
118
|
|
@@ -129,7 +136,7 @@ module OAI::Provider
|
|
129
136
|
else # end of result set
|
130
137
|
find_scope.where(token_conditions(token))
|
131
138
|
.limit(@limit)
|
132
|
-
.order("#{
|
139
|
+
.order("#{identifier_field} asc")
|
133
140
|
end
|
134
141
|
end
|
135
142
|
|
@@ -138,9 +145,9 @@ module OAI::Provider
|
|
138
145
|
def select_partial(find_scope, token)
|
139
146
|
records = find_scope.where(token_conditions(token))
|
140
147
|
.limit(@limit)
|
141
|
-
.order("#{
|
148
|
+
.order("#{identifier_field} asc")
|
142
149
|
raise OAI::ResumptionTokenException.new unless records
|
143
|
-
offset = records.last.send(
|
150
|
+
offset = records.last.send(identifier_field)
|
144
151
|
|
145
152
|
PartialResult.new(records, token.next(offset))
|
146
153
|
end
|
@@ -157,7 +164,7 @@ module OAI::Provider
|
|
157
164
|
|
158
165
|
return sql if 0 == last
|
159
166
|
# Now add last id constraint
|
160
|
-
sql.first << " AND #{
|
167
|
+
sql.first << " AND #{identifier_field} > :id"
|
161
168
|
sql.last[:id] = last
|
162
169
|
|
163
170
|
return sql
|
@@ -48,8 +48,9 @@ module OAI::Provider::Response
|
|
48
48
|
|
49
49
|
private
|
50
50
|
|
51
|
+
# Namespace syntax suggested in http://www.openarchives.org/OAI/2.0/guidelines-oai-identifier.htm
|
51
52
|
def identifier_for(record)
|
52
|
-
"#{provider.prefix}
|
53
|
+
"#{provider.prefix}:#{record.send( provider.model.identifier_field )}"
|
53
54
|
end
|
54
55
|
|
55
56
|
def timestamp_for(record)
|
@@ -3,7 +3,24 @@ require 'logger'
|
|
3
3
|
|
4
4
|
# Configure AR connection
|
5
5
|
#ActiveRecord::Base.logger = Logger.new(STDOUT)
|
6
|
+
|
7
|
+
if RUBY_PLATFORM == "java"
|
8
|
+
require 'jdbc/sqlite3'
|
9
|
+
Jdbc::SQLite3.load_driver
|
10
|
+
end
|
11
|
+
|
6
12
|
ActiveRecord::Migration.verbose = false
|
7
13
|
ActiveRecord::Base.establish_connection :adapter => "sqlite3",
|
8
14
|
:database => ":memory:"
|
9
|
-
|
15
|
+
|
16
|
+
if ActiveRecord.version < Gem::Version.new("6.0.0")
|
17
|
+
ActiveRecord::MigrationContext.new(
|
18
|
+
File.join(File.dirname(__FILE__), '..', 'database')
|
19
|
+
).migrate
|
20
|
+
else
|
21
|
+
ActiveRecord::MigrationContext.new(
|
22
|
+
File.join(File.dirname(__FILE__), '..', 'database'),
|
23
|
+
ActiveRecord::Base.connection.schema_migration
|
24
|
+
).migrate
|
25
|
+
end
|
26
|
+
|
@@ -12,6 +12,22 @@ class ARProvider < OAI::Provider::Base
|
|
12
12
|
source_model ActiveRecordWrapper.new(DCField)
|
13
13
|
end
|
14
14
|
|
15
|
+
class ARProviderCustomIdentifierField < OAI::Provider::Base
|
16
|
+
repository_name 'ActiveRecord Based Provider'
|
17
|
+
repository_url 'http://localhost'
|
18
|
+
record_prefix 'oai:test'
|
19
|
+
source_model ActiveRecordWrapper.new(DCField, identifier_field: "source")
|
20
|
+
end
|
21
|
+
|
22
|
+
class ARProviderWithScope < OAI::Provider::Base
|
23
|
+
DATE_LESS_THAN_RESTRICTION = Time.parse("2007-03-12 19:30:22 UTC")
|
24
|
+
|
25
|
+
repository_name 'ActiveRecord Based Provider'
|
26
|
+
repository_url 'http://localhost'
|
27
|
+
record_prefix 'oai:test'
|
28
|
+
source_model ActiveRecordWrapper.new(DCField.where("date < ?", DATE_LESS_THAN_RESTRICTION).includes(:sets))
|
29
|
+
end
|
30
|
+
|
15
31
|
class SimpleResumptionProvider < OAI::Provider::Base
|
16
32
|
repository_name 'ActiveRecord Resumption Provider'
|
17
33
|
repository_url 'http://localhost'
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'test_helper_ar_provider'
|
2
2
|
|
3
3
|
class ActiveRecordProviderTest < TransactionalTestCase
|
4
4
|
|
@@ -14,7 +14,7 @@ class ActiveRecordProviderTest < TransactionalTestCase
|
|
14
14
|
|
15
15
|
def test_metadata_formats_for_record
|
16
16
|
record_id = DCField.first.id
|
17
|
-
assert_nothing_raised { REXML::Document.new(@provider.list_metadata_formats(:identifier => "oai:test
|
17
|
+
assert_nothing_raised { REXML::Document.new(@provider.list_metadata_formats(:identifier => "oai:test:#{record_id}")) }
|
18
18
|
doc = REXML::Document.new(@provider.list_metadata_formats)
|
19
19
|
assert doc.elements['/OAI-PMH/ListMetadataFormats/metadataFormat/metadataPrefix'].text == 'oai_dc'
|
20
20
|
end
|
@@ -28,6 +28,30 @@ class ActiveRecordProviderTest < TransactionalTestCase
|
|
28
28
|
assert_equal 100, doc.elements['OAI-PMH/ListRecords'].to_a.size
|
29
29
|
end
|
30
30
|
|
31
|
+
def test_list_records_scope
|
32
|
+
@provider = ARProviderWithScope.new
|
33
|
+
|
34
|
+
doc = nil
|
35
|
+
assert_nothing_raised do
|
36
|
+
doc = REXML::Document.new(@provider.list_records(:metadata_prefix => 'oai_dc'))
|
37
|
+
end
|
38
|
+
|
39
|
+
expected_count = DCField.where("date < ?", ARProviderWithScope::DATE_LESS_THAN_RESTRICTION).count
|
40
|
+
assert_equal expected_count, doc.elements['OAI-PMH/ListRecords'].to_a.size
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def test_get_record_alternate_identifier_column
|
45
|
+
@provider = ARProviderCustomIdentifierField.new
|
46
|
+
|
47
|
+
record_id = DCField.first.send(@provider.class.model.identifier_field)
|
48
|
+
|
49
|
+
doc = REXML::Document.new(@provider.get_record(
|
50
|
+
:identifier => "oai:test:#{record_id}", :metadata_prefix => 'oai_dc'))
|
51
|
+
|
52
|
+
assert_equal "oai:test:#{record_id}", doc.elements['OAI-PMH/GetRecord/record/header/identifier'].text
|
53
|
+
end
|
54
|
+
|
31
55
|
def test_list_identifiers
|
32
56
|
assert_nothing_raised { REXML::Document.new(@provider.list_identifiers) }
|
33
57
|
doc = REXML::Document.new(@provider.list_identifiers)
|
@@ -38,11 +62,11 @@ class ActiveRecordProviderTest < TransactionalTestCase
|
|
38
62
|
record_id = DCField.first.id
|
39
63
|
assert_nothing_raised do
|
40
64
|
REXML::Document.new(@provider.get_record(
|
41
|
-
:identifier => "oai:test
|
65
|
+
:identifier => "oai:test:#{record_id}", :metadata_prefix => 'oai_dc'))
|
42
66
|
end
|
43
67
|
doc = REXML::Document.new(@provider.get_record(
|
44
68
|
:identifier => "#{record_id}", :metadata_prefix => 'oai_dc'))
|
45
|
-
assert_equal "oai:test
|
69
|
+
assert_equal "oai:test:#{record_id}", doc.elements['OAI-PMH/GetRecord/record/header/identifier'].text
|
46
70
|
end
|
47
71
|
|
48
72
|
def test_deleted
|
@@ -50,8 +74,8 @@ class ActiveRecordProviderTest < TransactionalTestCase
|
|
50
74
|
record.deleted = true;
|
51
75
|
record.save
|
52
76
|
doc = REXML::Document.new(@provider.get_record(
|
53
|
-
:identifier => "oai:test
|
54
|
-
assert_equal "oai:test
|
77
|
+
:identifier => "oai:test:#{record.id}", :metadata_prefix => 'oai_dc'))
|
78
|
+
assert_equal "oai:test:#{record.id}", doc.elements['OAI-PMH/GetRecord/record/header/identifier'].text
|
55
79
|
assert_equal 'deleted', doc.elements['OAI-PMH/GetRecord/record/header'].attributes["status"]
|
56
80
|
end
|
57
81
|
|
@@ -1,12 +1,5 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
|
3
|
-
if ENV['COVERAGE'] and RUBY_VERSION =~ /^1.9/
|
4
|
-
require 'simplecov'
|
5
|
-
require 'simplecov-rcov'
|
6
|
-
|
7
|
-
SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
|
8
|
-
SimpleCov.start
|
9
|
-
end
|
10
3
|
require 'test/unit'
|
11
4
|
require File.dirname(__FILE__) + '/config/connection'
|
12
5
|
require File.dirname(__FILE__) + '/helpers/providers'
|
@@ -1,20 +1,20 @@
|
|
1
1
|
require 'webrick'
|
2
2
|
require File.dirname(__FILE__) + '/../../provider/models'
|
3
3
|
|
4
|
-
class ComplexProvider < OAI::Provider::Base
|
5
|
-
repository_name 'Complex Provider'
|
6
|
-
repository_url 'http://localhost'
|
7
|
-
record_prefix 'oai:test'
|
8
|
-
source_model ComplexModel.new(100)
|
9
|
-
end
|
10
4
|
|
11
5
|
class ProviderServer
|
6
|
+
class ComplexClientProvider < OAI::Provider::Base
|
7
|
+
repository_name 'Complex Provider'
|
8
|
+
repository_url 'http://localhost'
|
9
|
+
record_prefix 'oai:test'
|
10
|
+
source_model ComplexModel.new(100)
|
11
|
+
end
|
12
12
|
|
13
13
|
attr_reader :consumed, :server
|
14
14
|
|
15
15
|
def initialize(port, mount_point)
|
16
16
|
@consumed = []
|
17
|
-
@provider =
|
17
|
+
@provider = ComplexClientProvider.new
|
18
18
|
@server = WEBrick::HTTPServer.new(
|
19
19
|
:BindAddress => '127.0.0.1',
|
20
20
|
:Logger => WEBrick::Log.new('/dev/null'),
|
@@ -62,4 +62,4 @@ class ProviderServer
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
end
|
65
|
+
end
|
data/test/client/tc_exception.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'test_helper_client'
|
2
2
|
|
3
3
|
class ExceptionTest < Test::Unit::TestCase
|
4
4
|
|
@@ -9,7 +9,7 @@ class ExceptionTest < Test::Unit::TestCase
|
|
9
9
|
|
10
10
|
def test_xml_error
|
11
11
|
client = OAI::Client.new 'http://www.yahoo.com'
|
12
|
-
begin
|
12
|
+
begin
|
13
13
|
client.identify
|
14
14
|
rescue OAI::Exception => e
|
15
15
|
assert_match /response not well formed XML/, e.to_s, 'xml error'
|
@@ -23,7 +23,7 @@ class ExceptionTest < Test::Unit::TestCase
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
# must pass in options as a hash
|
26
|
+
# must pass in options as a hash
|
27
27
|
def test_parameter_error
|
28
28
|
client = OAI::Client.new 'http://localhost:3333/oai'
|
29
29
|
assert_raises(OAI::ArgumentException) {client.get_record('foo')}
|
@@ -32,5 +32,5 @@ class ExceptionTest < Test::Unit::TestCase
|
|
32
32
|
assert_raises(OAI::ArgumentException) {client.list_metadata_formats('foo')}
|
33
33
|
assert_raises(OAI::ArgumentException) {client.list_sets('foo')}
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require '
|
1
|
+
require 'test_helper_client'
|
2
2
|
|
3
3
|
class GetRecordTest < Test::Unit::TestCase
|
4
|
-
|
4
|
+
|
5
5
|
def test_get_one
|
6
6
|
client = OAI::Client.new 'http://localhost:3333/oai'
|
7
|
-
response = client.get_record :identifier => 'oai:test
|
7
|
+
response = client.get_record :identifier => 'oai:test:3'
|
8
8
|
assert_kind_of OAI::GetRecordResponse, response
|
9
9
|
assert_kind_of OAI::Record, response.record
|
10
10
|
assert_kind_of REXML::Element, response.record._source
|
@@ -13,8 +13,7 @@ class GetRecordTest < Test::Unit::TestCase
|
|
13
13
|
assert_kind_of REXML::Element, response.record.about
|
14
14
|
|
15
15
|
# minimal check that the header is working
|
16
|
-
assert_equal 'oai:test
|
17
|
-
response.record.header.identifier
|
16
|
+
assert_equal 'oai:test:3', response.record.header.identifier
|
18
17
|
|
19
18
|
# minimal check that the metadata is working
|
20
19
|
#assert 'en', response.record.metadata.elements['.//dc:language'].text
|
@@ -33,7 +32,7 @@ class GetRecordTest < Test::Unit::TestCase
|
|
33
32
|
|
34
33
|
def test_deleted_record
|
35
34
|
client = OAI::Client.new 'http://localhost:3333/oai'
|
36
|
-
record = client.get_record :identifier => 'oai:test
|
35
|
+
record = client.get_record :identifier => 'oai:test:275'
|
37
36
|
assert record.deleted?
|
38
37
|
end
|
39
38
|
|
data/test/client/tc_identify.rb
CHANGED
data/test/client/tc_libxml.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'test_helper_client'
|
2
2
|
|
3
3
|
class LibXMLTest < Test::Unit::TestCase
|
4
4
|
|
@@ -13,7 +13,7 @@ class LibXMLTest < Test::Unit::TestCase
|
|
13
13
|
def test_list_records
|
14
14
|
return unless have_libxml
|
15
15
|
|
16
|
-
# since there is regex magic going on to remove default oai namespaces
|
16
|
+
# since there is regex magic going on to remove default oai namespaces
|
17
17
|
# it's worth trying a few different oai targets
|
18
18
|
oai_targets = %w{
|
19
19
|
http://localhost:3333/oai
|
@@ -43,10 +43,10 @@ class LibXMLTest < Test::Unit::TestCase
|
|
43
43
|
|
44
44
|
uri = 'http://localhost:3333/oai'
|
45
45
|
client = OAI::Client.new(uri, :parser => 'libxml')
|
46
|
-
response = client.get_record :identifier => 'oai:test
|
46
|
+
response = client.get_record :identifier => 'oai:test:275'
|
47
47
|
assert response.record.deleted?
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
private
|
51
51
|
|
52
52
|
def have_libxml
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require '
|
1
|
+
require 'test_helper_client'
|
2
2
|
|
3
3
|
class ListMetadataFormatsTest < Test::Unit::TestCase
|
4
4
|
def test_list
|
5
|
-
client = OAI::Client.new 'http://localhost:3333/oai'
|
5
|
+
client = OAI::Client.new 'http://localhost:3333/oai'
|
6
6
|
response = client.list_metadata_formats
|
7
7
|
assert_kind_of OAI::ListMetadataFormatsResponse, response
|
8
8
|
assert response.entries.size > 0
|
@@ -13,6 +13,6 @@ class ListMetadataFormatsTest < Test::Unit::TestCase
|
|
13
13
|
assert_equal 'http://www.openarchives.org/OAI/2.0/oai_dc.xsd', format.schema
|
14
14
|
assert_equal 'http://www.openarchives.org/OAI/2.0/oai_dc/', format.namespace
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
end
|
18
18
|
|
data/test/client/tc_list_sets.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
require '
|
1
|
+
require 'test_helper_client'
|
2
2
|
|
3
3
|
class LowResolutionDatesTest < Test::Unit::TestCase
|
4
4
|
|
5
5
|
def test_low_res_date_parsing
|
6
|
-
client = OAI::Client.new 'http://authors.library.caltech.edu/cgi/oai2'
|
6
|
+
client = OAI::Client.new 'http://authors.library.caltech.edu/cgi/oai2'
|
7
7
|
|
8
8
|
date = Date.new 2003, 1, 1
|
9
|
-
|
9
|
+
|
10
10
|
# get a list of identifier headers
|
11
|
-
assert_nothing_raised { client.list_identifiers :from => date }
|
11
|
+
assert_nothing_raised { client.list_identifiers :from => date }
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require '
|
1
|
+
require 'test_helper_client'
|
2
2
|
|
3
3
|
class UTF8Test < Test::Unit::TestCase
|
4
|
-
|
4
|
+
|
5
5
|
def test_escaping_invalid_utf_8_characters
|
6
6
|
client = OAI::Client.new 'http://localhost:3333/oai' #, :parser => 'libxml'
|
7
7
|
invalid_utf_8 = [2, 3, 4, 104, 5, 101, 6, 108, 66897, 108, 66535, 111, 1114112, 33, 55234123, 33].pack("U*")
|
data/test/client/tc_xpath.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'test_helper_client'
|
2
2
|
|
3
3
|
class XpathTest < Test::Unit::TestCase
|
4
4
|
include OAI::XPath
|
@@ -11,7 +11,7 @@ class XpathTest < Test::Unit::TestCase
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def test_libxml
|
14
|
-
begin
|
14
|
+
begin
|
15
15
|
require 'xml/libxml'
|
16
16
|
rescue LoadError
|
17
17
|
# libxml not available so nothing to test!
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'test_helper_provider'
|
2
2
|
|
3
3
|
class ProviderExceptions < Test::Unit::TestCase
|
4
4
|
|
@@ -36,7 +36,7 @@ class ProviderExceptions < Test::Unit::TestCase
|
|
36
36
|
|
37
37
|
def test_bad_format_raises_exception
|
38
38
|
assert_raise(OAI::FormatException) do
|
39
|
-
@provider.get_record(:identifier => 'oai:test
|
39
|
+
@provider.get_record(:identifier => 'oai:test:1', :metadata_prefix => 'html')
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -45,16 +45,18 @@ class ProviderExceptions < Test::Unit::TestCase
|
|
45
45
|
@provider.list_records()
|
46
46
|
end
|
47
47
|
assert_raise(OAI::ArgumentException) do
|
48
|
-
@provider.get_record(:identifier => 'oai:test
|
48
|
+
@provider.get_record(:identifier => 'oai:test:1')
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
52
|
def test_bad_id_raises_exception
|
53
53
|
badIdentifiers = [
|
54
|
-
'oai:test
|
55
|
-
'oai:test
|
54
|
+
'oai:test:5000',
|
55
|
+
'oai:test:-1',
|
56
|
+
'oai:test:one',
|
56
57
|
'oai:test/one',
|
57
|
-
'oai:test
|
58
|
+
'oai:test/1',
|
59
|
+
'oai:test:\\$1\1!']
|
58
60
|
badIdentifiers.each do |id|
|
59
61
|
assert_raise(OAI::IdException) do
|
60
62
|
@provider.get_record(:identifier => id, :metadata_prefix => 'oai_dc')
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'test_helper_provider'
|
2
2
|
|
3
3
|
class ResumptionTokenFunctionalTest < Test::Unit::TestCase
|
4
4
|
include REXML
|
@@ -44,4 +44,4 @@ class ResumptionTokenFunctionalTest < Test::Unit::TestCase
|
|
44
44
|
assert_equal 100, doc.elements["/OAI-PMH/ListRecords"].to_a.size
|
45
45
|
end
|
46
46
|
|
47
|
-
end
|
47
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'test_helper_provider'
|
2
2
|
|
3
3
|
class ResumptionTokenTest < Test::Unit::TestCase
|
4
4
|
include REXML
|
@@ -43,4 +43,4 @@ class ResumptionTokenTest < Test::Unit::TestCase
|
|
43
43
|
assert_equal "#{@token.to_s}:#{@token.last}", doc.elements['/resumptionToken'].text
|
44
44
|
end
|
45
45
|
|
46
|
-
end
|
46
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'test_helper_provider'
|
2
2
|
|
3
3
|
class TestSimpleProvider < Test::Unit::TestCase
|
4
4
|
|
@@ -35,7 +35,7 @@ class TestSimpleProvider < Test::Unit::TestCase
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def test_metadata_formats_for_document
|
38
|
-
assert_nothing_raised { REXML::Document.new(@simple_provider.list_metadata_formats(:identifier => "oai:test
|
38
|
+
assert_nothing_raised { REXML::Document.new(@simple_provider.list_metadata_formats(:identifier => "oai:test:1")) }
|
39
39
|
doc = REXML::Document.new(@simple_provider.list_metadata_formats)
|
40
40
|
assert_equal "oai_dc",
|
41
41
|
doc.elements['/OAI-PMH/ListMetadataFormats/metadataFormat/metadataPrefix'].text
|
@@ -85,18 +85,18 @@ class TestSimpleProvider < Test::Unit::TestCase
|
|
85
85
|
assert_nothing_raised do
|
86
86
|
REXML::Document.new(
|
87
87
|
@simple_provider.get_record(
|
88
|
-
:identifier => 'oai:test
|
88
|
+
:identifier => 'oai:test:1',
|
89
89
|
:metadataPrefix => 'oai_dc'
|
90
90
|
)
|
91
91
|
)
|
92
92
|
end
|
93
93
|
doc = REXML::Document.new(
|
94
94
|
@simple_provider.get_record(
|
95
|
-
:identifier => 'oai:test
|
95
|
+
:identifier => 'oai:test:1',
|
96
96
|
:metadataPrefix => 'oai_dc'
|
97
97
|
)
|
98
98
|
)
|
99
|
-
assert_equal 'oai:test
|
99
|
+
assert_equal 'oai:test:1',
|
100
100
|
doc.elements['OAI-PMH/GetRecord/record/header/identifier'].text
|
101
101
|
end
|
102
102
|
|
@@ -104,18 +104,18 @@ class TestSimpleProvider < Test::Unit::TestCase
|
|
104
104
|
assert_nothing_raised do
|
105
105
|
REXML::Document.new(
|
106
106
|
@simple_provider.get_record(
|
107
|
-
:identifier => 'oai:test
|
107
|
+
:identifier => 'oai:test:6',
|
108
108
|
:metadataPrefix => 'oai_dc'
|
109
109
|
)
|
110
110
|
)
|
111
111
|
end
|
112
112
|
doc = REXML::Document.new(
|
113
113
|
@simple_provider.get_record(
|
114
|
-
:identifier => 'oai:test
|
114
|
+
:identifier => 'oai:test:5',
|
115
115
|
:metadataPrefix => 'oai_dc'
|
116
116
|
)
|
117
117
|
)
|
118
|
-
assert_equal 'oai:test
|
118
|
+
assert_equal 'oai:test:5', doc.elements['OAI-PMH/GetRecord/record/header/identifier'].text
|
119
119
|
assert_equal 'deleted', doc.elements['OAI-PMH/GetRecord/record/header'].attributes["status"]
|
120
120
|
end
|
121
121
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oai
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ed Summers
|
8
8
|
autorequire: oai
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: builder
|
@@ -52,6 +52,40 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activerecord
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 5.2.0
|
62
|
+
- - "<"
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '6.1'
|
65
|
+
type: :development
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: 5.2.0
|
72
|
+
- - "<"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '6.1'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: appraisal
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
55
89
|
description:
|
56
90
|
email: ehs@pobox.com
|
57
91
|
executables:
|
@@ -119,7 +153,7 @@ files:
|
|
119
153
|
- test/activerecord_provider/tc_ar_sets_provider.rb
|
120
154
|
- test/activerecord_provider/tc_caching_paging_provider.rb
|
121
155
|
- test/activerecord_provider/tc_simple_paging_provider.rb
|
122
|
-
- test/activerecord_provider/
|
156
|
+
- test/activerecord_provider/test_helper_ar_provider.rb
|
123
157
|
- test/client/helpers/provider.rb
|
124
158
|
- test/client/helpers/test_wrapper.rb
|
125
159
|
- test/client/tc_exception.rb
|
@@ -134,14 +168,14 @@ files:
|
|
134
168
|
- test/client/tc_low_resolution_dates.rb
|
135
169
|
- test/client/tc_utf8_escaping.rb
|
136
170
|
- test/client/tc_xpath.rb
|
137
|
-
- test/client/
|
171
|
+
- test/client/test_helper_client.rb
|
138
172
|
- test/provider/models.rb
|
139
173
|
- test/provider/tc_exceptions.rb
|
140
174
|
- test/provider/tc_functional_tokens.rb
|
141
175
|
- test/provider/tc_provider.rb
|
142
176
|
- test/provider/tc_resumption_tokens.rb
|
143
177
|
- test/provider/tc_simple_provider.rb
|
144
|
-
- test/provider/
|
178
|
+
- test/provider/test_helper_provider.rb
|
145
179
|
- test/test.xml
|
146
180
|
homepage: http://github.com/code4lib/ruby-oai
|
147
181
|
licenses: []
|
@@ -157,15 +191,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
157
191
|
version: '0'
|
158
192
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
159
193
|
requirements:
|
160
|
-
- - "
|
194
|
+
- - ">"
|
161
195
|
- !ruby/object:Gem::Version
|
162
|
-
version:
|
196
|
+
version: 1.3.1
|
163
197
|
requirements: []
|
164
|
-
|
165
|
-
rubygems_version: 2.2.1
|
198
|
+
rubygems_version: 3.0.3
|
166
199
|
signing_key:
|
167
200
|
specification_version: 4
|
168
201
|
summary: A ruby library for working with the Open Archive Initiative Protocol for
|
169
202
|
Metadata Harvesting (OAI-PMH)
|
170
203
|
test_files: []
|
171
|
-
has_rdoc:
|
data/test/client/test_helper.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
if ENV['COVERAGE'] and RUBY_VERSION =~ /^1.9/
|
2
|
-
require 'simplecov'
|
3
|
-
require 'simplecov-rcov'
|
4
|
-
|
5
|
-
SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
|
6
|
-
SimpleCov.start
|
7
|
-
end
|
8
|
-
|
9
|
-
require 'oai'
|
10
|
-
require 'test/unit'
|
11
|
-
|
12
|
-
require File.dirname(__FILE__) + '/helpers/provider'
|
13
|
-
require File.dirname(__FILE__) + '/helpers/test_wrapper'
|