oai 0.2.1 → 0.3.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.
Files changed (48) hide show
  1. data/README.md +28 -23
  2. data/Rakefile +14 -40
  3. data/examples/providers/dublin_core.rb +63 -63
  4. data/lib/oai/client.rb +131 -97
  5. data/lib/oai/client/list_identifiers.rb +1 -0
  6. data/lib/oai/client/list_records.rb +6 -5
  7. data/lib/oai/client/list_sets.rb +6 -5
  8. data/lib/oai/client/record.rb +6 -7
  9. data/lib/oai/client/response.rb +7 -4
  10. data/lib/oai/client/resumable.rb +42 -0
  11. data/lib/oai/harvester/shell.rb +40 -41
  12. data/lib/oai/provider.rb +85 -67
  13. data/lib/oai/provider/metadata_format/oai_dc.rb +5 -6
  14. data/lib/oai/provider/model/activerecord_caching_wrapper.rb +23 -25
  15. data/lib/oai/provider/model/activerecord_wrapper.rb +99 -51
  16. data/lib/oai/provider/response.rb +33 -31
  17. data/lib/oai/provider/response/get_record.rb +7 -7
  18. data/lib/oai/provider/response/list_records.rb +5 -4
  19. data/lib/oai/provider/response/record_response.rb +14 -14
  20. data/test/activerecord_provider/config/connection.rb +8 -4
  21. data/test/activerecord_provider/database/{ar_migration.rb → 0001_oaipmh_tables.rb} +17 -12
  22. data/test/activerecord_provider/helpers/providers.rb +2 -3
  23. data/test/activerecord_provider/helpers/set_provider.rb +10 -22
  24. data/test/activerecord_provider/helpers/transactional_test_case.rb +34 -0
  25. data/test/activerecord_provider/models/dc_field.rb +4 -4
  26. data/test/activerecord_provider/models/dc_set.rb +3 -2
  27. data/test/activerecord_provider/models/exclusive_set_dc_field.rb +11 -0
  28. data/test/activerecord_provider/tc_ar_provider.rb +67 -28
  29. data/test/activerecord_provider/tc_ar_sets_provider.rb +104 -18
  30. data/test/activerecord_provider/tc_caching_paging_provider.rb +6 -10
  31. data/test/activerecord_provider/tc_simple_paging_provider.rb +7 -11
  32. data/test/activerecord_provider/test_helper.rb +10 -0
  33. data/test/client/helpers/provider.rb +44 -47
  34. data/test/client/helpers/test_wrapper.rb +4 -16
  35. data/test/client/tc_http_client.rb +90 -2
  36. data/test/client/tc_list_identifiers.rb +22 -3
  37. data/test/client/tc_list_records.rb +17 -4
  38. data/test/client/tc_list_sets.rb +17 -2
  39. data/test/provider/models.rb +32 -30
  40. data/test/provider/tc_exceptions.rb +30 -20
  41. data/test/provider/tc_functional_tokens.rb +11 -6
  42. data/test/provider/tc_provider.rb +58 -24
  43. data/test/provider/tc_resumption_tokens.rb +6 -6
  44. data/test/provider/tc_simple_provider.rb +51 -26
  45. data/test/provider/test_helper.rb +7 -0
  46. metadata +67 -128
  47. data/test/activerecord_provider/config/database.yml +0 -6
  48. data/test/activerecord_provider/database/oaipmhtest +0 -0
@@ -1,7 +1,9 @@
1
1
  module OAI
2
2
 
3
- # An OAI::Response contains entries and a resumption token. If a resumption token is present,
3
+ # An OAI::Response contains entries and a resumption token. If a resumption token is present,
4
4
  # then you must use it to fetch the rest of the entries for your query. For example:
5
+ #
6
+ # ```ruby
5
7
  # # List all records in a given set
6
8
  # client = OAI::Client.new 'http://my-oai-provider.example.com/oai'
7
9
  # response = client.list_records :set => 'my_set_name'
@@ -13,14 +15,15 @@ module OAI
13
15
  # # Note: You do not need to pass the options hash again, just the verb and the resumption token
14
16
  # response = client.list_records :resumption_token => token if token
15
17
  # end
16
-
18
+ # ```
17
19
  class Response
18
20
  include OAI::XPath
19
- attr_reader :doc, :resumption_token
21
+ attr_reader :doc, :resumption_token, :resumption_block
20
22
 
21
- def initialize(doc)
23
+ def initialize(doc, &resumption_block)
22
24
  @doc = doc
23
25
  @resumption_token = xpath(doc, './/resumptionToken')
26
+ @resumption_block = resumption_block
24
27
 
25
28
  # throw an exception if there was an error
26
29
  error = xpath_first(doc, './/error')
@@ -0,0 +1,42 @@
1
+ module OAI
2
+ module Resumable
3
+
4
+ class ResumptionWrapper
5
+ include Enumerable
6
+
7
+ def initialize(response)
8
+ @response = response
9
+ @resumption_block = response.resumption_block
10
+ end
11
+
12
+ def each(&block)
13
+ yield_from_response &block
14
+ while resumable?
15
+ @response = @resumption_block.call @response
16
+ yield_from_response &block
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def yield_from_response(&block)
23
+ @response.each do |obj|
24
+ block.call(obj)
25
+ end
26
+ end
27
+
28
+ def resumable?
29
+ @response.resumption_token and not @response.resumption_token.empty?
30
+ end
31
+
32
+ end
33
+
34
+ def full
35
+ if @resumption_block.nil?
36
+ raise NotImplementedError.new("Resumption block not provided")
37
+ end
38
+ ResumptionWrapper.new(self)
39
+ end
40
+
41
+ end
42
+ end
@@ -1,13 +1,12 @@
1
1
  module OAI
2
2
  module Harvester
3
- # = OAI::Harvester::Shell
4
- #
5
3
  # A OAI-PMH client shell allowing OAI Harvesting to be configured in
6
- # an interactive manner. Typing 'oai' on the command line starts the
4
+ # an interactive manner. Typing `oai` on the command line starts the
7
5
  # shell. The first time the shell is run it will prompt for the following
8
6
  # configuration details:
9
- # 1. A storage directory for all harvested records. Harvests will be
10
- # stored under this directory in a directory structure based on the
7
+ #
8
+ # 1. A storage directory for all harvested records. Harvests will be
9
+ # stored under this directory in a directory structure based on the
11
10
  # date of the harvest.
12
11
  # 2. A log file directory.
13
12
  # 3. Email address(es) for sending daily harvesting activity reports.
@@ -21,15 +20,15 @@ module OAI
21
20
  #
22
21
  # The shell automatically pulls down the list of sets in the repository, and
23
22
  # the supported metadata prefixes. Making it very simple to setup harvests.
24
- #
23
+ #
25
24
  class Shell
26
25
  include Readline
27
-
26
+
28
27
  def initialize(config)
29
28
  @conf = config
30
29
  @conf.sites ||= {} # Initialize sites hash there isn't one
31
30
  end
32
-
31
+
33
32
  def start
34
33
  unless @conf.storage
35
34
  banner "Entering first-time setup"
@@ -54,9 +53,9 @@ module OAI
54
53
  end
55
54
  end
56
55
  end
57
-
56
+
58
57
  private
59
-
58
+
60
59
  def help
61
60
  banner "Commands:"
62
61
  puts "\tharvest site [date] - Harvest site(s) manually"
@@ -68,7 +67,7 @@ module OAI
68
67
  puts "\tedit [site] - Change settings for a provider site"
69
68
  puts "\texit - Exit the harvester shell.\n\n"
70
69
  end
71
-
70
+
72
71
  def harvest(options)
73
72
  site, *date = options.split(/\s/)
74
73
  if @conf.sites.keys.include?(site)
@@ -80,7 +79,7 @@ module OAI
80
79
  puts "Couldn't parse the date supplied"
81
80
  return
82
81
  end
83
- else
82
+ else
84
83
  date = nil
85
84
  end
86
85
  harvester = Harvest.new(@conf, @conf.storage, date)
@@ -91,7 +90,7 @@ module OAI
91
90
  end
92
91
  puts # blank line
93
92
  end
94
-
93
+
95
94
  def list(args = nil)
96
95
  if 'config' == args
97
96
  banner "Current Configuration"
@@ -104,7 +103,7 @@ module OAI
104
103
  end
105
104
  puts # blank line
106
105
  end
107
-
106
+
108
107
  def info(args)
109
108
  banner "Provider Site Information"
110
109
  sites = args.split(/[,\s|\s|,]/)
@@ -115,21 +114,21 @@ module OAI
115
114
  rescue
116
115
  puts args + " doesn't appear to be configured, use list to see configured repositories."
117
116
  end
118
-
117
+
119
118
  def new
120
119
  banner "Define New Harvesting Site"
121
120
  name, site = form
122
121
  @conf.sites[name] = site
123
122
  @conf.save
124
123
  end
125
-
124
+
126
125
  def edit(name)
127
126
  banner "Edit Harvesting Site"
128
127
  name, site = form(name)
129
128
  @conf.sites[name] = site
130
129
  @conf.save
131
130
  end
132
-
131
+
133
132
  def remove(site)
134
133
  if 'Y' == readline("Remove #{site}? (Y/N): ").upcase
135
134
  @conf.sites.delete(site)
@@ -149,14 +148,14 @@ module OAI
149
148
  end
150
149
  end
151
150
  site = @conf.sites[name] || {}
152
-
151
+
153
152
  # URL
154
153
  url = prompt("url", site['url'])
155
154
  while(not (site['url'] = verify(url)))
156
155
  puts "Trouble contacting provider, bad url?"
157
156
  url = prompt("url", site['url'])
158
157
  end
159
-
158
+
160
159
  # Metadata formats
161
160
  formats = metadata(site['url'])
162
161
  report "Repository supports [#{formats.join(', ')}] metadata formats."
@@ -187,15 +186,15 @@ module OAI
187
186
  puts "Must be daily, weekly, or monthly"
188
187
  period = expand_period(prompt("period", "daily"))
189
188
  end
190
-
189
+
191
190
  site['period'] = period
192
-
191
+
193
192
  return [name, site]
194
- rescue
193
+ rescue
195
194
  puts "Problem adding/updating provider, aborting. (#{$!})"
196
195
  end
197
196
  end
198
-
197
+
199
198
  def config
200
199
  begin
201
200
  directory = prompt("storage directory", @conf.storage)
@@ -205,7 +204,7 @@ module OAI
205
204
 
206
205
  email = @conf.email.join(', ') rescue nil
207
206
  @conf.email = parse_emails(prompt("email", email))
208
-
207
+
209
208
  @conf.mail_server = prompt("mail server", @conf.mail_server)
210
209
 
211
210
  logfile = prompt("log file(s) directory", @conf.logfile)
@@ -215,22 +214,22 @@ module OAI
215
214
  @conf.storage = directory
216
215
  @conf.logfile = logfile
217
216
  @conf.save
218
- rescue
217
+ rescue
219
218
  nil
220
219
  end
221
220
  end
222
-
221
+
223
222
  def display(key, value, split = 40)
224
223
  (split - key.size).times { print " " } if key.size < split
225
224
  puts "#{key}: #{value}"
226
225
  end
227
-
226
+
228
227
  def banner(str)
229
228
  puts "\n#{str}"
230
229
  str.size.times { print "-" }
231
230
  puts "\n"
232
231
  end
233
-
232
+
234
233
  def report(str)
235
234
  puts "\n#{str}\n"
236
235
  end
@@ -240,7 +239,7 @@ module OAI
240
239
  print "\t"
241
240
  end
242
241
  end
243
-
242
+
244
243
  def prompt(text, default = nil, split = 20)
245
244
  prompt_text = "#{text} [#{default}]: "
246
245
  (split - prompt_text.size).times { print " " } if prompt_text.size < split
@@ -248,7 +247,7 @@ module OAI
248
247
  raise RuntimeError.new("Exit loop") unless value
249
248
  return value.empty? ? default : value
250
249
  end
251
-
250
+
252
251
  def verify(url)
253
252
  begin
254
253
  client = OAI::Client.new(url, :redirects => false)
@@ -264,7 +263,7 @@ module OAI
264
263
  end
265
264
  end
266
265
  end
267
-
266
+
268
267
  def metadata(url)
269
268
  formats = []
270
269
  client = OAI::Client.new url
@@ -274,7 +273,7 @@ module OAI
274
273
  end
275
274
  formats
276
275
  end
277
-
276
+
278
277
  def sets(url)
279
278
  sets = []
280
279
  client = OAI::Client.new url
@@ -292,35 +291,35 @@ module OAI
292
291
  end
293
292
  true
294
293
  end
295
-
294
+
296
295
  def expand_period(str)
297
296
  return str if Config::PERIODS.include?(str)
298
297
  Config::PERIODS.each { |p| return p if p =~ /^#{str}/}
299
298
  nil
300
299
  end
301
-
300
+
302
301
  def parse_emails(emails)
303
302
  return nil unless emails
304
303
  addresses = emails.split(/[,\s|\s|,]/)
305
304
  end
306
-
305
+
307
306
  def list_config
308
307
  display("storage directory", @conf.storage, 20)
309
308
  display("email", @conf.email.join(', '), 20) if @conf.email
310
309
  display("mail server", @conf.mail_server, 20) if @conf.mail_server
311
310
  display("log location", @conf.logfile, 20) if @conf.logfile
312
311
  end
313
-
312
+
314
313
  def list_sites
315
314
  banner "Sites"
316
315
  @conf.sites.each_key { |site| print_site(site) }
317
316
  end
318
-
317
+
319
318
  def print_site(site)
320
319
  puts site
321
320
  @conf.sites[site].each { |k,v| display(k, v, 15)}
322
321
  end
323
-
322
+
324
323
  def setup_cron
325
324
  banner "Scheduling Automatic Harvesting"
326
325
  puts "To activate automatic harvesting you must add an entry to"
@@ -330,9 +329,9 @@ module OAI
330
329
  puts "Windows users should use WinAt to schedule"
331
330
  puts "#{$0} to run every night.\n\n\n"
332
331
  end
333
-
332
+
334
333
  end
335
334
 
336
335
  end
337
- end
338
-
336
+ end
337
+
@@ -11,21 +11,21 @@ end
11
11
 
12
12
  %w{ response metadata_format resumption_token model partial_result
13
13
  response/record_response response/identify response/get_record
14
- response/list_identifiers response/list_records
14
+ response/list_identifiers response/list_records
15
15
  response/list_metadata_formats response/list_sets response/error
16
16
  }.each { |lib| require File.dirname(__FILE__) + "/provider/#{lib}" }
17
-
17
+
18
18
  if defined?(ActiveRecord)
19
19
  require File.dirname(__FILE__) + "/provider/model/activerecord_wrapper"
20
20
  require File.dirname(__FILE__) + "/provider/model/activerecord_caching_wrapper"
21
21
  end
22
22
 
23
- # = OAI::Provider
23
+ # # OAI::Provider
24
24
  #
25
- # Open Archives Initiative - Protocol for Metadata Harvesting see
26
- # http://www.openarchives.org/
25
+ # Open Archives Initiative - Protocol for Metadata Harvesting see
26
+ # <http://www.openarchives.org/>
27
27
  #
28
- # == Features
28
+ # ## Features
29
29
  # * Easily setup a simple repository
30
30
  # * Simple integration with ActiveRecord
31
31
  # * Dublin Core metadata format included
@@ -33,13 +33,14 @@ end
33
33
  # * Adaptable to any data source
34
34
  # * Simple resumption token support
35
35
  #
36
- # == Usage
36
+ # ## Usage
37
37
  #
38
- # To create a functional provider either subclass Provider::Base,
38
+ # To create a functional provider either subclass {OAI::Provider::Base},
39
39
  # or reconfigure the defaults.
40
- #
41
- # === Sub classing a provider
42
40
  #
41
+ # ### Sub classing a provider
42
+ #
43
+ # ```ruby
43
44
  # class MyProvider < Oai::Provider
44
45
  # repository_name 'My little OAI provider'
45
46
  # repository_url 'http://localhost/provider'
@@ -47,9 +48,11 @@ end
47
48
  # admin_email 'root@localhost' # String or Array
48
49
  # source_model MyModel.new # Subclass of OAI::Provider::Model
49
50
  # end
51
+ # ```
50
52
  #
51
- # === Configuring the default provider
53
+ # ### Configuring the default provider
52
54
  #
55
+ # ```ruby
53
56
  # class Oai::Provider::Base
54
57
  # repository_name 'My little OAI Provider'
55
58
  # repository_url 'http://localhost/provider'
@@ -58,23 +61,27 @@ end
58
61
  # sample_identifier 'oai:pubmedcentral.gov:13900'
59
62
  # source_model MyModel.new
60
63
  # end
64
+ # ```
61
65
  #
62
66
  # The provider does allow a URL to be passed in at request processing time
63
67
  # in case the repository URL cannot be determined ahead of time.
64
68
  #
65
- # == Integrating with frameworks
69
+ # ## Integrating with frameworks
66
70
  #
67
- # === Camping
71
+ # ### Camping
68
72
  #
69
73
  # In the Models module of your camping application post model definition:
70
- #
74
+ #
75
+ # ```ruby
71
76
  # class CampingProvider < OAI::Provider::Base
72
77
  # repository_name 'Camping Test OAI Repository'
73
78
  # source_model ActiveRecordWrapper.new(YOUR_ACTIVE_RECORD_MODEL)
74
79
  # end
80
+ # ```
75
81
  #
76
82
  # In the Controllers module:
77
83
  #
84
+ # ```ruby
78
85
  # class Oai
79
86
  # def get
80
87
  # @headers['Content-Type'] = 'text/xml'
@@ -82,15 +89,17 @@ end
82
89
  # provider.process_request(@input.merge(:url => "http:"+URL(Oai).to_s))
83
90
  # end
84
91
  # end
92
+ # ```
85
93
  #
86
94
  # The provider will be available at "/oai"
87
95
  #
88
- # === Rails
96
+ # ### Rails
89
97
  #
90
98
  # At the bottom of environment.rb create a OAI Provider:
91
99
  #
100
+ # ```ruby
92
101
  # # forgive the standard blog example.
93
- #
102
+ #
94
103
  # require 'oai'
95
104
  # class BlogProvider < OAI::Provider::Base
96
105
  # repository_name 'My little OAI Provider'
@@ -100,9 +109,11 @@ end
100
109
  # source_model OAI::Provider::ActiveRecordWrapper.new(Post)
101
110
  # sample_identifier 'oai:pubmedcentral.gov:13900'
102
111
  # end
112
+ # ```
103
113
  #
104
114
  # Create a custom controller:
105
115
  #
116
+ # ```ruby
106
117
  # class OaiController < ApplicationController
107
118
  # def index
108
119
  # # Remove controller and action from the options. Rails adds them automatically.
@@ -112,50 +123,54 @@ end
112
123
  # render :text => response, :content_type => 'text/xml'
113
124
  # end
114
125
  # end
126
+ # ```
115
127
  #
116
- # Special thanks to Jose Hales-Garcia for this solution.
128
+ # Special thanks to Jose Hales-Garcia for this solution.
117
129
  #
118
- # == Supporting custom metadata formats
130
+ # ## Supporting custom metadata formats
119
131
  #
120
- # See Oai::Metadata for details.
121
- #
122
- # == ActiveRecord Integration
132
+ # See {OAI::MetadataFormat} for details.
123
133
  #
124
- # ActiveRecord integration is provided by the ActiveRecordWrapper class.
134
+ # ## ActiveRecord Integration
135
+ #
136
+ # ActiveRecord integration is provided by the `ActiveRecordWrapper` class.
125
137
  # It takes one required paramater, the class name of the AR class to wrap,
126
138
  # and optional hash of options.
127
139
  #
128
140
  # Valid options include:
129
- # * timestamp_field - Specifies the model field to use as the update
130
- # filter. Defaults to 'updated_at'.
131
- # * limit - Maximum number of records to return in each page/set.
132
- # Defaults to 100. The wrapper will paginate the result via resumption tokens.
133
- # Caution: specifying too large a limit will adversely affect performance.
134
- #
141
+ #
142
+ # * `timestamp_field` - Specifies the model field to use as the update
143
+ # filter. Defaults to `updated_at`.
144
+ # * `limit` - Maximum number of records to return in each page/set.
145
+ # Defaults to 100.
146
+ # The wrapper will paginate the result via resumption tokens.
147
+ # _Caution: specifying too large a limit will adversely affect performance._
148
+ #
135
149
  # Mapping from a ActiveRecord object to a specific metadata format follows
136
150
  # this set of rules:
137
151
  #
138
- # 1. Does Model#to_{metadata_prefix} exist? If so just return the result.
139
- # 2. Does the model provide a map via Model.map_{metadata_prefix}? If so
152
+ # 1. Does `Model#to_{metadata_prefix}` exist? If so just return the result.
153
+ # 2. Does the model provide a map via `Model.map_{metadata_prefix}`? If so
140
154
  # use the map to generate the xml document.
141
155
  # 3. Loop thru the fields of the metadata format and check to see if the
142
156
  # model responds to either the plural, or singular of the field.
143
157
  #
144
158
  # For maximum control of the xml metadata generated, it's usually best to
145
- # provide a 'to_{metadata_prefix}' in the model. If using Builder be sure
146
- # not to include any instruct! in the xml object.
147
- #
148
- # === Explicit creation example
159
+ # provide a `to_{metadata_prefix}` in the model. If using Builder be sure
160
+ # not to include any `instruct!` in the xml object.
149
161
  #
162
+ # ### Explicit creation example
163
+ #
164
+ # ```ruby
150
165
  # class Post < ActiveRecord::Base
151
166
  # def to_oai_dc
152
167
  # xml = Builder::XmlMarkup.new
153
- # xml.tag!("oai_dc:dc",
168
+ # xml.tag!("oai_dc:dc",
154
169
  # 'xmlns:oai_dc' => "http://www.openarchives.org/OAI/2.0/oai_dc/",
155
170
  # 'xmlns:dc' => "http://purl.org/dc/elements/1.1/",
156
171
  # 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
157
- # 'xsi:schemaLocation' =>
158
- # %{http://www.openarchives.org/OAI/2.0/oai_dc/
172
+ # 'xsi:schemaLocation' =>
173
+ # %{http://www.openarchives.org/OAI/2.0/oai_dc/
159
174
  # http://www.openarchives.org/OAI/2.0/oai_dc.xsd}) do
160
175
  # xml.tag!('oai_dc:title', title)
161
176
  # xml.tag!('oai_dc:description', text)
@@ -166,24 +181,27 @@ end
166
181
  # end
167
182
  # xml.target!
168
183
  # end
169
- # end
184
+ # end
185
+ # ```
170
186
  #
171
- # === Mapping Example
187
+ # ### Mapping Example
172
188
  #
189
+ # ```ruby
173
190
  # # Extremely contrived mapping
174
191
  # class Post < ActiveRecord::Base
175
192
  # def self.map_oai_dc
176
- # {:subject => :tags,
177
- # :description => :text,
178
- # :creator => :user,
193
+ # {:subject => :tags,
194
+ # :description => :text,
195
+ # :creator => :user,
179
196
  # :contibutor => :comments}
180
197
  # end
181
198
  # end
199
+ # ```
182
200
  #
183
201
  module OAI::Provider
184
202
  class Base
185
203
  include OAI::Provider
186
-
204
+
187
205
  class << self
188
206
  attr_reader :formats
189
207
  attr_accessor :name, :url, :prefix, :email, :delete_support, :granularity, :model, :identifier, :description
@@ -192,11 +210,11 @@ module OAI::Provider
192
210
  @formats ||= {}
193
211
  @formats[format.prefix] = format
194
212
  end
195
-
213
+
196
214
  def format_supported?(prefix)
197
215
  @formats.keys.include?(prefix)
198
216
  end
199
-
217
+
200
218
  def format(prefix)
201
219
  if @formats[prefix].nil?
202
220
  raise OAI::FormatException.new
@@ -205,8 +223,8 @@ module OAI::Provider
205
223
  end
206
224
  end
207
225
 
208
- protected
209
-
226
+ protected
227
+
210
228
  def inherited(klass)
211
229
  self.instance_variables.each do |iv|
212
230
  klass.instance_variable_set(iv, self.instance_variable_get(iv))
@@ -217,12 +235,12 @@ module OAI::Provider
217
235
  alias_method :repository_url, :url=
218
236
  alias_method :record_prefix, :prefix=
219
237
  alias_method :admin_email, :email=
220
- alias_method :deletion_support, :delete_support=
221
- alias_method :update_granularity, :granularity=
238
+ alias_method :deletion_support, :delete_support=
239
+ alias_method :update_granularity, :granularity=
222
240
  alias_method :source_model, :model=
223
241
  alias_method :sample_id, :identifier=
224
242
  alias_method :extra_description, :description=
225
-
243
+
226
244
  end
227
245
 
228
246
  # Default configuration of a repository
@@ -235,7 +253,7 @@ module OAI::Provider
235
253
  Base.sample_id '13900'
236
254
 
237
255
  Base.register_format(OAI::Provider::Metadata::DublinCore.instance)
238
-
256
+
239
257
  # Equivalent to '&verb=Identify', returns information about the repository
240
258
  def identify(options = {})
241
259
  Response::Identify.new(self.class, options).to_xml
@@ -246,33 +264,33 @@ module OAI::Provider
246
264
  def list_sets(options = {})
247
265
  Response::ListSets.new(self.class, options).to_xml
248
266
  end
249
-
267
+
250
268
  # Equivalent to '&verb=ListMetadataFormats', returns a list of metadata formats
251
269
  # supported by the repository.
252
270
  def list_metadata_formats(options = {})
253
271
  Response::ListMetadataFormats.new(self.class, options).to_xml
254
272
  end
255
273
 
256
- # Equivalent to '&verb=ListIdentifiers', returns a list of record headers that
274
+ # Equivalent to '&verb=ListIdentifiers', returns a list of record headers that
257
275
  # meet the supplied criteria.
258
276
  def list_identifiers(options = {})
259
277
  Response::ListIdentifiers.new(self.class, options).to_xml
260
278
  end
261
-
262
- # Equivalent to '&verb=ListRecords', returns a list of records that meet the
279
+
280
+ # Equivalent to '&verb=ListRecords', returns a list of records that meet the
263
281
  # supplied criteria.
264
282
  def list_records(options = {})
265
283
  Response::ListRecords.new(self.class, options).to_xml
266
284
  end
267
-
285
+
268
286
  # Equivalent to '&verb=GetRecord', returns a record matching the required
269
- # :identifier option
287
+ # :identifier option
270
288
  def get_record(options = {})
271
289
  Response::GetRecord.new(self.class, options).to_xml
272
290
  end
273
-
274
- # xml_response = process_verb('ListRecords', :from => 'October 1, 2005',
275
- # :until => 'November 1, 2005')
291
+
292
+ # xml_response = process_verb('ListRecords', :from => 'October 1, 2005',
293
+ # :until => 'November 1, 2005')
276
294
  #
277
295
  # If you are implementing a web interface using process_request is the
278
296
  # preferred way.
@@ -281,14 +299,14 @@ module OAI::Provider
281
299
 
282
300
  # Allow the request to pass in a url
283
301
  self.class.url = params['url'] ? params.delete('url') : self.class.url
284
-
302
+
285
303
  verb = params.delete('verb') || params.delete(:verb)
286
-
304
+
287
305
  unless verb and OAI::Const::VERBS.keys.include?(verb)
288
306
  raise OAI::VerbException.new
289
307
  end
290
-
291
- send(methodize(verb), params)
308
+
309
+ send(methodize(verb), params)
292
310
 
293
311
  rescue => err
294
312
  if err.respond_to?(:code)
@@ -298,12 +316,12 @@ module OAI::Provider
298
316
  end
299
317
  end
300
318
  end
301
-
319
+
302
320
  # Convert valid OAI-PMH verbs into ruby method calls
303
321
  def methodize(verb)
304
322
  verb.gsub(/[A-Z]/) {|m| "_#{m.downcase}"}.sub(/^\_/,'')
305
323
  end
306
-
324
+
307
325
  end
308
-
326
+
309
327
  end