Created
May 27, 2010 07:40
-
-
Save ql/415580 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class Object | |
| def _metaclass | |
| class << self | |
| self | |
| end | |
| end | |
| end | |
| module ThinkingSphinx | |
| class Search | |
| # Overwrite the configured content attributes with excerpted and highlighted versions of themselves. | |
| # Runs run if it hasn't already been done. | |
| def instances_from_matches #hacked from thinking_sphinx/search.rb | |
| options = { | |
| :before_match => '<strong class="highlight">', | |
| :after_match => '</strong>', | |
| :chunk_separator => "...", | |
| :limit => 256, | |
| :around => 5 | |
| } | |
| res = if one_class | |
| single_class_results | |
| else | |
| groups = results[:matches].group_by { |match| | |
| match[:attributes]["class_crc"] | |
| } | |
| groups.each do |crc, group| | |
| group.replace( | |
| instances_from_class(class_from_crc(crc), group) | |
| ) | |
| end | |
| results[:matches].collect do |match| | |
| groups.detect { |crc, group| | |
| crc == match[:attributes]["class_crc"] | |
| }[1].compact.detect { |obj| | |
| obj.primary_key_for_sphinx == match[:attributes]["sphinx_internal_id"] | |
| } | |
| end | |
| end | |
| content_methods = %w{title game_title post_title name description description_html body body_html address aka developer publisher publisher_russian} # the attributes of any model you would like to have excerpted | |
| content_h_methods = %w{title game_title post_title name aka address developer publisher publisher_russian} # methods that are escaped (h()) before having them excerpted | |
| # See what fields in each result might respond to our excerptable methods | |
| results_with_content_methods = res.map do |result| | |
| [result, | |
| content_methods.map do |methods| | |
| methods.detect do |this| | |
| result.respond_to? this | |
| end | |
| end | |
| ] | |
| end | |
| # Fetch the actual field contents | |
| docs = results_with_content_methods.map do |result, methods| | |
| methods.map do |method| | |
| if content_h_methods.include?(method) | |
| method and strip_bogus_characters(ERB::Util.html_escape(result.send(method))) or "" | |
| else | |
| method and strip_bogus_characters(result.send(method)) or "" | |
| end | |
| end | |
| end.flatten | |
| excerpting_options = { | |
| :docs => docs, | |
| # WARNING: extremely stupid, you need to have User indexed for anything to work | |
| :index => "user_core", #MAIN_INDEX, # http://www.sphinxsearch.com/forum/view.html?id=100 | |
| :words => strip_query_commands(query.to_s) | |
| }.merge(options) | |
| responses = client.excerpts(excerpting_options) | |
| responses = responses.in_groups_of(content_methods.size) | |
| results_with_content_methods.each_with_index do |result_and_methods, i| | |
| # Override the individual model accessors with the excerpted data | |
| result, methods = result_and_methods | |
| methods.each_with_index do |method, j| | |
| data = responses[i][j] | |
| if method | |
| result._metaclass.send('define_method', method) { data } | |
| attributes = result.instance_variable_get('@attributes') | |
| attributes[method] = data if attributes[method] | |
| end | |
| end | |
| end | |
| res = results_with_content_methods.map do |result_and_content_method| | |
| result_and_content_method.first.freeze | |
| end | |
| res | |
| end | |
| def search_with_excerpts(*args) | |
| query = args.clone # an array | |
| options = query.extract_options! | |
| retry_search_on_stale_index(query, options) do | |
| results, client = search_results(*(query + [options])) | |
| ::ActiveRecord::Base.logger.error( | |
| "Sphinx Error: #{results[:error]}" | |
| ) if results[:error] | |
| klass = options[:class] | |
| page = options[:page] ? options[:page].to_i : 1 | |
| total = results[:total] | |
| results = ThinkingSphinx::Collection.create_from_results(results, page, client.limit, options) | |
| if options[:excerpts] and !results.empty? | |
| exp = excerpts(results, client, query) | |
| end | |
| results | |
| end | |
| end | |
| alias_method_chain :search, :excerpts | |
| def search_with_hypen_escape(*args) | |
| if args.size > 0 && args[0].is_a?(String) | |
| args[0] = args[0].gsub(/([^\s])\-/, '\1\-') | |
| end | |
| search_without_hypen_escape(*args) | |
| end | |
| alias_method_chain :search, :hypen_escape | |
| def strip_bogus_characters(s) | |
| # Used to remove some garbage before highlighting | |
| s.gsub(/<.*?>|\.\.\.|\342\200\246|\n|\r/, " ") if s | |
| # s.gsub(/<.*?>|\.\.\.|\342\200\246|\n|\r/, " ").gsub(/http.*?( |$)/, ' ') if s | |
| end | |
| def strip_query_commands(s) | |
| # XXX Hack for query commands, since Sphinx doesn't intelligently parse the query in excerpt mode | |
| # Also removes apostrophes in the middle of words so that they don't get split in two. | |
| s.gsub(/(^|\s)(AND|OR|NOT|\@\w+)(\s|$)/i, "").gsub(/(\w)\'(\w)/, '\1\2') | |
| end | |
| end | |
| end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment