exlibris-aleph 0.1.6 → 1.0.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 (101) hide show
  1. data/README.md +89 -0
  2. data/Rakefile +2 -4
  3. data/lib/exlibris-aleph.rb +8 -21
  4. data/lib/exlibris/aleph.rb +13 -0
  5. data/lib/exlibris/aleph/abstract.rb +28 -0
  6. data/lib/exlibris/aleph/config.rb +78 -0
  7. data/lib/exlibris/aleph/patron.rb +71 -56
  8. data/lib/exlibris/aleph/record.rb +34 -40
  9. data/lib/exlibris/aleph/rest/base.rb +56 -0
  10. data/lib/exlibris/aleph/tab_helper.rb +84 -99
  11. data/lib/exlibris/aleph/{config/config_base.rb → tabs_parser/base.rb} +2 -2
  12. data/lib/exlibris/aleph/{config → tabs_parser}/pc_tab_exp_field_extended.rb +2 -2
  13. data/lib/exlibris/aleph/{config/config_by_sub_library.rb → tabs_parser/sub_library.rb} +2 -2
  14. data/lib/exlibris/aleph/{config → tabs_parser}/tab15_by_item_process_status.rb +2 -2
  15. data/lib/exlibris/aleph/{config → tabs_parser}/tab15_by_item_status.rb +2 -2
  16. data/lib/exlibris/aleph/{config → tabs_parser}/tab31.rb +2 -2
  17. data/lib/exlibris/aleph/{config → tabs_parser}/tab37.rb +2 -2
  18. data/lib/exlibris/aleph/{config → tabs_parser}/tab40.rb +2 -2
  19. data/lib/exlibris/aleph/{config → tabs_parser}/tab_sub_library.rb +2 -2
  20. data/lib/exlibris/aleph/{config → tabs_parser}/tab_www_item_desc.rb +2 -2
  21. data/lib/exlibris/aleph/task_installer.rb +23 -0
  22. data/lib/exlibris/aleph/version.rb +1 -1
  23. data/lib/exlibris/aleph/write_attributes.rb +38 -0
  24. data/lib/exlibris/aleph/xml_util.rb +50 -0
  25. data/lib/exlibris/aleph/xservice/bor_auth.rb +47 -0
  26. data/lib/tasks/exlibris-aleph_tasks.rake +1 -8
  27. data/test/{dummy/config → config}/aleph/alephe/sub_libraries.yml +0 -1
  28. data/test/{dummy/config → config}/aleph/nyu50/collections.yml +0 -1
  29. data/test/{dummy/config → config}/aleph/nyu50/item_permissions_by_item_process_status.yml +0 -1
  30. data/test/{dummy/config → config}/aleph/nyu50/item_permissions_by_item_status.yml +104 -105
  31. data/test/{dummy/config → config}/aleph/nyu50/items.yml +0 -1
  32. data/test/{dummy/config → config}/aleph/nyu50/patron_permissions.yml +27 -28
  33. data/test/{dummy/config → config}/aleph/nyu50/patrons.yml +0 -1
  34. data/test/{dummy/config → config}/aleph/nyu50/pickup_locations.yml +0 -1
  35. data/test/{dummy/config → config}/aleph/nyu51/collections.yml +0 -1
  36. data/test/{dummy/config → config}/aleph/nyu51/item_permissions_by_item_process_status.yml +0 -1
  37. data/test/{dummy/config → config}/aleph/nyu51/item_permissions_by_item_status.yml +6 -7
  38. data/test/{dummy/config → config}/aleph/nyu51/items.yml +0 -1
  39. data/test/{dummy/config → config}/aleph/nyu51/patron_permissions.yml +27 -28
  40. data/test/{dummy/config → config}/aleph/nyu51/patrons.yml +0 -1
  41. data/test/{dummy/config → config}/aleph/nyu51/pickup_locations.yml +0 -1
  42. data/test/config_test.rb +24 -0
  43. data/test/patron_test.rb +98 -0
  44. data/test/{unit/record_benchmarks.rb → record_benchmarks.rb} +0 -0
  45. data/test/record_test.rb +64 -0
  46. data/test/support/config.yml +2 -0
  47. data/test/{unit/tab_helper_benchmarks.rb → tab_helper_benchmarks.rb} +5 -20
  48. data/test/tab_helper_test.rb +178 -0
  49. data/test/test_helper.rb +26 -22
  50. data/test/vcr_cassettes/bor_auth.yml +8 -10
  51. data/test/vcr_cassettes/patron.yml +77 -18
  52. data/test/vcr_cassettes/patron_address.yml +45 -0
  53. data/test/vcr_cassettes/patron_bogus_url.yml +731 -0
  54. data/test/vcr_cassettes/patron_error.yml +93 -0
  55. data/test/vcr_cassettes/record.yml +18 -17
  56. data/test/vcr_cassettes/record_bogus_url.yml +690 -0
  57. data/test/{unit → xservice}/bor_auth_test.rb +4 -4
  58. metadata +160 -150
  59. data/README.rdoc +0 -67
  60. data/lib/exlibris/aleph/bor_auth.rb +0 -45
  61. data/lib/exlibris/aleph/railtie.rb +0 -9
  62. data/lib/exlibris/aleph/rest.rb +0 -43
  63. data/lib/exlibris/aleph/tasks.rb +0 -25
  64. data/test/dummy/README.rdoc +0 -261
  65. data/test/dummy/Rakefile +0 -7
  66. data/test/dummy/app/assets/javascripts/application.js +0 -15
  67. data/test/dummy/app/assets/stylesheets/application.css +0 -13
  68. data/test/dummy/app/controllers/application_controller.rb +0 -3
  69. data/test/dummy/app/helpers/application_helper.rb +0 -2
  70. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  71. data/test/dummy/config.ru +0 -4
  72. data/test/dummy/config/application.rb +0 -56
  73. data/test/dummy/config/boot.rb +0 -10
  74. data/test/dummy/config/database.yml +0 -25
  75. data/test/dummy/config/environment.rb +0 -5
  76. data/test/dummy/config/environments/development.rb +0 -37
  77. data/test/dummy/config/environments/production.rb +0 -67
  78. data/test/dummy/config/environments/test.rb +0 -37
  79. data/test/dummy/config/initializers/aleph.rb +0 -1
  80. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  81. data/test/dummy/config/initializers/inflections.rb +0 -15
  82. data/test/dummy/config/initializers/mime_types.rb +0 -5
  83. data/test/dummy/config/initializers/secret_token.rb +0 -7
  84. data/test/dummy/config/initializers/session_store.rb +0 -8
  85. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  86. data/test/dummy/config/locales/en.yml +0 -5
  87. data/test/dummy/config/routes.rb +0 -58
  88. data/test/dummy/db/README +0 -0
  89. data/test/dummy/db/test.sqlite3 +0 -0
  90. data/test/dummy/log/aleph/aleph_tab_helper.log +0 -1
  91. data/test/dummy/log/aleph/tab_helper.log +0 -109
  92. data/test/dummy/log/tab_helper.log +0 -16
  93. data/test/dummy/log/test.log +0 -5160
  94. data/test/dummy/public/404.html +0 -26
  95. data/test/dummy/public/422.html +0 -26
  96. data/test/dummy/public/500.html +0 -25
  97. data/test/dummy/public/favicon.ico +0 -0
  98. data/test/dummy/script/rails +0 -6
  99. data/test/unit/patron_test.rb +0 -41
  100. data/test/unit/record_test.rb +0 -32
  101. data/test/unit/tab_helper_test.rb +0 -222
data/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # Exlibris::Aleph
2
+ [![Gem Version](https://badge.fury.io/rb/exlibris-aleph.png)](http://badge.fury.io/rb/exlibris-aleph)
3
+ [![Build Status](https://api.travis-ci.org/scotdalton/exlibris-aleph.png?branch=master)](https://travis-ci.org/scotdalton/exlibris-aleph)
4
+ [![Dependency Status](https://gemnasium.com/scotdalton/exlibris-aleph.png)](https://gemnasium.com/scotdalton/exlibris-aleph)
5
+ [![Code Climate](https://codeclimate.com/github/scotdalton/exlibris-aleph.png)](https://codeclimate.com/github/scotdalton/exlibris-aleph)
6
+ [![Coverage Status](https://coveralls.io/repos/scotdalton/exlibris-aleph/badge.png?branch=master)](https://coveralls.io/r/scotdalton/exlibris-aleph)
7
+
8
+ Exlibris::Aleph offers a set of libraries for interacting with the ExLibris Aleph ILS.
9
+
10
+ ## Exlibris::Aleph::Patron
11
+ Exlibris::Aleph::Patron provides access to the Aleph Patron REST API.
12
+
13
+ ### Example of Exlibris::Aleph::Patron in action
14
+ patron =
15
+ Exlibris::Aleph::Patron.
16
+ new(patron_id: "S0M31D", rest_url: "http://aleph.institution.edu")
17
+ patron.address # Returns a Hash of the of patron's address
18
+ patron.loans # Returns an Array of institution Hashes, each containing an Array of the patron's loans for that institution
19
+ patron.renew_loans # Renews all loans
20
+ patron.renew_loans("ADM5000000001") # Renews loan of item 00000001 in ADM50
21
+ patron.place_hold("ADM50", "SBLIB", "00000001", "00000001", {:pickup_location => "SBLIB"}) # Places hold on the specified item for pickup at SBLIB
22
+
23
+ ## Exlibris::Aleph::Record
24
+ Provides access to the Aleph Record REST API.
25
+
26
+ ### Example of Exlibris::Aleph::Record in action
27
+ record =
28
+ Exlibris::Aleph::Record.
29
+ new(bib_library: "ADM50", record_id: "00000001", rest_url: "http://aleph.institution.edu")
30
+ record.bib # Returns a MARC::Record with bibliographic metadata
31
+ record.holdings # Returns and Array of MARC::Records respresenting the record's holdings
32
+ record.items # Returns and Array of Hashes representing the record's items
33
+
34
+ ## Exlibris::Aleph.configure
35
+ Exlibris::Aleph can be configured at startup in an initializer.
36
+
37
+ # Placed this in an initializer.
38
+ Exlibris::Aleph.configure { |c|
39
+ c.base_url = "http://aleph.institution.edu"
40
+ c.tab_path = "/mnt/aleph_tab"
41
+ c.adms = ["ADM50", "ADM51"]
42
+ }
43
+
44
+ It can also read from a yaml file.
45
+
46
+ # Placed this in an initializer.
47
+ Exlibris::Aleph.configure { |c|
48
+ config.load_yaml File.expand_path("#{File.dirname(__FILE__)}/../config/aleph.yml", __FILE__)
49
+ }
50
+
51
+ ## Exlibris::Aleph::TabHelper
52
+ Exlibris::Aleph::TabHelper provides a way to access the various tab settings for patrons, patron\_permissions, items, item_permission (both by item status and by item processing status), collections and pickup locations. It also provides convenience methods for common tasks like getting the pickup location for a given combination of item status, item process status and borrower status or getting an item's web text. Support a
53
+
54
+ ### Example of Exlibris::Aleph::TabHelper in action
55
+ # Placed this in an initializer.
56
+ Exlibris::Aleph.configure { |c|
57
+ c.tab_path = "/mnt/aleph_tab"
58
+ c.adms = ["ADM50", "ADM51"]
59
+ }
60
+
61
+ # Rake task to refresh the config yml files
62
+ rake exlibris:aleph:refresh
63
+
64
+ # Get an instance of TabHelper
65
+ helper = Exlibris::Aleph::TabHelper.instance
66
+ helper.sub_library_text("SBLIB") # Returns display text for the give code
67
+ helper.sub_library_adm("SBLIB") # Returns ADM for the give code
68
+ helper.item_pickup_locations({:adm_library_code => "ADM50", :sub_library_code => "SBLIB", :bor_status => "51"}) # Returns the pickup locations for the given parameters
69
+ helper.collection_text({:adm_library_code => "ADM50", :sub_library_code => "SBLIB", :collection_code => "MAIN"}) # Returns the collection display text for the give parameters
70
+ helper.item_web_text({:adm_library_code => "ADM50", :item_process_status => "Item Process Status"}) # Returns the web text for the given parameters
71
+ helper.item_web_text({:adm_library_code => "ADM50", :sub_library_code => "SBLIB", :item_process_status_code => "DP"}) # Returns the web text for the given parameters
72
+
73
+ ### Configure irrelevant sub libraries for TabHelper
74
+ To configure the gem to ignore sub libraries pulled from Aleph but not relevant to working with permissions call the following setter with an array of sub library Aleph codes.
75
+
76
+ # Place this in an initializer to replace the current irrelevant sub libraries.
77
+ Exlibris::Aleph.configure { |c|
78
+ c.irrelevant_sub_libraries = ["IRRLIB1", "IRRLIB2"]
79
+ }
80
+
81
+ ## Exlibris::Aleph::BorAuth
82
+ Exlibris::Aleph::BorAuth provides access to the BorAuth Aleph XService.
83
+
84
+ ### Example of Exlibris::Aleph::BorAuth in action
85
+ bor_auth =
86
+ Exlibris::Aleph::BorAuth.
87
+ new("http://aleph.institution.edu", "ADM50", "SBLIB", "N", "S0M31D", "V3R1F1C@T10N")
88
+ permissions = bor_auth.permissions # Return a Hash of permissions based on the Exlibris::Aleph::BorAuth instance
89
+
data/Rakefile CHANGED
@@ -20,9 +20,6 @@ RDoc::Task.new(:rdoc) do |rdoc|
20
20
  rdoc.rdoc_files.include('lib/**/*.rb')
21
21
  end
22
22
 
23
-
24
-
25
-
26
23
  Bundler::GemHelper.install_tasks
27
24
 
28
25
  require 'rake/testtask'
@@ -34,5 +31,6 @@ Rake::TestTask.new(:test) do |t|
34
31
  t.verbose = false
35
32
  end
36
33
 
37
-
38
34
  task :default => :test
35
+
36
+ require 'exlibris-aleph'
@@ -1,21 +1,8 @@
1
- PATH = File.dirname(__FILE__) + "/exlibris/aleph/"
2
- [
3
- 'config/config_base',
4
- 'config/config_by_sub_library',
5
- 'config/pc_tab_exp_field_extended',
6
- 'config/tab15_by_item_process_status',
7
- 'config/tab15_by_item_status',
8
- 'config/tab31',
9
- 'config/tab37',
10
- 'config/tab40',
11
- 'config/tab_sub_library',
12
- 'config/tab_www_item_desc',
13
- 'tab_helper',
14
- 'rest',
15
- 'record',
16
- 'patron',
17
- 'bor_auth'
18
- ].each do |library|
19
- require PATH + library
20
- end
21
- require PATH + 'railtie' if defined?(Rails)
1
+ # Leverage ActiveSupport core extensions
2
+ require 'active_support/core_ext'
3
+ require 'active_support/builder'
4
+ require 'marc'
5
+ require "require_all"
6
+ require_all "#{File.dirname(__FILE__)}/exlibris/"
7
+ # Install tasks
8
+ Exlibris::Aleph::TaskInstaller.install_tasks
@@ -0,0 +1,13 @@
1
+ module Exlibris
2
+ module Aleph
3
+ class << self
4
+ def configure
5
+ yield config
6
+ end
7
+
8
+ def config
9
+ @config ||= Config
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,28 @@
1
+ module Exlibris
2
+ module Aleph
3
+ #
4
+ # If a class is abstract, it can't be instantiated.
5
+ #
6
+ module Abstract
7
+ def self.included(klass)
8
+ klass.class_eval do
9
+ extend ClassAttributes
10
+ end
11
+ end
12
+
13
+ module ClassAttributes
14
+ def abstract
15
+ @abstract ||= false
16
+ end
17
+ alias :abstract? :abstract
18
+
19
+ attr_writer :abstract
20
+ protected :abstract=
21
+ end
22
+
23
+ def initialize *args
24
+ raise NotImplementedError.new("Cannot instantiate #{self.class.name}. It is abstract") if self.class.abstract?
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,78 @@
1
+ module Exlibris
2
+ module Aleph
3
+
4
+ #
5
+ # Specify global configuration settings for
6
+ #
7
+ module Config
8
+ class << self
9
+ include WriteAttributes
10
+ attr_accessor :base_url, :rest_url, :adms, :refresh_time, :tab_path,
11
+ :yml_path, :logger, :irrelevant_sub_libraries, :load_time
12
+
13
+ def load_yaml file
14
+ write_attributes YAML.load_file(file)
15
+ self.load_time = Time.now
16
+ end
17
+ end
18
+
19
+ #
20
+ # These attributes default to the global config settings if not
21
+ # specified locally.
22
+ #
23
+ module Attributes
24
+ def config
25
+ @config ||= Config
26
+ end
27
+
28
+ # Aleph base url
29
+ def base_url
30
+ @base_url ||= String.new config.base_url.to_s
31
+ end
32
+
33
+ # Aleph rest url
34
+ def rest_url
35
+ @rest_url ||= (config.rest_url) ? String.new(config.rest_url.to_s) : "#{base_url}:1891/rest-dlf"
36
+ end
37
+
38
+ # Refresh time for TabHelper
39
+ def refresh_time
40
+ @refresh_time ||= (config.refresh_time) ? config.refresh_time : lambda{1.day.ago}
41
+ end
42
+
43
+ # Aleph ADMs to parse
44
+ def adms
45
+ @adms ||= (config.adms) ? config.adms.collect{|adm| adm.downcase} : []
46
+ end
47
+
48
+ # Tab path for Aleph tables
49
+ def tab_path
50
+ @tab_path ||= File.join(config.tab_path)
51
+ end
52
+
53
+ # YAML path for persisting Aleph config
54
+ def yml_path
55
+ @yml_path ||= (File.join(config.yml_path) || File.join(tab_path, "..", "config", "aleph"))
56
+ end
57
+
58
+ def logger
59
+ @logger ||= (config.logger) ? config.logger : Logger.new(File.join(yml_path, "..", "..", "log", "exlibris_aleph.log"))
60
+ end
61
+
62
+ def irrelevant_sub_libraries
63
+ @irrelevant_sub_libraries ||=
64
+ (config.irrelevant_sub_libraries) ? config.irrelevant_sub_libraries :
65
+ [ "USR00", "HOME", "BOX", "ILLDT", "NYU51", "ALEPH", "USM50",
66
+ "MED", "HYL", "HIL", "LAM", "LAW", "LIT", "MUS", "WID", "EXL", "CIRC", "HILR", "HIL01",
67
+ "HYL01", "HYL02", "HYL03", "HYL04", "HYL05", "HYL06", "LAM01", "LAM02", "LAM03", "LAW01",
68
+ "LAW02", "LAW03", "LIT01", "LIT02", "MED01", "MED02", "MUS01", "MUS02", "WID01", "WID02",
69
+ "WID03", "WID04", "WID05", "U60WD", "U60HL", "U60LA", "U70WD", "CBAB", "BCU", "MBAZU", "USM51",
70
+ "ELEC5", "GDOC5", "EDUC5", "LINC5", "RRLIN", "OU511", "OR512", "OR513", "OR514", "OR515", "U61ED",
71
+ "U61EL", "U61LN", "S61GD", "USM53", "ELEC7", "GDOC7", "EDUC7", "LINC7", "USM54", "ELEC4", "USM55",
72
+ "CUN50", "CLEC5", "CDOC5", "CDUC5", "CINC5", "UNI50", "NARCV", "NELEC", "NRLEC", "NGDOC", "NRDOC",
73
+ "NEDUC", "NHLTH", "NLINC", "NLAW", "NMUSI", "NSCI", "NUPTN" ]
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -2,84 +2,99 @@ module Exlibris
2
2
  module Aleph
3
3
  # ==Overview
4
4
  # Provides access to the Aleph Patron REST API.
5
- class Patron < Rest
6
- attr_reader :patron_id
7
-
8
- # Creates an instance of Exlibris::Aleph::Patron for the given :patron_id
9
- def initialize(patron_id, uri)
10
- @patron_id = patron_id
11
- raise "Initialization error in #{self.class}. Missing patron id." if @patron_id.nil?
12
- super(uri)
13
- @uri = @uri+ "/patron/#{patron_id}"
14
- end
5
+ class Patron < Rest::Base
6
+ attr_accessor :patron_id
15
7
 
16
8
  # Place a hold on the specificed item.
17
- # Raises an error if there was a problem placing the hold.
18
- # Returns a HTTParty::Response.
9
+ # Returns a Hash, including the "note" returned from the underlying API.
10
+ # Raises an exception if the response is not valid XML or there are errors.
19
11
  def place_hold(adm_library, bib_library, bib_id, item_id, params)
20
- pickup_location = params[:pickup_location]
21
- raise "Error in place hold. Missing pickup location." if pickup_location.nil?
22
- last_interest_date = params.fetch(:last_interest_date, "")
23
- start_interest_date = params.fetch(:start_interest_date, "")
24
- sub_author = params.fetch(:sub_author, "")
25
- sub_title = params.fetch(:sub_title, "")
26
- pages = params.fetch(:pages, "")
27
- note_1 = params.fetch(:note_1, "")
28
- note_2 = params.fetch(:note_2, "")
29
- rush = params.fetch(:rush, "N")
30
- body_str = "<hold-request-parameters>"
31
- body_str << "<pickup-location>#{pickup_location}</pickup-location>"
32
- body_str << "<last-interest-date>#{last_interest_date}</last-interest-date>"
33
- body_str << "<start-interest-date>#{start_interest_date}</start-interest-date>"
34
- body_str << "<sub-author>#{sub_author}</sub-author>"
35
- body_str << "<sub-title>#{sub_title}</sub-title>"
36
- body_str << "<pages>#{pages}</pages>"
37
- body_str << "<note-1>#{note_1}</note-1>"
38
- body_str << "<note-2>#{note_2}</note-2>"
39
- body_str << "<rush>#{rush}</rush>"
40
- body_str << "</hold-request-parameters>"
41
- options = { :body => "post_xml=#{body_str}"}
42
- @response = self.class.put(@uri+ "/record/#{bib_library}#{bib_id}/items/#{item_id}/hold", options)
43
- raise "Error placing hold through Aleph REST APIs. #{error}" unless error.nil?
44
- return @response
12
+ options = { :body => "post_xml=#{place_hold_xml(params)}"}
13
+ self.response = self.class.put("#{patron_url}/record/#{bib_library}#{bib_id}/items/#{item_id}/hold", options)
14
+ raise_error_if("Error placing hold through Aleph REST APIs. #{error}") {
15
+ (response.parsed_response["put_item_hold"].nil? or response.parsed_response["put_item_hold"]["create_hold"].nil?)
16
+ }
17
+ response.parsed_response["put_item_hold"]["create_hold"]
45
18
  end
46
19
 
47
- # Call the patronInformation/address Aleph Patron REST API
48
- # Returns a HTTParty::Response.
49
- def address()
50
- @response = self.class.get(@uri+ "/patronInformation/address")
51
- return "Error getting patron's address through Aleph REST APIs. #{error}" unless error.nil?
52
- return @response
20
+ # Returns a Hash representing the patron's address information.
21
+ # Every method call refreshes the data from the underlying API.
22
+ # Raises an exception if the response is not valid XML or there are errors.
23
+ def address
24
+ self.response = self.class.get("#{patron_url}/patronInformation/address")
25
+ raise_error_if("Error getting patron address through Aleph REST APIs.") {
26
+ (response.parsed_response["get_pat_adrs"].nil? or response.parsed_response["get_pat_adrs"]["address_information"].nil?)
27
+ }
28
+ response.parsed_response["get_pat_adrs"]["address_information"]
53
29
  end
54
30
 
55
- # Call the circulationActions/loans Aleph Patron REST API
56
- # Returns a HTTParty::Response.
57
- def loans()
58
- @response = self.class.get(@uri+ "/circulationActions/loans?view=full")
59
- raise "Error getting loans through Aleph REST APIs. #{error}" unless error.nil?
60
- return @response
31
+ # Returns an Array of institutions.
32
+ # Each institution is a Hash containing an array of loans for that institution.
33
+ # Every method call refreshes the data from the underlying API.
34
+ # Raises an exception if the response is not valid XML or there are errors.
35
+ def loans
36
+ self.response = self.class.get("#{patron_url}/circulationActions/loans?view=full")
37
+ raise_error_if("Error getting loans through Aleph REST APIs.") {
38
+ (response.parsed_response["pat_loan_list"].nil? or response.parsed_response["pat_loan_list"]["loans"].nil?)
39
+ }
40
+ [response.parsed_response["pat_loan_list"]["loans"]["institution"]].flatten
61
41
  end
62
42
 
63
43
  # Renew the specified item.
64
44
  # Will renew all if item not specified.
65
- # Returns a HTTParty::Response.
45
+ # Returns an Array of institutions.
46
+ # Each institution is a Hash containing an array of loan renewals for that institution.
47
+ # Raises an exception if the response is not valid XML or there are errors.
66
48
  def renew_loans(item_id="")
67
- @response = self.class.post(@uri+ "/circulationActions/loans/#{item_id}")
68
- raise "Error renewing loan(s) through Aleph REST APIs. #{error}" unless error.nil?
69
- return @response
49
+ self.response = self.class.post("#{patron_url}/circulationActions/loans/#{item_id}")
50
+ raise_error_if("Error renewing loans through Aleph REST APIs.") {
51
+ (response.parsed_response["renew_loan"].nil? or response.parsed_response["renew_loan"]["renewals"].nil?)
52
+ }
53
+ [response.parsed_response["renew_loan"]["renewals"]["institution"]].flatten
70
54
  end
71
-
55
+
72
56
  # Returns the note associated with the request.
73
57
  def note
74
- return (not @response.first.last.kind_of?(Hash) or @response.first.last["create_hold"].nil?) ? "" : ": #{@response.first.last["create_hold"]["note"]["__content__"]}" if @response.instance_of?(Hash)
58
+ return (not response.first.last.kind_of?(Hash) or response.first.last["create_hold"].nil?) ? "" : ": #{response.first.last["create_hold"]["note"]["__content__"]}" if response.instance_of?(Hash)
75
59
  end
76
-
60
+
77
61
  # Returns the error associated with the request.
78
62
  # Returns nil if no error.
79
63
  def error
80
64
  return nil if reply_code == "0000"
81
65
  return "#{reply_text}#{note}"
82
66
  end
67
+
68
+ def patron_url
69
+ @patron_url ||= "#{rest_url}/patron/#{patron_id}"
70
+ end
71
+ private :patron_url
72
+
73
+ def place_hold_xml(params)
74
+ pickup_location = params[:pickup_location]
75
+ last_interest_date = params.fetch(:last_interest_date, "")
76
+ start_interest_date = params.fetch(:start_interest_date, "")
77
+ sub_author = params.fetch(:sub_author, "")
78
+ sub_title = params.fetch(:sub_title, "")
79
+ pages = params.fetch(:pages, "")
80
+ note_1 = params.fetch(:note_1, "")
81
+ note_2 = params.fetch(:note_2, "")
82
+ rush = params.fetch(:rush, "N")
83
+ build_xml { |xml|
84
+ xml.send(:"hold-request-parameters") {
85
+ xml.send :"pickup-location", pickup_location
86
+ xml.send :"last-interest-date", last_interest_date
87
+ xml.send :"start-interest-date", start_interest_date
88
+ xml.send :"sub-author", sub_author
89
+ xml.send :"sub-title", sub_title
90
+ xml.send :"pages", pages
91
+ xml.send :"note-1", note_1
92
+ xml.send :"note-2", note_2
93
+ xml.send :"rush", rush
94
+ }
95
+ }
96
+ end
97
+ private :place_hold_xml
83
98
  end
84
99
  end
85
100
  end
@@ -1,64 +1,58 @@
1
1
  module Exlibris
2
2
  module Aleph
3
+ require 'marc'
3
4
  # ==Overview
4
5
  # Provides access to the Aleph Record REST API.
5
- class Record < Rest
6
- attr_reader :bib_library, :record_id
6
+ class Record < Rest::Base
7
+ attr_accessor :bib_library, :record_id
7
8
 
8
- # Creates an instance of Exlibris::Aleph::Record for the given :bib_library and :record_id
9
- def initialize(bib_library, record_id, uri)
10
- @record_id = record_id
11
- raise "Initialization error in #{self.class}. Missing record id." if @record_id.nil?
12
- @bib_library = bib_library
13
- raise "Initialization error in #{self.class}. Missing bib library." if @bib_library.nil?
14
- super(uri)
15
- @uri = @uri+ "/record/#{bib_library}#{record_id}"
16
- # Format :xml parses response as a hash.
17
- # Eventually I'd like this to be the default since it raises exceptions for invalid XML.
18
- # self.class.format :xml
19
- # Format :html does no parsing, just passes back raw XML for parsing by client
20
- self.class.format :html
9
+ def initialize(*args)
10
+ super
21
11
  end
22
12
 
23
- # Returns an XML string representation of a bib.
13
+ # Returns a MARC::Record that contains the bib data
24
14
  # Every method call refreshes the data from the underlying API.
25
- # Raises and exception if there are errors.
26
- # Returns a HTTParty::Response.
15
+ # Raises an exception if the response is not valid XML or there are errors.
27
16
  def bib
28
- @response = self.class.get(@uri+ "?view=full")
29
- raise "Error getting bib from Aleph REST APIs. #{error}" unless error.nil?
30
- return @response
17
+ self.response = self.class.get("#{record_url}?view=full")
18
+ raise_error_if("Error getting bib from Aleph REST APIs.") {
19
+ (response.parsed_response["get_record"].nil? or response.parsed_response["get_record"]["record"].nil?)
20
+ }
21
+ MARC::XMLReader.new(StringIO.new(xml(xml: response.body).at_xpath("get-record/record").to_xml(xml_options).strip)).first
31
22
  end
32
23
 
33
- # Returns an array of items. Each item is represented as an HTTParty hash.
24
+ # Returns an array of items. Each item is represented as a Hash.
34
25
  # Every method call refreshes the data from the underlying API.
35
26
  # Raises an exception if the response is not valid XML or there are errors.
36
- # Returns a HTTParty::Response.
37
27
  def items
38
- @items = []
39
- self.class.format :xml
40
28
  # Since we're parsing xml, this will raise an error
41
29
  # if the response isn't xml.
42
- @response = self.class.get(@uri+ "/items?view=full")
43
- self.class.format :html
44
- raise "Error getting items from Aleph REST APIs. #{error}" if not error.nil? or
45
- @response.nil? or @response["get_item_list"].nil? or @response["get_item_list"]["items"].nil?
46
- item_list = @response["get_item_list"]["items"]["item"]
47
- @items.push(item_list) if item_list.instance_of?(Hash)
48
- item_list.each {|item|@items.push(item)} if item_list.instance_of?(Array)
49
- # Rails.logger.warn("No items returned from Aleph in #{self.class}.") if @items.empty?
50
- return @items
30
+ self.response = self.class.get("#{record_url}/items?view=full")
31
+ raise_error_if("Error getting items from Aleph REST APIs.") {
32
+ (response.parsed_response["get_item_list"].nil? or response.parsed_response["get_item_list"]["items"].nil?)
33
+ }
34
+ [response.parsed_response["get_item_list"]["items"]["item"]].flatten
51
35
  end
52
36
 
53
- # Returns an XML string representation of holdings
37
+ # Returns an array of holdings. Each holding is represented as a MARC::Record.
54
38
  # Every method call refreshes the data from the underlying API.
55
- # Raises and exception if there are errors.
56
- # Returns a HTTParty::Response.
39
+ # Raises an exception if there are errors.
57
40
  def holdings
58
- @response = self.class.get(@uri+ "/holdings?view=full")
59
- raise "Error getting holdings from Aleph REST APIs. #{error}" unless error.nil?
60
- return @response
41
+ self.response = self.class.get("#{record_url}/holdings?view=full")
42
+ raise_error_if("Error getting holdings from Aleph REST APIs.") {
43
+ (response.parsed_response["get_hol_list"].nil? or response.parsed_response["get_hol_list"]["holdings"].nil?)
44
+ }
45
+ xml(xml: response.body).xpath("get-hol-list/holdings/holding").collect{ |holding|
46
+ # Change the tag name to record so that the MARC::XMLReader can parse it.
47
+ holding.name = "record"
48
+ MARC::XMLReader.new(StringIO.new(holding.to_xml(xml_options).strip)).first
49
+ }
50
+ end
51
+
52
+ def record_url
53
+ @record_url ||= "#{rest_url}/record/#{bib_library}#{record_id}"
61
54
  end
55
+ private :record_url
62
56
  end
63
57
  end
64
58
  end