solo-rails 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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: ''