Skip to content

Commit eae3c6c

Browse files
committed
Allow switching on instance or class for provider
Prior to this commit, instance methods of the Provider class were passing the instance's class to the associated response classes. This was a surprise; Why would an instance method send as a parameter it's class instead of the instance method's instance? This made it difficult to add context to the Provider on a request by request basis; In our implementation, we wanted to pass the controller to the instantiated provider instance. Further, the following line of code was dangerous, in that it would override the URL for the entire class and all future uses. (Perhaps that's the OAI specification, but it's a dangerous class mutation) ```ruby self.class.url = params['url'] ? params.delete('url') : self.class.url ``` All told, this commit seeks to: * preserve backwards compatibility by adding instance methods that mirror the expected class methods used by the Response module's classes. * provide extensibility for downstream implementers when they instantiate an OAI::Provider
1 parent 45d8051 commit eae3c6c

File tree

3 files changed

+91
-8
lines changed

3 files changed

+91
-8
lines changed

lib/oai/provider.rb

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,10 @@ module OAI::Provider
240240
class Base
241241
include OAI::Provider
242242

243+
OAI_PMH_ATTRIBUTES = [:name, :url, :prefix, :email, :delete_support, :granularity, :model, :identifier, :description]
243244
class << self
244245
attr_reader :formats
245-
attr_accessor :name, :url, :prefix, :email, :delete_support, :granularity, :model, :identifier, :description
246+
attr_accessor(*OAI_PMH_ATTRIBUTES)
246247

247248
def register_format(format)
248249
@formats ||= {}
@@ -292,39 +293,72 @@ def inherited(klass)
292293

293294
Base.register_format(OAI::Provider::Metadata::DublinCore.instance)
294295

296+
PROVIDER_CONTEXTS = {
297+
:class_based => :class_based,
298+
:instance_based => :instance_based
299+
}
300+
301+
def initialize(provider_context = :class_based)
302+
@provider_context = PROVIDER_CONTEXTS.fetch(provider_context)
303+
OAI_PMH_ATTRIBUTES.each do |attr|
304+
instance_variable_set("@#{attr}", self.class.public_send(attr))
305+
end
306+
end
307+
attr_accessor(*OAI_PMH_ATTRIBUTES)
308+
309+
def provider_context
310+
if @provider_context == :class_based
311+
self.class
312+
else
313+
self
314+
end
315+
end
316+
317+
def format_supported?(*args)
318+
self.class.format_supported?(*args)
319+
end
320+
321+
def format(*args)
322+
self.class.format(*args)
323+
end
324+
325+
def formats
326+
self.class.formats
327+
end
328+
295329
# Equivalent to '&verb=Identify', returns information about the repository
296330
def identify(options = {})
297-
Response::Identify.new(self.class, options).to_xml
331+
Response::Identify.new(provider_context, options).to_xml
298332
end
299333

300334
# Equivalent to '&verb=ListSets', returns a list of sets that are supported
301335
# by the repository or an error if sets are not supported.
302336
def list_sets(options = {})
303-
Response::ListSets.new(self.class, options).to_xml
337+
Response::ListSets.new(provider_context, options).to_xml
304338
end
305339

306340
# Equivalent to '&verb=ListMetadataFormats', returns a list of metadata formats
307341
# supported by the repository.
308342
def list_metadata_formats(options = {})
309-
Response::ListMetadataFormats.new(self.class, options).to_xml
343+
Response::ListMetadataFormats.new(provider_context, options).to_xml
310344
end
311345

312346
# Equivalent to '&verb=ListIdentifiers', returns a list of record headers that
313347
# meet the supplied criteria.
314348
def list_identifiers(options = {})
315-
Response::ListIdentifiers.new(self.class, options).to_xml
349+
Response::ListIdentifiers.new(provider_context, options).to_xml
316350
end
317351

318352
# Equivalent to '&verb=ListRecords', returns a list of records that meet the
319353
# supplied criteria.
320354
def list_records(options = {})
321-
Response::ListRecords.new(self.class, options).to_xml
355+
Response::ListRecords.new(provider_context, options).to_xml
322356
end
323357

324358
# Equivalent to '&verb=GetRecord', returns a record matching the required
325359
# :identifier option
326360
def get_record(options = {})
327-
Response::GetRecord.new(self.class, options).to_xml
361+
Response::GetRecord.new(provider_context, options).to_xml
328362
end
329363

330364
# xml_response = process_verb('ListRecords', :from => 'October 1, 2005',
@@ -336,7 +370,7 @@ def process_request(params = {})
336370
begin
337371

338372
# Allow the request to pass in a url
339-
self.class.url = params['url'] ? params.delete('url') : self.class.url
373+
provider_context.url = params['url'] ? params.delete('url') : self.class.url
340374

341375
verb = params.delete('verb') || params.delete(:verb)
342376

test/provider/tc_instance_provider.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
require 'test_helper_provider'
2+
3+
class TestInstanceProvider < Test::Unit::TestCase
4+
5+
# Prior to the commit introducing this code, the InstanceProvider#identify
6+
# method would instantiate a Response::Identify object, passing the
7+
# InstanceProvider class as the provider for the Response::Identify
8+
# instance. With the commit introducing this test, the
9+
# InstanceProvider#identify now passes the instance of InstanceProvider
10+
# to the instantiation of Response::Identify.
11+
#
12+
# Thus we can override, on an instance by instance basis, the behavior of a
13+
# response object.
14+
def test_instance_used_in_responses
15+
@url_path = "/stringy-mc-string-face"
16+
@instance_provider = InstanceProvider.new(:instance_based, @url_path)
17+
18+
xml = @instance_provider.identify
19+
doc = REXML::Document.new(xml)
20+
assert_equal "http://localhost#{@url_path}", doc.elements["OAI-PMH/Identify/baseURL"].text
21+
end
22+
23+
def test_class_used_in_responses
24+
@url_path = "/stringy-mc-string-face"
25+
@instance_provider = InstanceProvider.new(:class_based, @url_path)
26+
27+
xml = @instance_provider.identify
28+
doc = REXML::Document.new(xml)
29+
assert_equal "http://localhost", doc.elements["OAI-PMH/Identify/baseURL"].text
30+
end
31+
32+
end

test/provider/test_helper_provider.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,20 @@ class DescribedProvider < Provider::Base
4343
sample_id '13900'
4444
extra_description "<my_custom_xml />"
4545
end
46+
47+
class InstanceProvider < Provider::Base
48+
repository_name 'Instance Provider'
49+
record_prefix 'oai:test'
50+
repository_url 'http://localhost'
51+
source_model SimpleModel.new
52+
53+
def initialize(context_provider, url_path)
54+
super(context_provider)
55+
@url_path = url_path
56+
end
57+
attr_reader :url_path
58+
59+
def url
60+
File.join(super, url_path)
61+
end
62+
end

0 commit comments

Comments
 (0)