Class: BorrowDirect::GenerateQuery

Inherits:
Object
  • Object
show all
Defined in:
lib/borrow_direct/generate_query.rb

Overview

Generate a “deep link” to query results in BD’s native HTML interface.

Constant Summary collapse

@@fields =

Hash from our own API argument to BD field code

{
  :keyword  => "term",
  :title    => "ti",
  :author   => "au",
  :subject  => "su",
  :isbn     => "isbn",
  :issn     => "issn"
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url_base = nil) ⇒ GenerateQuery

Returns a new instance of GenerateQuery.



19
20
21
# File 'lib/borrow_direct/generate_query.rb', line 19

def initialize(url_base = nil)
  self.url_base = (url_base || BorrowDirect::Defaults.html_base_url)
end

Instance Attribute Details

#url_baseObject

Returns the value of attribute url_base.



7
8
9
# File 'lib/borrow_direct/generate_query.rb', line 7

def url_base
  @url_base
end

Class Method Details

.escape(str) ⇒ Object

Escape a query value. We don’t really know how to escape, for now we just remove double quotes and parens, and replace with spaces. those seem to cause problems, and that seems to work.



141
142
143
# File 'lib/borrow_direct/generate_query.rb', line 141

def self.escape(str)
  str.gsub(/[")()]/, ' ')
end

Instance Method Details

#add_query_param(uri, key, value) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/borrow_direct/generate_query.rb', line 149

def add_query_param(uri, key, value)
  uri = URI.parse(uri) unless uri.kind_of? URI

  query_param = "#{CGI.escape key}=#{CGI.escape value}"

  if uri.query
    uri.query += "&" + query_param
  else
    uri.query = query_param
  end
  
  return uri
end

#build_query_with(options) ⇒ Object

build_query_with(:title => “one two”, :author => “three four”) valid keys are those supported by BD HTML interface:

:title, :author, :isbn, :subject, :keyword, :isbn, :issn

For now, the value is always searched as a phrase, and multiple fields are always ‘and’d. We may enhance/expand later.

Returns an un-escaped query, still needs to be put into a URL



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/borrow_direct/generate_query.rb', line 31

def build_query_with(options)
  clauses = []

  options.each_pair do |field, value|
    next if value.nil?

    code = @@fields[field]

    raise ArgumentError.new("Don't recognize field code `#{field}`") unless code

    clauses << %Q{#{code}="#{escape value}"}
  end

  return clauses.join(" and ")
end

#escape(str) ⇒ Object

Instance method version for convenience.



145
146
147
# File 'lib/borrow_direct/generate_query.rb', line 145

def escape(str)
  self.class.escape(str)
end

#normalized_author(author) ⇒ Object

Lowercase, and try to get just the last name out of something that looks like a cataloging authorized heading.



123
124
125
126
127
128
129
130
131
132
133
# File 'lib/borrow_direct/generate_query.rb', line 123

def normalized_author(author)
  return "" if author.nil? || author.empty?

  author = author.downcase
  # Just take everything before the comma if we have one
  if author =~ /\A(.*),/
    author = $1
  end

  return author
end

#normalized_author_title_params(options) ⇒ Object

Give it a :title and optionally an :author, we’ll normalize them to our suggestion for a good BD author-title keyword search. Returns a hash suitable for passing to #query_url_with

Additional option :max_title_words, default 5.

Raises:

  • (ArgumentError)


60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/borrow_direct/generate_query.rb', line 60

def normalized_author_title_params(options)
  raise ArgumentError.new("Need a Hash argument, got #{options.inspect}") unless options.kind_of?(Hash)

  # Symbolize keys please
  #options = options.inject({}){ |h, (k, v)| hash.merge( (k.respond_to?(:to_sym) ? k.to_sym : k) => v )  }

  title           = options[:title].dup  if options[:title]
  author          = options[:author].dup if options[:author]

  
  title  = normalized_title(title, :max_title_words => options[:max_title_words])
  author = normalized_author(author)

  results = {}
  results[:title] = title if title && ! title.empty?
  results[:author] = author if author && ! author.empty?
  
  return results
end

#normalized_author_title_query(options) ⇒ Object

:title, :author and optionally :max_title_words.

Returns a query with a suggested normalized author and title for best BD search. May return just BD base URL if no author/title given.



85
86
87
# File 'lib/borrow_direct/generate_query.rb', line 85

def normalized_author_title_query(options)
  return self.query_url_with self.normalized_author_title_params(options)
end

#normalized_title(title, args = {}) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/borrow_direct/generate_query.rb', line 89

def normalized_title(title, args = {})
  return "" if title.nil? || title.empty?

  max_title_words = args[:max_title_words] || 5
 
  # Remove all things in parens at the END of the title, they tend
  # to be weird addendums. 
  title.gsub!(/\([^)]*\)\s*$/, '')

  # Strip the subtitle or other weird titles, just keep the text
  # before the first colon OR semi-colon
  title.sub!(/[\:\;](.*)$/, '')

  # remove any remaining non-alphanumeric, excepting apostrophe, replacing
  # with space. The punctuation doesn't help our queries. 
  title.gsub!(/[^[:alnum:][:space:]\']/, ' ')

  # compress any remaining whitespace
  title.strip!
  title.gsub!(/\s+/, ' ')

  # downcase
  title.downcase!

  # Limit to only first N words
  if max_title_words && title.index(/((.+?[ ,.:\;]+){#{max_title_words}})/)
    title = title.slice(0, $1.length).gsub(/[ ,.:\;]+$/, '')
  end

  return title
end

#query_url_with(arg) ⇒ Object



49
50
51
52
53
# File 'lib/borrow_direct/generate_query.rb', line 49

def query_url_with(arg)
  query = arg.kind_of?(Hash) ? build_query_with(arg) : arg.to_s
  
  return add_query_param(self.url_base, "query", query).to_s
end