lib/exlibris/primo/chain_gang/search.rb
module Exlibris
module Primo
module ChainGang
# = Primo ChainGang Search
# These search attributes are included in
# Exlibris::Primo::Search and allow for chaining methods together.
#
# == Examples
#
# Search.new.title("Travels", "title", "contains").
# and.add_query_term("Greene", "creator", "contains").search
#
module Search
def self.included(klass)
klass.class_eval do
extend ClassAttributes
end
end
module ClassAttributes
def indexes
@indexes ||= [:any, :stitle, :title, :creator, :genre, :rsrctype, :author, :isbn]
end
def indexes_map
@indexes_map ||= {:author => :creator, :genre => :rsrctype}
end
def precisions
@precisions ||= [:is, :begins_with, :contains, :starts_with]
end
def precisions_map
@precisions_map ||= {:is => :exact, :starts_with => :begins_with}
end
end
#
# Set the boolean operator for the search
# to "AND".
# Suitable for chaining, e.g.
#
# Search.new.add_query_term("Travels", "title", "contains").
# and.add_query_term("Greene", "creator", "contains").search
#
def and
search_request.boolean_operator = "AND"
self
end
#
# Set the boolean operator for the search
# to "OR".
# Suitable for chaining, e.g.
#
# Search.new.add_query_term("Travels", "title", "contains").
# or.add_query_term("Greene", "creator", "contains").search
#
def or
search_request.boolean_operator = "OR"
self
end
#
# Adds a query term to the search.
# Suitable for chaining, e.g.
#
# Search.new.add_query_term("Travels", "title", "begins_with").
# add_query_term("Greene", "creator", "contains").search
#
def add_query_term(*args)
search_request.add_query_term(*args)
self
end
#
# Dynamically sets chainable accessor for indexes and
# precisions
# Suitable for chaining, e.g.
#
# Search.new.title_begins_with("Travels").
# creator_contains("Greene").search
#
def method_missing(method, *args, &block)
if matches? method
self.class.send(:define_method, method) { |value|
index = indexize(method)
index = (indexes_map[index] || index)
precision = precisionize(method)
precision = (precisions_map[precision] || precision)
add_query_term value, index, precision
}
send method, *args, &block
else
super
end
end
# Returns true if the method can be evaluated to a method name
# and parameter.
def respond_to? method, include_private=false
if(matches? method)
return true
else
super
end
end
# Supported indexes
def indexes
@indexes ||= self.class.indexes
end
private :indexes
# Alternative indexes mapping
def indexes_map
@indexes_map ||= self.class.indexes_map
end
private :indexes_map
# Supported precisions
def precisions
@precisions ||= self.class.precisions
end
private :precisions
# Alternative precisions mapping
def precisions_map
@precisions_map ||= self.class.precisions_map
end
private :precisions_map
# Get the index from the method.
def indexize(method)
parse_method(method).first.to_sym
end
private :indexize
# Get the precision from the method.
def precisionize(method)
parse_method(method).last.to_sym
end
private :precisionize
# Parse the method on the first occurence of delimiter.
def parse_method(method, delimiter="_")
method.to_s.split(delimiter, 2)
end
private :parse_method
# Does this match our indexes and precisions.
def matches? method
indexes.include? indexize(method) and precisions.include? precisionize(method)
end
private :matches?
#
# Set start index for the search.
# Suitable for chaining, e.g.
#
# Search.new.start_index!(11).
# add_query_term("Digital divide", "any", "contains").
# search.records.first => 11th record from the search
#
def start_index!(start_index)
request_attributes[:start_index] = "#{start_index}"
self
end
alias :start_index= :start_index!
#
# Set page size for the search.
# Suitable for chaining, e.g.
#
# Search.new.page_size!(10).
# add_query_term("Digital divide", "any", "contains").
# search.records.size => 10
#
def page_size!(page_size)
request_attributes[:bulk_size] = "#{page_size}"
self
end
alias :page_size= :page_size!
#
# Enable "Did U Mean" functionality for the search.
# Suitable for chaining, e.g.
#
# Search.new.enable_did_u_mean.add_query_term("Digital dvide", "any", "contains").
# search.did_u_mean => "digital video"
#
def enable_did_u_mean
request_attributes[:did_u_mean_enabled] = "true"
self
end
#
# Disable "Did U Mean" functionality for the search.
# Suitable for chaining, e.g.
#
# Search.new.disable_did_u_mean.add_query_term("Digital dvide", "any", "contains").
# search.did_u_mean => nil
#
def disable_did_u_mean
request_attributes[:did_u_mean_enabled] = "false"
self
end
#
# Enable highlighting functionality for the search.
# Suitable for chaining, e.g.
#
# Search.new.enable_highlighting.add_query_term("Digital dvide", "any", "contains").
# search.did_u_mean => "digital d vide"
#
def enable_highlighting
request_attributes[:highlighting_enabled] = "true"
self
end
#
# Disable highlighting functionality for the search.
# Suitable for chaining, e.g.
#
# Search.new.disable_highlighting.add_query_term("Digital dvide", "any", "contains").
# search.did_u_mean => nil
#
def disable_highlighting
request_attributes[:highlighting_enabled] = "false"
self
end
#
# Adds a language to the search.
# Suitable for chaining, e.g.
#
# Search.new.add_language("eng").
# add_query_term("Greene", "creator", "contains").search
#
def add_language(*args)
search_request.add_language(*args)
self
end
#
# Adds a sort by to the search.
# Currently the Primo API only supports
# one sort by value. Add multiple
# sort bys at your own peril.
# Suitable for chaining, e.g.
#
# Search.new.add_sort_by("stitle").
# add_query_term("Greene", "creator", "contains").search
#
def add_sort_by(*args)
search_request.add_sort_by(*args)
self
end
#
# Adds a display field (for highlighting) to the search.
# Suitable for chaining, e.g.
#
# Search.new.add_display_field("creator").
# add_query_term("Greene", "creator", "contains").search
#
def add_display_field(*args)
search_request.add_display_field(*args)
self
end
#
# Adds a location to the search.
# Suitable for chaining, e.g.
#
# Search.new.add_location("local", "scope:(VOLCANO)").
# add_query_term("Greene", "creator", "contains").search
#
def add_location(*args)
search_request.add_location(*args)
self
end
#
# Adds a local location to the search.
# Suitable for chaining, e.g.
#
# Search.new.add_local_location("scope:(VOLCANO)").
# add_query_term("Greene", "creator", "contains").search
#
def add_local_location(location)
add_location("local", location)
end
#
# Adds an adaptor location to the search.
# Suitable for chaining, e.g.
#
# Search.new.add_adaptor_location("primo_central_multiple_fe").
# add_query_term("Greene", "creator", "contains").search
#
def add_adaptor_location(location)
add_location("adaptor", location)
end
#
# Adds a remote location to the search.
# Suitable for chaining, e.g.
#
# Search.new.add_remote_location("quickset_name").
# add_query_term("Greene", "creator", "contains").search
#
def add_remote_location(location)
add_location("remote", location)
end
end
end
end
end