mwmitchell-rsolr-ext 0.4.1 → 0.5.0

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/lib/core_ext.rb ADDED
@@ -0,0 +1,5 @@
1
+ class Hash
2
+ def to_mash
3
+ Mash.new(self)
4
+ end
5
+ end
data/lib/mash.rb ADDED
@@ -0,0 +1,143 @@
1
+ # This class has dubious semantics and we only have it so that people can write
2
+ # params[:key] instead of params['key'].
3
+ class Mash < Hash
4
+
5
+ # @param constructor<Object>
6
+ # The default value for the mash. Defaults to an empty hash.
7
+ #
8
+ # @details [Alternatives]
9
+ # If constructor is a Hash, a new mash will be created based on the keys of
10
+ # the hash and no default value will be set.
11
+ def initialize(constructor = {})
12
+ if constructor.is_a?(Hash)
13
+ super()
14
+ update(constructor)
15
+ else
16
+ super(constructor)
17
+ end
18
+ end
19
+
20
+ # @param key<Object> The default value for the mash. Defaults to nil.
21
+ #
22
+ # @details [Alternatives]
23
+ # If key is a Symbol and it is a key in the mash, then the default value will
24
+ # be set to the value matching the key.
25
+ def default(key = nil)
26
+ if key.is_a?(Symbol) && include?(key = key.to_s)
27
+ self[key]
28
+ else
29
+ super
30
+ end
31
+ end
32
+
33
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
34
+ alias_method :regular_update, :update unless method_defined?(:regular_update)
35
+
36
+ # @param key<Object> The key to set.
37
+ # @param value<Object>
38
+ # The value to set the key to.
39
+ #
40
+ # @see Mash#convert_key
41
+ # @see Mash#convert_value
42
+ def []=(key, value)
43
+ regular_writer(convert_key(key), convert_value(value))
44
+ end
45
+
46
+ # @param other_hash<Hash>
47
+ # A hash to update values in the mash with. The keys and the values will be
48
+ # converted to Mash format.
49
+ #
50
+ # @return <Mash> The updated mash.
51
+ def update(other_hash)
52
+ other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
53
+ self
54
+ end
55
+
56
+ alias_method :merge!, :update
57
+
58
+ # @param key<Object> The key to check for. This will be run through convert_key.
59
+ #
60
+ # @return <TrueClass, FalseClass> True if the key exists in the mash.
61
+ def key?(key)
62
+ super(convert_key(key))
63
+ end
64
+
65
+ # def include? def has_key? def member?
66
+ alias_method :include?, :key?
67
+ alias_method :has_key?, :key?
68
+ alias_method :member?, :key?
69
+
70
+ # @param key<Object> The key to fetch. This will be run through convert_key.
71
+ # @param *extras<Array> Default value.
72
+ #
73
+ # @return <Object> The value at key or the default value.
74
+ def fetch(key, *extras)
75
+ super(convert_key(key), *extras)
76
+ end
77
+
78
+ # @param *indices<Array>
79
+ # The keys to retrieve values for. These will be run through +convert_key+.
80
+ #
81
+ # @return <Array> The values at each of the provided keys
82
+ def values_at(*indices)
83
+ indices.collect {|key| self[convert_key(key)]}
84
+ end
85
+
86
+ # @return <Mash> A duplicate of this mash.
87
+ def dup
88
+ Mash.new(self)
89
+ end
90
+
91
+ # @param hash<Hash> The hash to merge with the mash.
92
+ #
93
+ # @return <Mash> A new mash with the hash values merged in.
94
+ def merge(hash)
95
+ self.dup.update(hash)
96
+ end
97
+
98
+ # @param key<Object>
99
+ # The key to delete from the mash.\
100
+ def delete(key)
101
+ super(convert_key(key))
102
+ end
103
+
104
+ # Used to provide the same interface as Hash.
105
+ #
106
+ # @return <Mash> This mash unchanged.
107
+ def stringify_keys!; self end
108
+
109
+ # @return <Hash> The mash as a Hash with string keys.
110
+ def to_hash
111
+ Hash.new(default).merge(self)
112
+ end
113
+
114
+ protected
115
+ # @param key<Object> The key to convert.
116
+ #
117
+ # @param <Object>
118
+ # The converted key. If the key was a symbol, it will be converted to a
119
+ # string.
120
+ #
121
+ # @api private
122
+ def convert_key(key)
123
+ key.kind_of?(Symbol) ? key.to_s : key
124
+ end
125
+
126
+ # @param value<Object> The value to convert.
127
+ #
128
+ # @return <Object>
129
+ # The converted value. A Hash or an Array of hashes, will be converted to
130
+ # their Mash equivalents.
131
+ #
132
+ # @api private
133
+ def convert_value(value)
134
+ case value
135
+ when Hash
136
+ value.to_mash
137
+ when Array
138
+ value.collect { |e| convert_value(e) }
139
+ else
140
+ value
141
+ end
142
+ end
143
+ end
@@ -1,7 +1,24 @@
1
1
  module RSolr::Ext::Request
2
2
 
3
+ # A module that provides method mapping capabilities.
4
+ # The basic idea is to pass in a hash to the #map method,
5
+ # the map method then goes through a list of keys to
6
+ # be processed. Each key name can match a key in the input hash.
7
+ # If there is a match, a method by the name of "map_#{key}" is
8
+ # called with the following args: input[key], output_hash
9
+ # The method is responsible for processing the value.
10
+ # The return value from the method does nothing.
11
+ #
12
+ # For example: if the mapped params list has a name, :query,
13
+ # there should be a method like: map_query(input_value, output_hash)
3
14
  module Mapable
4
15
 
16
+ # accepts an input hash.
17
+ # prepares a return hash by copying the input.
18
+ # runs through all of the keys in MAPPED_PARAMS.
19
+ # calls any mapper methods that match the current key in MAPPED_PARAMS.
20
+ # The mapped keys from the input hash are deleted.
21
+ # returns a new hash.
5
22
  def map(input)
6
23
  result = input.dup
7
24
  self.class::MAPPED_PARAMS.each do |meth|
@@ -12,24 +29,42 @@ module RSolr::Ext::Request
12
29
  result
13
30
  end
14
31
 
15
- def append_to_param(existing_value, new_value)
32
+ # creates an array where the "existing_value" param is first
33
+ # and the "new_value" is the last.
34
+ # All empty/nil items are removed.
35
+ # the return result is either the result of the
36
+ # array being joined on a space, or the array itself.
37
+ # "auto_join" should be true or false.
38
+ def append_to_param(existing_value, new_value, auto_join=true)
16
39
  values = [existing_value, new_value]
17
40
  values.delete_if{|v|v.nil?}
18
- values.join(' ')
41
+ auto_join ? values.join(' ') : values
19
42
  end
20
43
 
21
44
  end
22
45
 
46
+ # a module to help the creation of solr queries.
23
47
  module Queryable
24
48
 
49
+ # Wraps a string around double quotes
25
50
  def quote(value)
26
51
  %("#{value}")
27
52
  end
28
53
 
54
+ # builds a solr range query from a Range object
29
55
  def build_range(r)
30
56
  "[#{r.min} TO #{r.max}]"
31
57
  end
32
58
 
59
+ # builds a solr query fragment
60
+ # if "quote_string" is true, the values will be quoted.
61
+ # if "value" is a string/symbol, the #to_s method is called
62
+ # if the "value" is an array, each item in the array is
63
+ # send to build_query (recursive)
64
+ # if the "value" is a Hash, a fielded query is built
65
+ # where the keys are used as the field names and
66
+ # the values are either processed as a Range or
67
+ # passed back into build_query (recursive)
33
68
  def build_query(value, quote_string=false)
34
69
  case value
35
70
  when String,Symbol
@@ -0,0 +1,38 @@
1
+ # module for adding helper methods to each solr response[:docs] object
2
+ module RSolr::Ext::Response::DocExt
3
+
4
+ # Helper method to check if value/multi-values exist for a given key.
5
+ # The value can be a string, or a RegExp
6
+ # Example:
7
+ # doc.has?(:location_facet)
8
+ # doc.has?(:location_facet, 'Clemons')
9
+ # doc.has?(:id, 'h009', /^u/i)
10
+ def has?(k, *values)
11
+ return if self[k].nil?
12
+ return true if self.key?(k) and values.empty?
13
+ target = self[k]
14
+ if target.is_a?(Array)
15
+ values.each do |val|
16
+ return target.any?{|tv| val.is_a?(Regexp) ? (tv =~ val) : (tv==val)}
17
+ end
18
+ else
19
+ return values.any? {|val| val.is_a?(Regexp) ? (target =~ val) : (target == val)}
20
+ end
21
+ end
22
+
23
+ # helper
24
+ # key is the name of the field
25
+ # opts is a hash with the following valid keys:
26
+ # - :sep - a string used for joining multivalued field values
27
+ # - :default - a value to return when the key doesn't exist
28
+ # if :sep is nil and the field is a multivalued field, the array is returned
29
+ def get(key, opts={:sep=>', ', :default=>nil})
30
+ if self.key? key
31
+ val = self[key]
32
+ (val.is_a?(Array) and opts[:sep]) ? val.join(opts[:sep]) : val
33
+ else
34
+ opts[:default]
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,24 @@
1
+ class RSolr::Ext::Response::FacetPaginator
2
+
3
+ attr_reader :total, :items, :previous_offset, :next_offset
4
+
5
+ def initialize(all_facet_values, offset, limit)
6
+ offset = offset.to_s.to_i
7
+ limit = limit.to_s.to_i
8
+ total = all_facet_values.size
9
+ @items = all_facet_values.slice(0, limit-1)
10
+ @has_next = total == limit
11
+ @has_previous = offset > 0
12
+ @next_offset = offset + (limit-1)
13
+ @previous_offset = offset - (limit-1)
14
+ end
15
+
16
+ def has_next?
17
+ @has_next
18
+ end
19
+
20
+ def has_previous?
21
+ @has_previous
22
+ end
23
+
24
+ end
@@ -0,0 +1,64 @@
1
+ module RSolr::Ext::Response::Facetable
2
+
3
+ # represents a facet value; which is a field value and its hit count
4
+ class FacetValue
5
+ attr_reader :value,:hits
6
+ def initialize(value,hits)
7
+ @value,@hits=value,hits
8
+ end
9
+ end
10
+
11
+ # represents a facet; which is a field and its values
12
+ class Facet
13
+ attr_reader :field
14
+ attr_accessor :values
15
+ def initialize(field)
16
+ @field=field
17
+ @values=[]
18
+ end
19
+ end
20
+
21
+ # @response.facets.each do |facet|
22
+ # facet.field
23
+ # end
24
+ # "caches" the result in the @facets instance var
25
+ def facets
26
+ # memoize!
27
+ @facets ||= (
28
+ facet_fields.inject([]) do |acc,(facet_field_name,values_and_hits_list)|
29
+ acc << facet = Facet.new(facet_field_name)
30
+ # the values_and_hits_list is an array where a value is immediately followed by it's hit count
31
+ # so we shift off an item (the value)
32
+ while value = values_and_hits_list.shift
33
+ # and then shift off the next to get the hit value
34
+ facet.values << FacetValue.new(value, values_and_hits_list.shift)
35
+ # repeat until there are no more pairs in the values_and_hits_list array
36
+ end
37
+ acc
38
+ end
39
+ )
40
+ end
41
+
42
+ # pass in a facet field name and get back a Facet instance
43
+ def facet_by_field_name(name)
44
+ @facets_by_field_name ||= {}
45
+ @facets_by_field_name[name] ||= (
46
+ facets.detect{|facet|facet.field.to_s == name.to_s}
47
+ )
48
+ end
49
+
50
+ def facet_counts
51
+ @facet_counts ||= self[:facet_counts] || {}
52
+ end
53
+
54
+ # Returns the hash of all the facet_fields (ie: {'instock_b' => ['true', 123, 'false', 20]}
55
+ def facet_fields
56
+ @facet_fields ||= facet_counts[:facet_fields] || {}
57
+ end
58
+
59
+ # Returns all of the facet queries
60
+ def facet_queries
61
+ @facet_queries ||= facet_counts[:facet_queries] || {}
62
+ end
63
+
64
+ end # end Facets
@@ -0,0 +1,30 @@
1
+ module RSolr::Ext::Response::Pageable
2
+
3
+ attr_accessor :start, :per_page, :total
4
+
5
+ # Returns the current page calculated from 'rows' and 'start'
6
+ # WillPaginate hook
7
+ def current_page
8
+ return 1 if start < 1
9
+ @current_page ||= (start / per_page).ceil + 1
10
+ end
11
+
12
+ # Calcuates the total pages from 'numFound' and 'rows'
13
+ # WillPaginate hook
14
+ def total_pages
15
+ @total_pages ||= per_page > 0 ? (total / per_page.to_f).ceil : 1
16
+ end
17
+
18
+ # returns the previous page number or 1
19
+ # WillPaginate hook
20
+ def previous_page
21
+ @previous_page ||= (current_page > 1) ? current_page - 1 : 1
22
+ end
23
+
24
+ # returns the next page number or the last
25
+ # WillPaginate hook
26
+ def next_page
27
+ @next_page ||= (current_page < total_pages) ? current_page + 1 : total_pages
28
+ end
29
+
30
+ end
@@ -1,8 +1,67 @@
1
1
  module RSolr::Ext::Response
2
2
 
3
- autoload :Base, 'rsolr-ext/response/base'
4
- autoload :Select, 'rsolr-ext/response/select'
5
- autoload :Luke, 'rsolr-ext/response/luke'
6
- autoload :Update, 'rsolr-ext/response/update'
3
+ autoload :Facetable, 'rsolr-ext/response/facetable'
4
+ autoload :Pageable, 'rsolr-ext/response/pageable'
5
+ autoload :DocExt, 'rsolr-ext/response/doc_ext'
6
+
7
+ class Base < Mash
8
+
9
+ attr_reader :raw_response
10
+
11
+ def initialize(raw_response)
12
+ @raw_response = raw_response
13
+ super(raw_response)
14
+ RSolr::Ext::HashMethodizer.methodize!(self)
15
+ end
16
+
17
+ def ok?
18
+ response_header.status == 0
19
+ end
20
+
21
+ end
22
+
23
+ #
24
+ class Standard < Base
25
+
26
+ include Facetable
27
+
28
+ def initialize(*a)
29
+ super
30
+ activate_pagination!
31
+ end
32
+
33
+ def activate_pagination!
34
+ response.docs.each{ |d| d.extend DocExt }
35
+ d = response.docs
36
+ d.extend Pageable
37
+ d.start = response_header.params[:start].to_s.to_i
38
+ d.per_page = response_header.params[:rows].to_s.to_i
39
+ d.total = d.size
40
+ end
41
+
42
+ end
43
+
44
+ class Dismax < Standard
45
+
46
+ end
47
+
48
+ #
49
+ class RSolr::Ext::Response::Luke < Base
50
+
51
+ # Returns an array of fields from the index
52
+ # An optional rule can be used for "grepping" field names:
53
+ # field_list(/_facet$/)
54
+ def field_list(rule=nil)
55
+ fetch(:fields).select do |k,v|
56
+ rule ? k =~ rule : true
57
+ end.collect{|k,v|k}
58
+ end
59
+
60
+ end# end Luke
61
+
62
+ # Update
63
+ class Update < Base
64
+
65
+ end
7
66
 
8
67
  end
data/lib/rsolr-ext.rb CHANGED
@@ -15,10 +15,11 @@ module RSolr
15
15
 
16
16
  module Ext
17
17
 
18
- VERSION = '0.4.1'
18
+ VERSION = '0.5.0'
19
19
 
20
20
  autoload :Request, 'rsolr-ext/request.rb'
21
21
  autoload :Response, 'rsolr-ext/response.rb'
22
+ autoload :HashMethodizer, 'rsolr-ext/hash_methodizer.rb'
22
23
 
23
24
  end
24
25
 
data/rsolr-ext.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "rsolr-ext"
3
- s.version = "0.4.1"
4
- s.date = "2009-03-15"
3
+ s.version = "0.5.0"
4
+ s.date = "2009-03-17"
5
5
  s.summary = "An extension lib for RSolr"
6
6
  s.email = "goodieboy@gmail.com"
7
7
  s.homepage = "http://github.com/mwmitchell/rsolr_ext"
@@ -9,19 +9,27 @@ Gem::Specification.new do |s|
9
9
  s.has_rdoc = true
10
10
  s.authors = ["Matt Mitchell"]
11
11
  s.files = [
12
- "lib/rsolr-ext.rb",
13
- "lib/rsolr-ext/params.rb",
14
- "lib/rsolr-ext/request.rb",
15
- "lib/rsolr-ext/request/standard.rb",
16
- "lib/rsolr-ext/request/dismax.rb",
17
- "lib/rsolr-ext/response.rb",
18
- "lib/rsolr-ext/response/base.rb",
19
- "lib/rsolr-ext/response/luke.rb",
20
- "lib/rsolr-ext/response/select.rb",
21
- "lib/rsolr-ext/response/update.rb",
22
- "LICENSE",
23
- "README.rdoc",
24
- "rsolr-ext.gemspec"
12
+
13
+ "lib/core_ext.rb",
14
+ "lib/mash.rb",
15
+
16
+ "lib/rsolr-ext/hash_methodizer",
17
+
18
+ "lib/rsolr-ext/request/dismax.rb",
19
+ "lib/rsolr-ext/request/standard.rb",
20
+ "lib/rsolr-ext/request.rb",
21
+
22
+ "lib/rsolr-ext/response/doc_ext.rb",
23
+ "lib/rsolr-ext/response/facet_paginator.rb",
24
+ "lib/rsolr-ext/response/facetable.rb",
25
+ "lib/rsolr-ext/response/pageable.rb",
26
+ "lib/rsolr-ext/response.rb",
27
+
28
+ "lib/rsolr-ext.rb",
29
+
30
+ "LICENSE",
31
+ "README.rdoc",
32
+ "rsolr-ext.gemspec"
25
33
  ]
26
34
  s.test_files = ['test/request_test.rb', 'test/response_test.rb', 'test/test_unit_test_case.rb', 'test/helper.rb']
27
35
  s.extra_rdoc_files = %w(LICENSE README.rdoc)
@@ -4,10 +4,25 @@ require 'helper'
4
4
 
5
5
  class RSolrExtResponseTest < Test::Unit::TestCase
6
6
 
7
- test 'base response module' do
7
+ test 'base response class' do
8
8
  raw_response = eval(mock_query_response)
9
- r = RSolr::Ext::Response::Base.create(raw_response)
9
+ r = RSolr::Ext::Response::Base.new(raw_response)
10
10
  assert r.ok?
11
11
  end
12
12
 
13
+ test 'standard response class' do
14
+ raw_response = eval(mock_query_response)
15
+ r = RSolr::Ext::Response::Standard.new(raw_response)
16
+ assert r.ok?
17
+ assert_equal 10, r.response.docs.size
18
+ assert_equal 'EXPLICIT', r.response_header.params.echo_params
19
+ assert_equal r['responseHeader'], r.response_header
20
+ assert_equal r[:responseHeader], r.response_header
21
+ assert_equal 1, r.response.docs.previous_page
22
+ assert_equal 1, r.response.docs.next_page
23
+ #
24
+ assert r.response.docs.kind_of?(RSolr::Ext::Response::Pageable)
25
+ assert r.kind_of?(RSolr::Ext::Response::Facetable)
26
+ end
27
+
13
28
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mwmitchell-rsolr-ext
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Mitchell
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-15 00:00:00 -07:00
12
+ date: 2009-03-17 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -23,16 +23,18 @@ extra_rdoc_files:
23
23
  - LICENSE
24
24
  - README.rdoc
25
25
  files:
26
- - lib/rsolr-ext.rb
27
- - lib/rsolr-ext/params.rb
28
- - lib/rsolr-ext/request.rb
29
- - lib/rsolr-ext/request/standard.rb
26
+ - lib/core_ext.rb
27
+ - lib/mash.rb
28
+ - lib/rsolr-ext/hash_methodizer
30
29
  - lib/rsolr-ext/request/dismax.rb
30
+ - lib/rsolr-ext/request/standard.rb
31
+ - lib/rsolr-ext/request.rb
32
+ - lib/rsolr-ext/response/doc_ext.rb
33
+ - lib/rsolr-ext/response/facet_paginator.rb
34
+ - lib/rsolr-ext/response/facetable.rb
35
+ - lib/rsolr-ext/response/pageable.rb
31
36
  - lib/rsolr-ext/response.rb
32
- - lib/rsolr-ext/response/base.rb
33
- - lib/rsolr-ext/response/luke.rb
34
- - lib/rsolr-ext/response/select.rb
35
- - lib/rsolr-ext/response/update.rb
37
+ - lib/rsolr-ext.rb
36
38
  - LICENSE
37
39
  - README.rdoc
38
40
  - rsolr-ext.gemspec
@@ -1,35 +0,0 @@
1
- #
2
- # my_solr_hash.extend RSolrExt::Response::Base
3
- # my_solr_hash.header
4
- # my_solr_hash.ok?
5
- #
6
- module RSolr::Ext::Response::Base
7
-
8
- def header
9
- self[:responseHeader]
10
- end
11
-
12
- def params
13
- header[:params]
14
- end
15
-
16
- def status
17
- header[:status].to_i
18
- end
19
-
20
- def query_time
21
- header[:QTime]
22
- end
23
-
24
- def ok?
25
- self.status == 0
26
- end
27
-
28
- # converts to mash, then extends
29
- def self.create(hash)
30
- mash = hash.is_a?(Mash) ? hash : hash.to_mash
31
- mash.extend self
32
- mash
33
- end
34
-
35
- end # end Base
@@ -1,53 +0,0 @@
1
- module RSolr::Ext::Response::Luke
2
-
3
- include Base
4
-
5
- def index
6
- self[:index]
7
- end
8
-
9
- def directory
10
- index[:directory]
11
- end
12
-
13
- def has_deletions
14
- index[:hasDeletions]
15
- end
16
-
17
- def current
18
- index[:current]
19
- end
20
-
21
- def max_doc
22
- index[:max_doc]
23
- end
24
-
25
- def num_docs
26
- index[:numDocs]
27
- end
28
-
29
- def version
30
- index[:version]
31
- end
32
-
33
- alias :has_deletions? :has_deletions
34
- alias :optimized? :optimized
35
- alias :current? :current
36
-
37
- # Returns an array of fields from the index
38
- # An optional rule can be used for "grepping" field names:
39
- # field_list(/_facet$/)
40
- def field_list(rule=nil)
41
- self[:fields].select do |k,v|
42
- rule ? k =~ rule : true
43
- end.collect{|k,v|k}
44
- end
45
-
46
- # converts to mash, then extends
47
- def self.create(hash)
48
- mash = hash.is_a?(Mash) ? hash : hash.to_mash
49
- mash.extend self
50
- mash
51
- end
52
-
53
- end# end Luke
@@ -1,216 +0,0 @@
1
- module RSolr::Ext::Response::Select
2
-
3
- # module for adding helper methods to each solr response[:docs] object
4
- module DocExt
5
-
6
- # Helper method to check if value/multi-values exist for a given key.
7
- # The value can be a string, or a RegExp
8
- # Example:
9
- # doc.has?(:location_facet)
10
- # doc.has?(:location_facet, 'Clemons')
11
- # doc.has?(:id, 'h009', /^u/i)
12
- def has?(k, *values)
13
- return if self[k].nil?
14
- return true if self.key?(k) and values.empty?
15
- target = self[k]
16
- if target.is_a?(Array)
17
- values.each do |val|
18
- return target.any?{|tv| val.is_a?(Regexp) ? (tv =~ val) : (tv==val)}
19
- end
20
- else
21
- return values.any? {|val| val.is_a?(Regexp) ? (target =~ val) : (target == val)}
22
- end
23
- end
24
-
25
- # helper
26
- # key is the name of the field
27
- # opts is a hash with the following valid keys:
28
- # - :sep - a string used for joining multivalued field values
29
- # - :default - a value to return when the key doesn't exist
30
- # if :sep is nil and the field is a multivalued field, the array is returned
31
- def get(key, opts={:sep=>', ', :default=>nil})
32
- if self.key? key
33
- val = self[key]
34
- (val.is_a?(Array) and opts[:sep]) ? val.join(opts[:sep]) : val
35
- else
36
- opts[:default]
37
- end
38
- end
39
-
40
- end
41
-
42
- module Facets
43
-
44
- # represents a facet value; which is a field value and its hit count
45
- class FacetValue
46
- attr_reader :value,:hits
47
- def initialize(value,hits)
48
- @value,@hits=value,hits
49
- end
50
- end
51
-
52
- # represents a facet; which is a field and its values
53
- class Facet
54
- attr_reader :field
55
- attr_accessor :values
56
- def initialize(field)
57
- @field=field
58
- @values=[]
59
- end
60
- end
61
-
62
- # @response.facets.each do |facet|
63
- # facet.field
64
- # end
65
- # "caches" the result in the @facets instance var
66
- def facets
67
- # memoize!
68
- @facets ||= (
69
- facet_fields.inject([]) do |acc,(facet_field_name,values_and_hits_list)|
70
- acc << facet = Facet.new(facet_field_name)
71
- # the values_and_hits_list is an array where a value is immediately followed by it's hit count
72
- # so we shift off an item (the value)
73
- while value = values_and_hits_list.shift
74
- # and then shift off the next to get the hit value
75
- facet.values << FacetValue.new(value, values_and_hits_list.shift)
76
- # repeat until there are no more pairs in the values_and_hits_list array
77
- end
78
- acc
79
- end
80
- )
81
- end
82
-
83
- # pass in a facet field name and get back a Facet instance
84
- def facet_by_field_name(name)
85
- @facets_by_field_name ||= {}
86
- @facets_by_field_name[name] ||= (
87
- facets.detect{|facet|facet.field.to_s == name.to_s}
88
- )
89
- end
90
-
91
- def facet_counts
92
- @facet_counts ||= self[:facet_counts] || {}
93
- end
94
-
95
- # Returns the hash of all the facet_fields (ie: {'instock_b' => ['true', 123, 'false', 20]}
96
- def facet_fields
97
- @facet_fields ||= facet_counts[:facet_fields] || {}
98
- end
99
-
100
- # Returns all of the facet queries
101
- def facet_queries
102
- @facet_queries ||= facet_counts[:facet_queries] || {}
103
- end
104
-
105
- end # end Facets
106
-
107
- #
108
- #
109
- #
110
- class FacetPaginator
111
-
112
- attr_reader :total, :items, :previous_offset, :next_offset
113
-
114
- def initialize(all_facet_values, offset, limit)
115
- offset = offset.to_s.to_i
116
- limit = limit.to_s.to_i
117
- total = all_facet_values.size
118
- @items = all_facet_values.slice(0, limit-1)
119
- @has_next = total == limit
120
- @has_previous = offset > 0
121
- @next_offset = offset + (limit-1)
122
- @previous_offset = offset - (limit-1)
123
- end
124
-
125
- def has_next?
126
- @has_next
127
- end
128
-
129
- def has_previous?
130
- @has_previous
131
- end
132
-
133
- end
134
-
135
- #
136
- #
137
- #
138
- class Paginator
139
-
140
- attr_reader :start, :per_page, :total
141
-
142
- def initialize(start, per_page, total)
143
- @start = start.to_s.to_i
144
- @per_page = per_page.to_s.to_i
145
- @total = total.to_s.to_i
146
- end
147
-
148
- # Returns the current page calculated from 'rows' and 'start'
149
- # WillPaginate hook
150
- def current_page
151
- return 1 if start < 1
152
- @current_page ||= (start / per_page).ceil + 1
153
- end
154
-
155
- # Calcuates the total pages from 'numFound' and 'rows'
156
- # WillPaginate hook
157
- def total_pages
158
- @total_pages ||= per_page > 0 ? (total / per_page.to_f).ceil : 1
159
- end
160
-
161
- # returns the previous page number or 1
162
- # WillPaginate hook
163
- def previous_page
164
- @previous_page ||= (current_page > 1) ? current_page - 1 : 1
165
- end
166
-
167
- # returns the next page number or the last
168
- # WillPaginate hook
169
- def next_page
170
- @next_page ||= (current_page < total_pages) ? current_page + 1 : total_pages
171
- end
172
- end
173
-
174
- def paginator
175
- @paginator ||= Paginator.new(start, rows, total)
176
- end
177
-
178
- # The main select response class.
179
- # Includes the top level Response::Base module
180
- # Includes the Pagination module.
181
- # Each solr hash doc is extended by the DocExt module.
182
-
183
- include RSolr::Ext::Response::Base
184
- include Facets
185
-
186
- def response
187
- self[:response]
188
- end
189
-
190
- def num_found
191
- response[:numFound]
192
- end
193
-
194
- def start
195
- response[:start]
196
- end
197
-
198
- def rows
199
- params[:rows]
200
- end
201
-
202
- alias :total :num_found
203
- alias :offset :start
204
-
205
- def docs
206
- @docs ||= response[:docs].collect{ |d| d=d.to_mash; d.extend(DocExt); d }
207
- end
208
-
209
- # converts to mash, then extends
210
- def self.create(hash)
211
- mash = hash.is_a?(Mash) ? hash : hash.to_mash
212
- mash.extend self
213
- mash
214
- end
215
-
216
- end # end Select
@@ -1,13 +0,0 @@
1
- # for update responses
2
- module RSolr::Ext::Response::Update
3
-
4
- include Base
5
-
6
- # converts to mash, then extends
7
- def self.create(hash)
8
- mash = hash.is_a?(Mash) ? hash : hash.to_mash
9
- mash.extend self
10
- mash
11
- end
12
-
13
- end