139
139
#
140
140
# Special thanks to Jose Hales-Garcia for this solution.
141
141
#
142
+ # ### Leverage the Provider instance
143
+ #
144
+ # The traditional implementation of the OAI::Provider would pass the OAI::Provider
145
+ # class to the different resposnes. This made it hard to inject context into a
146
+ # common provider. Consider that we might have different request headers that
147
+ # change the scope of the OAI::Provider queries.
148
+ #
149
+ # ```ruby
150
+ # class InstanceProvider
151
+ # def initialize(options = {})
152
+ # super({ :provider_context => :instance_based })
153
+ # @controller = options.fetch(:controller)
154
+ # end
155
+ # attr_reader :controller
156
+ # end
157
+ #
158
+ # class OaiController < ApplicationController
159
+ # def index
160
+ # provider = InstanceProvider.new({ :controller => self })
161
+ # request_body = provider.process_request(oai_params.to_h)
162
+ # render :body => request_body, :content_type => 'text/xml'
163
+ # end
164
+ # ```
165
+ #
166
+ # In the above example, the underlying response object will now receive an
167
+ # instance of the InstanceProvider. Without the `super({ :provider_context => :instance_based })`
168
+ # the response objects would have received the class InstanceProvider as the
169
+ # given provider.
170
+ #
142
171
# ## Supporting custom metadata formats
143
172
#
144
173
# See {OAI::MetadataFormat} for details.
@@ -292,39 +321,132 @@ def inherited(klass)
292
321
293
322
Base . register_format ( OAI ::Provider ::Metadata ::DublinCore . instance )
294
323
324
+ PROVIDER_CONTEXTS = {
325
+ :class_based => :class_based ,
326
+ :instance_based => :instance_based
327
+ }
328
+
329
+ def initialize ( options = { } )
330
+ provider_context = options . fetch ( :provider_context ) { :class_based }
331
+ @provider_context = PROVIDER_CONTEXTS . fetch ( provider_context )
332
+ end
333
+
334
+ # @note These are the accessor methods on the class. If you need to overwrite
335
+ # them on the instance level you can do that. However, an instance of this
336
+ # class won't be used unless you initialize with:
337
+ # { :provider_context => :instance_based }
338
+ attr_writer :name , :url , :prefix , :email , :delete_support , :granularity , :model , :identifier , :description
339
+
340
+ # The traditional interaction of a Provider has been to:
341
+ #
342
+ # 1) Assign attributes to the Provider class
343
+ # 2) Instantiate the Provider class
344
+ # 3) Call response instance methods for theProvider which pass
345
+ # the Provider class and not the instance.
346
+ #
347
+ # The above behavior continues unless you initialize the Provider with
348
+ # { :provider_context => :instance_based }. If you do that, then the
349
+ # Provider behavior will be:
350
+ #
351
+ # 1) Assign attributes to Provider class
352
+ # 2) Instantiate the Provider class
353
+ # 3) Call response instance methods for theProvider which pass an
354
+ # instance of the Provider to those response objects.
355
+ # a) The instance will mirror all of the assigned Provider class
356
+ # attributes, but allows for overriding and extending on a
357
+ # case by case basis.
358
+ # (Dear reader, please note the second behavior is something most
359
+ # of us would've assumed to be the case, but for historic now lost
360
+ # reasons is not the case.)
361
+ def provider_context
362
+ if @provider_context == :instance_based
363
+ self
364
+ else
365
+ self . class
366
+ end
367
+ end
368
+
369
+ def format_supported? ( *args )
370
+ self . class . format_supported? ( *args )
371
+ end
372
+
373
+ def format ( *args )
374
+ self . class . format ( *args )
375
+ end
376
+
377
+ def formats
378
+ self . class . formats
379
+ end
380
+
381
+ def name
382
+ @name || self . class . name
383
+ end
384
+
385
+ def url
386
+ @url || self . class . url
387
+ end
388
+
389
+ def prefix
390
+ @prefix || self . class . prefix
391
+ end
392
+
393
+ def email
394
+ @email || self . class . email
395
+ end
396
+
397
+ def delete_support
398
+ @delete_support || self . class . delete_support
399
+ end
400
+
401
+ def granularity
402
+ @granularity || self . class . granularity
403
+ end
404
+
405
+ def model
406
+ @model || self . class . model
407
+ end
408
+
409
+ def identifier
410
+ @identifier || self . class . identifier
411
+ end
412
+
413
+ def description
414
+ @description || self . class . description
415
+ end
416
+
295
417
# Equivalent to '&verb=Identify', returns information about the repository
296
418
def identify ( options = { } )
297
- Response ::Identify . new ( self . class , options ) . to_xml
419
+ Response ::Identify . new ( provider_context , options ) . to_xml
298
420
end
299
421
300
422
# Equivalent to '&verb=ListSets', returns a list of sets that are supported
301
423
# by the repository or an error if sets are not supported.
302
424
def list_sets ( options = { } )
303
- Response ::ListSets . new ( self . class , options ) . to_xml
425
+ Response ::ListSets . new ( provider_context , options ) . to_xml
304
426
end
305
427
306
428
# Equivalent to '&verb=ListMetadataFormats', returns a list of metadata formats
307
429
# supported by the repository.
308
430
def list_metadata_formats ( options = { } )
309
- Response ::ListMetadataFormats . new ( self . class , options ) . to_xml
431
+ Response ::ListMetadataFormats . new ( provider_context , options ) . to_xml
310
432
end
311
433
312
434
# Equivalent to '&verb=ListIdentifiers', returns a list of record headers that
313
435
# meet the supplied criteria.
314
436
def list_identifiers ( options = { } )
315
- Response ::ListIdentifiers . new ( self . class , options ) . to_xml
437
+ Response ::ListIdentifiers . new ( provider_context , options ) . to_xml
316
438
end
317
439
318
440
# Equivalent to '&verb=ListRecords', returns a list of records that meet the
319
441
# supplied criteria.
320
442
def list_records ( options = { } )
321
- Response ::ListRecords . new ( self . class , options ) . to_xml
443
+ Response ::ListRecords . new ( provider_context , options ) . to_xml
322
444
end
323
445
324
446
# Equivalent to '&verb=GetRecord', returns a record matching the required
325
447
# :identifier option
326
448
def get_record ( options = { } )
327
- Response ::GetRecord . new ( self . class , options ) . to_xml
449
+ Response ::GetRecord . new ( provider_context , options ) . to_xml
328
450
end
329
451
330
452
# xml_response = process_verb('ListRecords', :from => 'October 1, 2005',
@@ -336,7 +458,7 @@ def process_request(params = {})
336
458
begin
337
459
338
460
# Allow the request to pass in a url
339
- self . class . url = params [ 'url' ] ? params . delete ( 'url' ) : self . class . url
461
+ provider_context . url = params [ 'url' ] ? params . delete ( 'url' ) : self . url
340
462
341
463
verb = params . delete ( 'verb' ) || params . delete ( :verb )
342
464
0 commit comments