oaipmh 0.0.1 → 0.0.2
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/README +129 -3
- data/Rakefile +7 -5
- data/lib/oaipmh.rb +5 -6
- data/lib/oaipmh/constants.rb +2 -0
- data/lib/oaipmh/extensions/camping.rb +3 -3
- data/lib/oaipmh/metadata.rb +0 -2
- data/lib/oaipmh/provider.rb +43 -34
- data/lib/oaipmh/set.rb +30 -0
- data/lib/oaipmh/version.rb +1 -1
- data/test/oaipmh_test.rb +72 -2
- data/test/test_helper.rb +104 -0
- metadata +37 -10
data/README
CHANGED
@@ -1,3 +1,129 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# = README
|
2
|
+
#
|
3
|
+
# Copyright (C) 2006 William Groppe
|
4
|
+
#
|
5
|
+
# Will Groppe mailto:wfg@artstor.org
|
6
|
+
#
|
7
|
+
# Open Archives Initiative - Protocol for Metadata Harvesting see
|
8
|
+
# http://www.openarchives.org/
|
9
|
+
#
|
10
|
+
# === Features
|
11
|
+
# * Easily setup a simple repository
|
12
|
+
# * Simple integration with ActiveRecord
|
13
|
+
# * Dublin Core metadata format included
|
14
|
+
# * Easily add addition metadata formats
|
15
|
+
# * Adaptable to any data source
|
16
|
+
#
|
17
|
+
#
|
18
|
+
# === Current shortcomings
|
19
|
+
# * No resumption tokens
|
20
|
+
# * Doesn't validate metadata
|
21
|
+
# * No deletion support
|
22
|
+
# * Many others I can't think of right now. :-)
|
23
|
+
#
|
24
|
+
#
|
25
|
+
# === ActiveRecord integration
|
26
|
+
#
|
27
|
+
# To successfully use ActiveRecord as a OAI PMH datasource the database table
|
28
|
+
# should include an updated_at column so that updates to the table are
|
29
|
+
# tracked by ActiveRecord. This provides much of the base functionality for
|
30
|
+
# selecting update periods.
|
31
|
+
#
|
32
|
+
# To understand how the data is extracted from the AR model it's best to just
|
33
|
+
# go thru the logic:
|
34
|
+
#
|
35
|
+
# Does the model respond to 'to_{prefix}'? Where prefix is the
|
36
|
+
# metadata prefix. If it does then just include the response from
|
37
|
+
# the model. So if you want to provide custom or complex metadata you can
|
38
|
+
# simply define a 'to_{prefix}' method on your model.
|
39
|
+
#
|
40
|
+
# Example:
|
41
|
+
#
|
42
|
+
# class Record < ActiveRecord::Base
|
43
|
+
#
|
44
|
+
# def to_oai_dc
|
45
|
+
# xml = Builder::XmlMarkup.new
|
46
|
+
# xml.tag!('oai_dc:dc',
|
47
|
+
# 'xmlns:oai_dc' => "http://www.openarchives.org/OAI/2.0/oai_dc/",
|
48
|
+
# 'xmlns:dc' => "http://purl.org/dc/elements/1.1/",
|
49
|
+
# 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
|
50
|
+
# 'xsi:schemaLocation' =>
|
51
|
+
# %{http://www.openarchives.org/OAI/2.0/oai_dc/
|
52
|
+
# http://www.openarchives.org/OAI/2.0/oai_dc.xsd}) do
|
53
|
+
#
|
54
|
+
# xml.oai_dc :title, title
|
55
|
+
# xml.oai_dc :subject, subject
|
56
|
+
# end
|
57
|
+
# xml.to_s
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# If the model doesn't define a 'to_{prefix}' then start iterating thru
|
63
|
+
# the defined metadata fields.
|
64
|
+
#
|
65
|
+
# Grab a mapping if one exists by trying to call 'map_{prefix}'.
|
66
|
+
#
|
67
|
+
# Now do the iteration and try calling methods on the model that match
|
68
|
+
# the field names, or the mapped field names.
|
69
|
+
#
|
70
|
+
# So with Dublin Core we end up with the following:
|
71
|
+
#
|
72
|
+
# 1. Check for 'title' mapped to a different method.
|
73
|
+
# 2. Call model.titles - try plural
|
74
|
+
# 3. Call model.title - try singular last
|
75
|
+
#
|
76
|
+
# Extremely contrived Blog example:
|
77
|
+
#
|
78
|
+
# class Post < ActiveRecord::Base
|
79
|
+
# def map_oai_dc
|
80
|
+
# {:subject => :tags,
|
81
|
+
# :description => :text,
|
82
|
+
# :creator => :user,
|
83
|
+
# :contibutor => :comments}
|
84
|
+
# end
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
# === Supporting custom metadata
|
88
|
+
#
|
89
|
+
# See OaiPmh::Metadata for details.
|
90
|
+
#
|
91
|
+
# == Examples
|
92
|
+
#
|
93
|
+
# === Sub classing a provider
|
94
|
+
#
|
95
|
+
# class MyProvider < OaiPmh::Provider
|
96
|
+
# name 'My little OAI provider'
|
97
|
+
# url 'http://localhost/provider'
|
98
|
+
# prefix 'oai:localhost'
|
99
|
+
# email 'root@localhost' # String or Array
|
100
|
+
# deletes 'no' # future versions will support deletes
|
101
|
+
# granularity 'YYYY-MM-DDThh:mm:ssZ' # update resolution
|
102
|
+
# model MyModel # Class to get data from
|
103
|
+
# end
|
104
|
+
#
|
105
|
+
# # Now use it
|
106
|
+
#
|
107
|
+
# provider = MyProvider.new
|
108
|
+
# provider.identify
|
109
|
+
# provider.list_sets
|
110
|
+
# provider.list_metadata_formats
|
111
|
+
# # these verbs require a working model
|
112
|
+
# provider.list_identifiers
|
113
|
+
# provider.list_records
|
114
|
+
# provider.get_record('oai:localhost/1')
|
115
|
+
#
|
116
|
+
#
|
117
|
+
# === Configuring the default provider
|
118
|
+
#
|
119
|
+
# class OaiPmh::Provider
|
120
|
+
# name 'My little OAI Provider'
|
121
|
+
# url 'http://localhost/provider'
|
122
|
+
# prefix 'oai:localhost'
|
123
|
+
# email 'root@localhost' # String or Array
|
124
|
+
# deletes 'no' # future versions will support deletes
|
125
|
+
# granularity 'YYYY-MM-DDThh:mm:ssZ' # update resolution
|
126
|
+
# model MyModel # Class to get data from
|
127
|
+
# end
|
128
|
+
#
|
129
|
+
#
|
data/Rakefile
CHANGED
@@ -10,9 +10,9 @@ require 'fileutils'
|
|
10
10
|
include FileUtils
|
11
11
|
require File.join(File.dirname(__FILE__), 'lib', 'oaipmh', 'version')
|
12
12
|
|
13
|
-
AUTHOR = "
|
14
|
-
EMAIL = "
|
15
|
-
DESCRIPTION = "
|
13
|
+
AUTHOR = "Will Groppe"
|
14
|
+
EMAIL = "will.groppe@gmail.com"
|
15
|
+
DESCRIPTION = "OAI-PMH Provider"
|
16
16
|
RUBYFORGE_PROJECT = "oaipmh"
|
17
17
|
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
18
18
|
BIN_FILES = %w( )
|
@@ -57,8 +57,10 @@ spec =
|
|
57
57
|
s.require_path = "lib"
|
58
58
|
s.autorequire = "oaipmh"
|
59
59
|
|
60
|
-
|
61
|
-
|
60
|
+
s.add_dependency('activesupport', '>=1.3.1')
|
61
|
+
s.add_dependency('chronic', '>=0.1.4')
|
62
|
+
s.add_dependency('builder', '>=2.0.0')
|
63
|
+
s.required_ruby_version = '>= 1.8.2'
|
62
64
|
|
63
65
|
s.files = %w(README CHANGELOG Rakefile) +
|
64
66
|
Dir.glob("{bin,doc,test,lib,templates,generator,extras,website,script}/**/*") +
|
data/lib/oaipmh.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
#
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support'
|
3
|
+
require 'builder'
|
4
|
+
require 'chronic'
|
6
5
|
|
7
|
-
Dir[File.join(File.dirname(__FILE__), 'oaipmh
|
6
|
+
Dir[File.join(File.dirname(__FILE__), 'oaipmh/*.rb')].sort.each do |lib|
|
8
7
|
require lib
|
9
8
|
end
|
data/lib/oaipmh/constants.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'oaipmh'
|
2
2
|
|
3
3
|
module OaiPmh
|
4
|
-
module
|
5
|
-
module
|
4
|
+
module Goes
|
5
|
+
module Camping
|
6
6
|
|
7
7
|
def self.included(mod)
|
8
|
-
instance_eval(%{module
|
8
|
+
instance_eval(%{module ::#{mod}::Controllers
|
9
9
|
class Oai
|
10
10
|
def get
|
11
11
|
@headers['Content-Type'] = 'text/xml'
|
data/lib/oaipmh/metadata.rb
CHANGED
data/lib/oaipmh/provider.rb
CHANGED
@@ -132,28 +132,31 @@ module OaiPmh
|
|
132
132
|
class Provider
|
133
133
|
include Helpers
|
134
134
|
|
135
|
-
@@options = {}
|
136
|
-
|
137
135
|
AVAILABLE_FORMATS = {}
|
138
136
|
|
139
137
|
class << self
|
140
|
-
|
141
|
-
|
142
|
-
class_eval %{
|
143
|
-
def #{field}(value)
|
144
|
-
@@options[:#{field}] = value
|
145
|
-
end
|
146
|
-
}
|
147
|
-
end
|
148
|
-
|
138
|
+
attr_accessor :options
|
139
|
+
|
149
140
|
def model(value)
|
150
|
-
|
141
|
+
self.options ||={}
|
142
|
+
self.options[:model] = value
|
151
143
|
end
|
152
|
-
|
144
|
+
|
153
145
|
end
|
154
146
|
|
147
|
+
OaiPmh::Const::DEFAULTS.keys.each do |field|
|
148
|
+
class_eval %{
|
149
|
+
def self.#{field}(value)
|
150
|
+
self.options ||={}
|
151
|
+
self.options[:#{field}] = value
|
152
|
+
end
|
153
|
+
}
|
154
|
+
end
|
155
|
+
|
155
156
|
def initialize
|
156
|
-
@config =
|
157
|
+
@config = self.class.options ?
|
158
|
+
OaiPmh::Const::DEFAULTS.merge(self.class.options) :
|
159
|
+
OaiPmh::Const::DEFAULTS
|
157
160
|
end
|
158
161
|
|
159
162
|
def identify
|
@@ -235,12 +238,13 @@ module OaiPmh
|
|
235
238
|
end
|
236
239
|
|
237
240
|
def list_sets_response
|
238
|
-
raise SetException.new unless
|
241
|
+
raise SetException.new unless @model && @model.oai_sets
|
239
242
|
@xml.ListSets do |ls|
|
240
|
-
oai_sets.each do |ms|
|
243
|
+
@model.oai_sets.each do |ms|
|
241
244
|
@xml.set do |set|
|
242
245
|
@xml.setSpec ms.spec
|
243
246
|
@xml.setName ms.name
|
247
|
+
@xml.setDescription(ms.description) if ms.respond_to?(:description)
|
244
248
|
end
|
245
249
|
end
|
246
250
|
end
|
@@ -250,19 +254,19 @@ module OaiPmh
|
|
250
254
|
@xml.ListMetadataFormats do
|
251
255
|
@config[:formats].each_pair do |key, format|
|
252
256
|
@xml.metadataFormat do
|
253
|
-
@xml.metadataPrefix
|
254
|
-
@xml.schema
|
255
|
-
@xml.metadataNamespace
|
257
|
+
@xml.metadataPrefix format.send(:prefix)
|
258
|
+
@xml.schema format.send(:schema)
|
259
|
+
@xml.metadataNamespace format.send(:namespace)
|
256
260
|
end
|
257
261
|
end
|
258
262
|
end
|
259
263
|
end
|
260
264
|
|
261
265
|
def list_identifiers_response
|
262
|
-
raise
|
266
|
+
raise FormatException.new unless @config[:formats].include? @format
|
263
267
|
records = find :all
|
264
268
|
|
265
|
-
raise
|
269
|
+
raise NoMatchException.new if records.nil? || records.empty?
|
266
270
|
|
267
271
|
@xml.ListIdentifiers do
|
268
272
|
records.each do |record|
|
@@ -350,10 +354,12 @@ module OaiPmh
|
|
350
354
|
|
351
355
|
# emit record header
|
352
356
|
def metadata_header(record)
|
353
|
-
@xml.header do
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
+
@xml.header do
|
358
|
+
@xml.identifier "#{@config[:prefix]}/#{record.id}"
|
359
|
+
@xml.datestamp record.updated_at.utc.xmlschema
|
360
|
+
record.sets.each do |set|
|
361
|
+
@xml.setSpec set.spec
|
362
|
+
end if record.respond_to?(:sets)
|
357
363
|
end
|
358
364
|
end
|
359
365
|
|
@@ -369,8 +375,8 @@ module OaiPmh
|
|
369
375
|
@xml << str
|
370
376
|
end
|
371
377
|
else
|
372
|
-
map =
|
373
|
-
|
378
|
+
map = @model.respond_to?("map_#{@format}") ?
|
379
|
+
@model.send("map_#{@format}") : {}
|
374
380
|
|
375
381
|
mdformat = @config[:formats][@format]
|
376
382
|
@xml.metadata do
|
@@ -378,7 +384,7 @@ module OaiPmh
|
|
378
384
|
mdformat.fields.each do |field|
|
379
385
|
set = value_for(field, record, map)
|
380
386
|
set.each do |mdv|
|
381
|
-
|
387
|
+
@xml.tag! "#{mdformat.element_ns}:#{field}", mdv
|
382
388
|
end
|
383
389
|
end
|
384
390
|
end
|
@@ -397,17 +403,20 @@ module OaiPmh
|
|
397
403
|
# 4) Try calling the singular name method on the model, if it's not a
|
398
404
|
# reserved word.
|
399
405
|
def value_for(field, record, map)
|
400
|
-
if map.keys.include?(field)
|
401
|
-
|
402
|
-
|
406
|
+
if map.keys.include?(field.intern)
|
407
|
+
value = record.send(map[field.intern])
|
408
|
+
if value.kind_of?(String)
|
409
|
+
return [value]
|
410
|
+
end
|
411
|
+
return value.to_a
|
403
412
|
end
|
404
413
|
|
405
414
|
begin
|
406
|
-
return record.send(
|
407
|
-
rescue
|
415
|
+
return record.send(field.pluralize).to_a
|
416
|
+
rescue
|
408
417
|
unless OaiPmh::Const::RESERVED_WORDS.include?(field)
|
409
418
|
begin
|
410
|
-
return record.send(
|
419
|
+
return [record.send(field)]
|
411
420
|
rescue
|
412
421
|
return []
|
413
422
|
end
|
data/lib/oaipmh/set.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# = set.rb
|
2
|
+
#
|
3
|
+
# Copyright (C) 2006 William Groppe
|
4
|
+
#
|
5
|
+
# Will Groppe mailto: wfg@artstor.org
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# Implementing a set from scratch requires overridding two methods from
|
9
|
+
# OaiPmh::Set
|
10
|
+
#
|
11
|
+
# * name - descriptive name of this set
|
12
|
+
# * spec - short name of set
|
13
|
+
#
|
14
|
+
# and optionally
|
15
|
+
#
|
16
|
+
# * description - long description of the set
|
17
|
+
#
|
18
|
+
module OaiPmh
|
19
|
+
class Set
|
20
|
+
|
21
|
+
def name
|
22
|
+
"unknown"
|
23
|
+
end
|
24
|
+
|
25
|
+
def spec
|
26
|
+
"set"
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/lib/oaipmh/version.rb
CHANGED
data/test/oaipmh_test.rb
CHANGED
@@ -1,11 +1,81 @@
|
|
1
|
+
require 'rexml/document'
|
1
2
|
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
3
|
|
4
|
+
class MappedProvider < OaiPmh::Provider
|
5
|
+
name 'Mapped Provider'
|
6
|
+
prefix 'oai:test'
|
7
|
+
model MappedModel
|
8
|
+
end
|
9
|
+
|
10
|
+
class SimpleProvider < OaiPmh::Provider
|
11
|
+
name 'Test Provider'
|
12
|
+
prefix 'oai:test'
|
13
|
+
model SimpleModel
|
14
|
+
end
|
15
|
+
|
3
16
|
class OaipmhTest < Test::Unit::TestCase
|
4
17
|
|
5
18
|
def setup
|
19
|
+
@simple_provider = SimpleProvider.new
|
20
|
+
@mapped_provider = MappedProvider.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_indentify
|
24
|
+
doc = REXML::Document.new(@simple_provider.identify)
|
25
|
+
assert doc.elements["/OAI-PMH/Identify/repositoryName"].text == 'Test Provider'
|
26
|
+
assert doc.elements["/OAI-PMH/Identify/earliestDatestamp"].text == SimpleModel.oai_earliest.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_list_sets
|
30
|
+
doc = REXML::Document.new(@simple_provider.list_sets)
|
31
|
+
sets = doc.elements["/OAI-PMH/ListSets"]
|
32
|
+
assert sets.size == 2
|
33
|
+
assert sets[0].elements["//setName"].text == "Test Set"
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_metadata_formats
|
37
|
+
assert_nothing_raised { REXML::Document.new(@simple_provider.list_metadata_formats) }
|
38
|
+
doc = REXML::Document.new(@simple_provider.list_metadata_formats)
|
39
|
+
assert doc.elements['/OAI-PMH/ListMetadataFormats/metadataFormat/metadataPrefix'].text == 'oai_dc'
|
6
40
|
end
|
7
41
|
|
8
|
-
def
|
9
|
-
|
42
|
+
def test_list_records
|
43
|
+
assert_nothing_raised { REXML::Document.new(@simple_provider.list_records) }
|
44
|
+
doc = REXML::Document.new(@simple_provider.list_records)
|
45
|
+
assert_equal 5, doc.elements['OAI-PMH/ListRecords'].to_a.size
|
46
|
+
doc = REXML::Document.new(@simple_provider.list_records(:set => 'A'))
|
47
|
+
assert_equal 5, doc.elements['OAI-PMH/ListRecords'].to_a.size
|
48
|
+
doc = REXML::Document.new(@simple_provider.list_records(:set => 'A:B'))
|
49
|
+
assert_equal 2, doc.elements['OAI-PMH/ListRecords'].to_a.size
|
10
50
|
end
|
51
|
+
|
52
|
+
def test_list_identifiers
|
53
|
+
assert_nothing_raised { REXML::Document.new(@simple_provider.list_identifiers) }
|
54
|
+
doc = REXML::Document.new(@simple_provider.list_identifiers)
|
55
|
+
assert_equal 5, doc.elements['OAI-PMH/ListIdentifiers'].to_a.size
|
56
|
+
doc = REXML::Document.new(@simple_provider.list_identifiers(:set => 'A'))
|
57
|
+
assert_equal 5, doc.elements['OAI-PMH/ListIdentifiers'].to_a.size
|
58
|
+
doc = REXML::Document.new(@simple_provider.list_identifiers(:set => 'A:B'))
|
59
|
+
assert_equal 2, doc.elements['OAI-PMH/ListIdentifiers'].to_a.size
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_get_record
|
63
|
+
assert_nothing_raised { REXML::Document.new(@simple_provider.get_record('oai:test/1')) }
|
64
|
+
doc = REXML::Document.new(@simple_provider.get_record('oai:test/1'))
|
65
|
+
assert_equal 'oai:test/1', doc.elements['OAI-PMH/GetRecord/record/header/identifier'].text
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_mapped_source
|
69
|
+
assert_nothing_raised { REXML::Document.new(@mapped_provider.list_records) }
|
70
|
+
doc = REXML::Document.new(@mapped_provider.list_records)
|
71
|
+
assert_equal "title 1", doc.elements['OAI-PMH/ListRecords/record/metadata/oai_dc:dc/dc:creator'].text
|
72
|
+
assert_equal "creator", doc.elements['OAI-PMH/ListRecords/record/metadata/oai_dc:dc/dc:title'].text
|
73
|
+
assert_equal "tag 1", doc.elements['OAI-PMH/ListRecords/record/metadata/oai_dc:dc/dc:subject'].text
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_verb_exception
|
77
|
+
doc = REXML::Document.new(@simple_provider.process_verb('NoVerb'))
|
78
|
+
assert doc.elements["/OAI-PMH/error"].attributes["code"] == 'badVerb'
|
79
|
+
end
|
80
|
+
|
11
81
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,2 +1,106 @@
|
|
1
1
|
require 'test/unit'
|
2
2
|
require File.dirname(__FILE__) + '/../lib/oaipmh'
|
3
|
+
|
4
|
+
class Record
|
5
|
+
attr_accessor :id, :titles, :creator, :tags, :sets, :updated_at
|
6
|
+
|
7
|
+
def initialize(id, titles, creator, tags, sets)
|
8
|
+
@id = id;
|
9
|
+
@titles = titles
|
10
|
+
@creator = creator
|
11
|
+
@tags = tags
|
12
|
+
@sets = sets
|
13
|
+
@updated_at = Time.new.utc
|
14
|
+
end
|
15
|
+
|
16
|
+
# Override Object.id
|
17
|
+
def id
|
18
|
+
@id
|
19
|
+
end
|
20
|
+
|
21
|
+
def in_set(spec)
|
22
|
+
@sets.each { |set| return true if set.spec == spec }
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
class OneSet < OaiPmh::Set
|
29
|
+
|
30
|
+
def name
|
31
|
+
"Test Set"
|
32
|
+
end
|
33
|
+
|
34
|
+
def spec
|
35
|
+
"A"
|
36
|
+
end
|
37
|
+
|
38
|
+
def description
|
39
|
+
"A long winded description of this set."
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
class TwoSet < OaiPmh::Set
|
45
|
+
|
46
|
+
def name
|
47
|
+
"Not so test Set"
|
48
|
+
end
|
49
|
+
|
50
|
+
def spec
|
51
|
+
"A:B"
|
52
|
+
end
|
53
|
+
|
54
|
+
def description
|
55
|
+
"A short winded description of this set."
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
class SimpleModel
|
64
|
+
include OaiPmh::Model
|
65
|
+
|
66
|
+
RECORDS = [
|
67
|
+
Record.new(1, ['title 1', 'title 2'], 'creator', ['tag 1', 'tag 2'], [OneSet.new]),
|
68
|
+
Record.new(2, ['title 3', 'title 4'], 'creator', ['tag 3', 'tag 4'], [OneSet.new]),
|
69
|
+
Record.new(3, ['title 5', 'title 6'], 'creator', ['tag 5', 'tag 6'], [OneSet.new]),
|
70
|
+
Record.new(4, ['title 7', 'title 8'], 'creator', ['tag 9', 'tag 8'], [OneSet.new, TwoSet.new]),
|
71
|
+
Record.new(5, ['title 9', 'title 10'], 'creator', ['tag 9', 'tag 10'], [OneSet.new, TwoSet.new]),
|
72
|
+
]
|
73
|
+
|
74
|
+
class << self
|
75
|
+
def oai_earliest
|
76
|
+
Time.parse("2006-10-31T00:00:00Z")
|
77
|
+
end
|
78
|
+
|
79
|
+
def oai_sets
|
80
|
+
[OneSet.new, TwoSet.new]
|
81
|
+
end
|
82
|
+
|
83
|
+
def oai_find(selector, opts = {})
|
84
|
+
if selector == :all
|
85
|
+
if opts[:set]
|
86
|
+
return RECORDS.select { |rec| rec.in_set(opts[:set]) }
|
87
|
+
else
|
88
|
+
return RECORDS
|
89
|
+
end
|
90
|
+
else
|
91
|
+
RECORDS.each do |record|
|
92
|
+
return record if record.id.to_s == selector
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class MappedModel < SimpleModel
|
100
|
+
|
101
|
+
def self.map_oai_dc
|
102
|
+
{:title => :creator, :creator => :titles, :subject => :tags}
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
metadata
CHANGED
@@ -3,31 +3,31 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: oaipmh
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0.
|
7
|
-
date: 2006-11-
|
8
|
-
summary:
|
6
|
+
version: 0.0.2
|
7
|
+
date: 2006-11-07 00:00:00 -05:00
|
8
|
+
summary: OAI-PMH Provider
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
|
-
email:
|
11
|
+
email: will.groppe@gmail.com
|
12
12
|
homepage: http://oaipmh.rubyforge.org
|
13
13
|
rubyforge_project: oaipmh
|
14
|
-
description:
|
14
|
+
description: OAI-PMH Provider
|
15
15
|
autorequire: oaipmh
|
16
16
|
default_executable:
|
17
17
|
bindir: bin
|
18
18
|
has_rdoc: true
|
19
19
|
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
20
|
requirements:
|
21
|
-
- - "
|
21
|
+
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version:
|
23
|
+
version: 1.8.2
|
24
24
|
version:
|
25
25
|
platform: ruby
|
26
26
|
signing_key:
|
27
27
|
cert_chain:
|
28
28
|
post_install_message:
|
29
29
|
authors:
|
30
|
-
-
|
30
|
+
- Will Groppe
|
31
31
|
files:
|
32
32
|
- README
|
33
33
|
- CHANGELOG
|
@@ -44,6 +44,7 @@ files:
|
|
44
44
|
- lib/oaipmh/metadata.rb
|
45
45
|
- lib/oaipmh/model.rb
|
46
46
|
- lib/oaipmh/provider.rb
|
47
|
+
- lib/oaipmh/set.rb
|
47
48
|
- lib/oaipmh/version.rb
|
48
49
|
- lib/oaipmh/extensions/camping.rb
|
49
50
|
- lib/oaipmh/metadata/oai_dc.rb
|
@@ -70,5 +71,31 @@ extensions: []
|
|
70
71
|
|
71
72
|
requirements: []
|
72
73
|
|
73
|
-
dependencies:
|
74
|
-
|
74
|
+
dependencies:
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: activesupport
|
77
|
+
version_requirement:
|
78
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.3.1
|
83
|
+
version:
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: chronic
|
86
|
+
version_requirement:
|
87
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: 0.1.4
|
92
|
+
version:
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: builder
|
95
|
+
version_requirement:
|
96
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 2.0.0
|
101
|
+
version:
|