solo-rails 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 ADDED
@@ -0,0 +1,20 @@
1
+ SoloRails
2
+
3
+ This gem provides a Ruby wrapper for the Soutron Solo API.
4
+
5
+ It provides two methods, one to search the catalogue and one to fetch a specific record.
6
+
7
+ Search method
8
+
9
+ @records = Library.search :q => '',
10
+ :select => 'Title;Authors;Created Date',
11
+ :search_id => @records[:search_info].fetch(:id),
12
+ :ctrt => ct,
13
+ :sort => 'Created Date:d',
14
+ :material => ct[:content_type],
15
+ :per_page => 30,
16
+ :page => 0
17
+
18
+ Show
19
+
20
+ @record = Librar.search("1234556")
@@ -0,0 +1,5 @@
1
+ module Helpers
2
+ # def sh(cid)
3
+ # SoloRails::Catalogue.new.show("520276")
4
+ # end
5
+ end
@@ -1,5 +1,5 @@
1
1
  module Solo
2
2
  module Rails
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
data/lib/solo-rails.rb CHANGED
@@ -3,12 +3,231 @@ require 'cgi'
3
3
  require 'open-uri'
4
4
  require 'chronic'
5
5
  require 'nokogiri'
6
- require 'solo-rails/railtie' #if defined?(Rails)
7
6
 
8
7
  module SoloRails
9
8
 
10
- def initialize
11
- @site = options[:base_uri]
9
+ def show(id)
10
+ Catalogue.new.show(id)
12
11
  end
13
12
 
13
+ def search(*args)
14
+ Catalogue.new.search(*args)
15
+ end
16
+
17
+ class Catalogue
18
+
19
+ def initialize
20
+ @site = "http://library.iser.essex.ac.uk/Library/WebServices/SoutronApi.svc/"
21
+ end
22
+
23
+ # returns SoloHash of values for individual catalogue record
24
+ def show(id)
25
+ id = id.to_i
26
+ response = SoloHash.new
27
+ url = "#{@site}getcatalogue?id=#{id}"
28
+ begin
29
+ soutron_data = Nokogiri::XML(open(url, :read_timeout => 180))
30
+ response[:id] = soutron_data.xpath("/soutron/catalogs_view/ct/cat").attribute("id").text
31
+ # response[:request_url] = url - removed for security/speed purposes - PG 2011-02-17
32
+ response[:content_type] = soutron_data.xpath("/soutron/catalogs_view/ct").attribute("name").text
33
+ response[:record_type] = soutron_data.xpath("/soutron/catalogs_view/ct/cat/rt").attribute("name").text
34
+ soutron_data.xpath("/soutron/catalogs_view/ct/cat/fs/f").each do |f|
35
+ if f.xpath("count(./vs/v)") > 0
36
+ response[uscore(f.attribute("name").text).to_sym] = parse_values(f.attribute("ft").text, f.xpath("./vs/v"))
37
+ end
38
+ end
39
+ # related records - PG 2011-03-01
40
+ if soutron_data.xpath("count(/soutron/catalogs_view/ct/cat/related_catalogs)") > 0
41
+ @related_records = []
42
+ soutron_data.xpath("/soutron/catalogs_view/ct/cat/related_catalogs/ct").each do |related_ct|
43
+ related_record = SoloHash.new
44
+ related_record.merge!( { "content_type".to_sym => related_ct.attribute("name").text } )
45
+ related_ct.xpath('ctlgs/cat').each do |r|
46
+ related_record.merge!( {"cid".to_sym => r.attribute("id").text } )
47
+ end
48
+ @related_records << related_record
49
+ end
50
+ response[:related_records] = @related_records
51
+ end
52
+ rescue
53
+ response = nil
54
+ end
55
+ return response
56
+ end
57
+
58
+ # returns nested hash record for given search - PG 2011-01-21
59
+ def search(*args)
60
+ build_query_url(args.pop)
61
+ begin
62
+ parse_results(Nokogiri::XML(open(url, :read_timeout => 180)))
63
+ rescue Exception => e
64
+ Rails.logger.info("SOLO Error in URL: " + url)
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def build_query_url(*options)
71
+ q, ctrt, select, sort, page, material, search_id, per_page, ignore_is_website_feature = iser_solo_parse_options(options)
72
+ url = "#{@site}searchcatalogues?"
73
+ query_string = []
74
+ # If we have a value of search_id, then should only also pass: search_id, select, sort, page, per_page & material
75
+ if search_id.present?
76
+ query_string << "searchid=#{search_id}"
77
+ else
78
+ query_string << "q=#{q}"
79
+ query_string << "ctrt=#{ctrt}" if ctrt.present?
80
+ end
81
+ query_string << "page=#{page}" if page.present?
82
+ query_string << "pageSize=#{per_page}" if per_page.present?
83
+ query_string << "sort=#{sort}" if sort.present?
84
+ query_string << "fields=#{select}" if select.present?
85
+ query_string << "material=#{material}" if material.present?
86
+ url += query_string.join("&")
87
+ end
88
+
89
+ def parse_results(soutron_data)
90
+ response = SoloHash.new
91
+ meta = {:id => soutron_data.xpath("/soutron/search_info").attribute("id").text}
92
+ meta["total_items".to_sym] = soutron_data.xpath("/soutron/search_info").attribute("totalItems").text
93
+ meta["page".to_sym] = page
94
+ meta["per_page".to_sym] = per_page
95
+ meta["select".to_sym] = select
96
+ if soutron_data.xpath("count(//ct)") > 0
97
+ unless soutron_data.xpath("/soutron/search_info/catalogs_view/ct[*]").first.nil?
98
+ meta["active_content_type".to_sym] = soutron_data.xpath("/soutron/search_info/catalogs_view/ct[*]").first.attribute("name").text
99
+ meta["active_content_type_count".to_sym] = soutron_data.xpath("/soutron/search_info/catalogs_view/ct[*]").first.attribute("count").text
100
+ end
101
+ end
102
+ response.merge!("search_info".to_sym => meta)
103
+ @content_types = []
104
+ soutron_data.xpath("/soutron/search_info/catalogs_view/ct").each do |ct|
105
+ content_type = SoloHash.new
106
+ content_type.merge!( { "content_type".to_sym => ct.attribute("name").text } )
107
+ content_type.merge!( { "size".to_sym => ct.attribute("count").text } )
108
+ @records = []
109
+ ct.xpath("./ctlgs/cat").each do |cat|
110
+ record = SoloHash.new
111
+ record.merge!( {:id => cat.attribute("id").text, :record_type => cat.xpath("./rt").attribute("name").text} )
112
+ cat.xpath("./fs/f").each do |f|
113
+ if f.xpath("count(./vs/v)") > 0 # only include field if it has a value
114
+ record[uscore(f.attribute("name").text).to_sym] = parse_values(f.attribute("ft").text, f.xpath("./vs/v"))
115
+ end # / if has value
116
+ end # /f
117
+ @records << record
118
+ end # /cat
119
+ content_type.merge!({"records".to_sym => @records })
120
+ @content_types << content_type
121
+ end # /ct
122
+ response.merge!(:content_types => @content_types)
123
+ return response
124
+ end
125
+
126
+ # returns array of URL safe variables from options
127
+ def iser_solo_parse_options(options)
128
+ q = options[:q]
129
+ unless options[:ignore_is_website_feature] == true
130
+ q.nil? ? nil : q << ";Is Website Feature:Y"
131
+ end
132
+ ctrt = options[:ctrt]
133
+ select = options[:select]
134
+ sort = options[:sort]
135
+ page = options[:page]
136
+ material = options[:material]
137
+ search_id = options[:search_id]
138
+ per_page = options[:per_page].blank? ? 20 : options[:per_page]
139
+ url_safe([q, ctrt, select, sort, page, material, search_id, per_page])
140
+ end
141
+
142
+ # CGI escapes 'options' array to make safe URLs
143
+ def url_safe(options)
144
+ options.collect! { |option| CGI.escape(option.to_s) }
145
+ end
146
+
147
+ # Returns values for a field based on field type, either individual value or array
148
+ def parse_values(field_type, elements)
149
+ if elements.size > 1
150
+ value = elements.collect{|v| parse_value(field_type, v)}
151
+ else
152
+ value = parse_value(field_type, elements.first)
153
+ end
154
+ end
155
+
156
+ # returns value based on field type
157
+ # @field_types = {
158
+ # 1 => "Text",
159
+ # 2 => "Integer",
160
+ # 3 => "Date",
161
+ # 4 => "File",
162
+ # 5 => "Thesaurus",
163
+ # 6 => "Validation List",
164
+ # 7 => "URL",
165
+ # 8 => "Complex Date",
166
+ # 9 => "Decimal",
167
+ # 10 => "Image",
168
+ # 11 => "Rich Text",
169
+ # 12 => "User"
170
+ # }
171
+ def parse_value(field_type, element)
172
+ field_type = field_type.to_i
173
+ case field_type
174
+ when 1, 4, 5, 6, 11, 12 then element.text.to_s
175
+ when 2 then element.text.to_i
176
+ when 3 then Date.parse(element.text.to_s)
177
+ # when 3 then element.text.to_s
178
+ when 7 then
179
+ if element.attribute("desc").value.size > 0 && !element.attribute("desc").value.eql?(element.text.to_s)
180
+ # "#{element.attribute("desc")} - #{ActionController::Base.helpers.auto_link(element.text.to_s)}"
181
+ "#{element.attribute("desc")} - element.text.to_s)}"
182
+ else
183
+ # ActionController::Base.helpers.auto_link(element.text.to_s)
184
+ element.text.to_s
185
+ end
186
+ when 8 then parse_complex_date(element)
187
+ else field_type
188
+ end
189
+ end
190
+
191
+ # attempts to make ruby Date or failsover to string from SOLO complex date field - PG 2011-04-08
192
+ def parse_complex_date(element)
193
+ d = element.text.split("-")
194
+ date = []
195
+ date << "%02d" % d[2] unless d[2].nil?
196
+ date << "%02d" % d[1] unless d[1].nil?
197
+ date << d[0] unless d[0].nil?
198
+ circa = "circa " if element.attribute("circa").to_s == "1"
199
+ nodate = "forthcoming " if element.attribute("nodate").to_s == "1"
200
+ ongoing = "ongoing" if element.attribute("ongoing").to_s == "1"
201
+ begin
202
+ ret = Date.parse("#{date[0]}-#{date[1]}-#{date[2]}")
203
+ rescue
204
+ ret = "#{circa}#{nodate}#{date.join("-")} #{ongoing}".capitalize.strip
205
+ end
206
+ ret
207
+ end
208
+
209
+ # removes spaces from 'str' and then 'borrows' rails underscore method
210
+ # converts strings like "Publication Date" into "publication_date"
211
+ def uscore(str)
212
+ word = str.gsub(/\s*/,"")
213
+ word = word.to_s.dup
214
+ word.gsub!(/::/, '/')
215
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
216
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
217
+ word.tr!("-", "_")
218
+ word.downcase!
219
+ word
220
+ end
221
+
222
+ end
223
+
224
+ end
225
+
226
+ # Allows object.fieldname searches, returning nil rather than exception if key does not exist - PG 2011-01-20
227
+ class SoloHash < Hash
228
+ def method_missing(method, *params)
229
+ method = method.to_sym
230
+ return self[method] if self.keys.collect(&:to_sym).include?(method)
231
+ nil
232
+ end
14
233
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solo-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-01-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70147310277540 !ruby/object:Gem::Requirement
16
+ requirement: &70135075996920 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70147310277540
24
+ version_requirements: *70135075996920
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: nokogiri
27
- requirement: &70147310276900 !ruby/object:Gem::Requirement
27
+ requirement: &70135075995560 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70147310276900
35
+ version_requirements: *70135075995560
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: chronic
38
- requirement: &70147310276280 !ruby/object:Gem::Requirement
38
+ requirement: &70135075994020 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70147310276280
46
+ version_requirements: *70135075994020
47
47
  description: Provides methods to query Soutron Solo catalog from Ruby
48
48
  email:
49
49
  - github@modagoo.co.uk
@@ -53,8 +53,10 @@ extra_rdoc_files: []
53
53
  files:
54
54
  - .gitignore
55
55
  - Gemfile
56
+ - README
56
57
  - Rakefile
57
58
  - lib/solo-rails.rb
59
+ - lib/solo-rails/helpers.rb
58
60
  - lib/solo-rails/version.rb
59
61
  - solo-rails.gemspec
60
62
  homepage: ''