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 +20 -0
- data/lib/solo-rails/helpers.rb +5 -0
- data/lib/solo-rails/version.rb +1 -1
- data/lib/solo-rails.rb +222 -3
- metadata +9 -7
    
        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")
         | 
    
        data/lib/solo-rails/version.rb
    CHANGED
    
    
    
        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  | 
| 11 | 
            -
                 | 
| 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. | 
| 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: & | 
| 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: * | 
| 24 | 
            +
              version_requirements: *70135075996920
         | 
| 25 25 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 26 26 | 
             
              name: nokogiri
         | 
| 27 | 
            -
              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: * | 
| 35 | 
            +
              version_requirements: *70135075995560
         | 
| 36 36 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 37 37 | 
             
              name: chronic
         | 
| 38 | 
            -
              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: * | 
| 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: ''
         |