PageRenderTime 25ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/plugins/thinking-sphinx/lib/thinking_sphinx/collection.rb

http://github.com/stevenbristol/lovd-by-less
Ruby | 142 lines | 113 code | 22 blank | 7 comment | 13 complexity | eb51316bccbd7b581490e5fc416b14e9 MD5 | raw file
Possible License(s): MIT
  1. module ThinkingSphinx
  2. class Collection < ::Array
  3. attr_reader :total_entries, :total_pages, :current_page, :per_page
  4. attr_accessor :results
  5. # Compatibility with older versions of will_paginate
  6. alias_method :page_count, :total_pages
  7. def initialize(page, per_page, entries, total_entries)
  8. @current_page, @per_page, @total_entries = page, per_page, total_entries
  9. @total_pages = (entries / @per_page.to_f).ceil
  10. end
  11. def self.ids_from_results(results, page, limit, options)
  12. collection = self.new(page, limit,
  13. results[:total] || 0, results[:total_found] || 0
  14. )
  15. collection.results = results
  16. collection.replace results[:matches].collect { |match|
  17. match[:attributes]["sphinx_internal_id"]
  18. }
  19. return collection
  20. end
  21. def self.create_from_results(results, page, limit, options)
  22. collection = self.new(page, limit,
  23. results[:total] || 0, results[:total_found] || 0
  24. )
  25. collection.results = results
  26. collection.replace instances_from_matches(results[:matches], options)
  27. return collection
  28. end
  29. def self.instances_from_matches(matches, options = {})
  30. if klass = options[:class]
  31. instances_from_class klass, matches, options
  32. else
  33. instances_from_classes matches, options
  34. end
  35. end
  36. def self.instances_from_class(klass, matches, options = {})
  37. index_options = klass.sphinx_index_options
  38. ids = matches.collect { |match| match[:attributes]["sphinx_internal_id"] }
  39. instances = ids.length > 0 ? klass.find(
  40. :all,
  41. :conditions => {klass.primary_key.to_sym => ids},
  42. :include => (options[:include] || index_options[:include]),
  43. :select => (options[:select] || index_options[:select])
  44. ) : []
  45. # Raise an exception if we find records in Sphinx but not in the DB, so
  46. # the search method can retry without them. See
  47. # ThinkingSphinx::Search.retry_search_on_stale_index.
  48. if options[:raise_on_stale] && instances.length < ids.length
  49. stale_ids = ids - instances.map {|i| i.id }
  50. raise StaleIdsException, stale_ids
  51. end
  52. ids.collect { |obj_id|
  53. instances.detect { |obj| obj.id == obj_id }
  54. }
  55. end
  56. # Group results by class and call #find(:all) once for each group to reduce
  57. # the number of #find's in multi-model searches.
  58. #
  59. def self.instances_from_classes(matches, options = {})
  60. groups = matches.group_by { |match| match[:attributes]["class_crc"] }
  61. groups.each do |crc, group|
  62. group.replace(
  63. instances_from_class(class_from_crc(crc), group, options)
  64. )
  65. end
  66. matches.collect do |match|
  67. groups.detect { |crc, group|
  68. crc == match[:attributes]["class_crc"]
  69. }[1].detect { |obj|
  70. obj.id == match[:attributes]["sphinx_internal_id"]
  71. }
  72. end
  73. end
  74. def self.class_from_crc(crc)
  75. @@models_by_crc ||= ThinkingSphinx.indexed_models.inject({}) do |hash, model|
  76. hash[model.constantize.to_crc32] = model
  77. model.constantize.subclasses.each { |subclass|
  78. hash[subclass.to_crc32] = subclass.name
  79. }
  80. hash
  81. end
  82. @@models_by_crc[crc].constantize
  83. end
  84. def previous_page
  85. current_page > 1 ? (current_page - 1) : nil
  86. end
  87. def next_page
  88. current_page < total_pages ? (current_page + 1): nil
  89. end
  90. def offset
  91. (current_page - 1) * @per_page
  92. end
  93. def method_missing(method, *args, &block)
  94. super unless method.to_s[/^each_with_.*/]
  95. each_with_attribute method.to_s.gsub(/^each_with_/, ''), &block
  96. end
  97. def each_with_groupby_and_count(&block)
  98. results[:matches].each_with_index do |match, index|
  99. yield self[index], match[:attributes]["@groupby"], match[:attributes]["@count"]
  100. end
  101. end
  102. def each_with_attribute(attribute, &block)
  103. results[:matches].each_with_index do |match, index|
  104. yield self[index], (match[:attributes][attribute] || match[:attributes]["@#{attribute}"])
  105. end
  106. end
  107. def each_with_weighting(&block)
  108. results[:matches].each_with_index do |match, index|
  109. yield self[index], match[:weight]
  110. end
  111. end
  112. def inject_with_groupby_and_count(initial = nil, &block)
  113. index = -1
  114. results[:matches].inject(initial) do |memo, match|
  115. index += 1
  116. yield memo, self[index], match[:attributes]["@groupby"], match[:attributes]["@count"]
  117. end
  118. end
  119. end
  120. end