supernova 0.4.18 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -9,10 +9,10 @@ source "http://rubygems.org"
9
9
  gem "rsolr"
10
10
  gem "will_paginate"
11
11
  gem "json"
12
- gem "i18n"
13
12
  gem "activesupport"
14
13
 
15
14
  group :development do
15
+ gem "i18n"
16
16
  gem 'activerecord', '~>3.0.7', :require => "active_record"
17
17
  gem "ruby-debug"
18
18
  gem "mysql2", "~> 0.2.7"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.18
1
+ 0.6.0
@@ -1,4 +1,5 @@
1
1
  require "will_paginate"
2
2
 
3
3
  class Supernova::Collection < WillPaginate::Collection
4
+ attr_accessor :original_response, :facets
4
5
  end
@@ -69,6 +69,10 @@ class Supernova::Criteria
69
69
  def select(*fields)
70
70
  merge_filters_array :select, fields
71
71
  end
72
+
73
+ def facet_fields(*fields)
74
+ merge_filters_array :facets, fields
75
+ end
72
76
 
73
77
  def conditions(filters)
74
78
  merge_filters :conditions, filters
@@ -27,6 +27,11 @@ class Supernova::SolrCriteria < Supernova::Criteria
27
27
  end
28
28
  solr_options[:fq] << "type:#{self.clazz}" if self.clazz
29
29
 
30
+ if self.search_options[:facets]
31
+ solr_options[:facet] = true
32
+ solr_options["facet.field"] = self.search_options[:facets].compact.map { |field| solr_field_from_field(field) }
33
+ end
34
+
30
35
  if self.search_options[:pagination]
31
36
  solr_options[:rows] = per_page
32
37
  solr_options[:start] = (current_page - 1) * solr_options[:rows]
@@ -142,9 +147,20 @@ class Supernova::SolrCriteria < Supernova::Criteria
142
147
  end
143
148
  end
144
149
 
150
+ def hashify_facets_from_response(response)
151
+ if response["facet_counts"] && response["facet_counts"]["facet_fields"]
152
+ response["facet_counts"]["facet_fields"].inject({}) do |hash, (key, values)|
153
+ hash[reverse_lookup_solr_field(key)] = Hash[*values]
154
+ hash
155
+ end
156
+ end
157
+ end
158
+
145
159
  def execute
146
160
  response = Supernova::Solr.connection.post("select", :data => to_params)
147
161
  collection = Supernova::Collection.new(current_page, per_page, response["response"]["numFound"])
162
+ collection.original_response = response
163
+ collection.facets = hashify_facets_from_response(response)
148
164
  collection.replace(build_docs(response["response"]["docs"]))
149
165
  collection
150
166
  end
@@ -240,4 +240,31 @@ describe "Solr" do
240
240
  results.first.should == { "id" => "offers/1", "user_id_i" => 1 }
241
241
  end
242
242
  end
243
+
244
+ describe "#facets" do
245
+ it "returns the correct facets hash" do
246
+ # pending "fix me"
247
+ Supernova::Solr.connection.add(:id => "offers/3", :type => "Offer", :user_id_i => 3, :enabled_b => false,
248
+ :text_t => "Hans Müller", :popularity_i => 10, :type => "Offer"
249
+ )
250
+ Supernova::Solr.connection.commit
251
+ new_criteria.facet_fields(:text_t).execute.facets.should == {"text_t"=>{"mintal"=>1, "marek"=>1, "meyer"=>1, "m\303\274ller"=>1, "han"=>2}}
252
+ end
253
+ end
254
+
255
+ describe "with mapping" do
256
+ before(:each) do
257
+ @clazz = Class.new(Supernova::SolrIndexer)
258
+ @clazz.has :location, :type => :string
259
+ @clazz.has :city, :type => :string
260
+ end
261
+
262
+ it "returns the correct facets" do
263
+ row1 = { "id" => 1, "location" => "Hamburg", "type" => "Offer" }
264
+ row2 = { "id" => 2, "location" => "Hamburg", "type" => "Offer" }
265
+ row3 = { "id" => 3, "location" => "Berlin", "type" => "Offer" }
266
+ @clazz.new.index_rows([row1, row2, row3])
267
+ @clazz.facet_fields(:location).execute.facets.should == { :location=>{ "Berlin"=>1, "Hamburg"=>2 } }
268
+ end
269
+ end
243
270
  end
@@ -29,7 +29,8 @@ describe "Supernova::Criteria" do
29
29
  [:near, "test"],
30
30
  [:within, 10],
31
31
  [:options, {}],
32
- [:without, {}]
32
+ [:without, {}],
33
+ [:facet_fields, "name"]
33
34
  ].each do |args|
34
35
  it "returns the scope itself for #{args.first}" do
35
36
  scope.send(*args).should == scope
@@ -43,6 +44,12 @@ describe "Supernova::Criteria" do
43
44
  end
44
45
  end
45
46
 
47
+ describe "#facet_fields" do
48
+ it "sets the facets" do
49
+ scope.facet_fields("title").facet_fields("name", "first_name").search_options[:facets].should == %w(title name first_name)
50
+ end
51
+ end
52
+
46
53
  describe "#order" do
47
54
  it "sets the order statement" do
48
55
  scope.order("popularity desc").search_options[:order].should == "popularity desc"
@@ -82,7 +82,6 @@ describe Supernova::SolrCriteria do
82
82
  end
83
83
  end
84
84
 
85
-
86
85
  it "sets search correct search query" do
87
86
  criteria.search("some query").to_params[:q].should == "(some query)"
88
87
  end
@@ -104,6 +103,16 @@ describe Supernova::SolrCriteria do
104
103
  criteria.select(:user_id).select(:user_id).select(:enabled).to_params[:fl].should == "user_id,enabled,id"
105
104
  end
106
105
 
106
+ it "sets the correct facet options when set" do
107
+ params = criteria.facet_fields(:name).to_params
108
+ params[:facet].should == true
109
+ end
110
+
111
+ it "sets all facet fields" do
112
+ params = criteria.facet_fields(:name).facet_fields(:title).to_params
113
+ params["facet.field"].should == ["name", "title"]
114
+ end
115
+
107
116
  it "uses mapped fields for select" do
108
117
  mapping = {
109
118
  :user_id => { :type => :integer },
@@ -196,6 +205,10 @@ describe Supernova::SolrCriteria do
196
205
  rsolr.stub!(:post).and_return solr_response
197
206
  end
198
207
 
208
+ it "sets the original response" do
209
+ criteria.execute.original_response.should == solr_response
210
+ end
211
+
199
212
  it "calls to_params" do
200
213
  criteria.should_receive(:to_params).and_return params
201
214
  criteria.execute
@@ -240,13 +253,37 @@ describe Supernova::SolrCriteria do
240
253
  end
241
254
 
242
255
  it "calls replace on collection wit returned docs" do
243
- col = double("collection")
256
+ col = double("collection", :original_response= => true, :facets= => true)
244
257
  Supernova::Collection.stub!(:new).and_return col
245
258
  built_docs = double("built docs")
246
259
  criteria.stub!(:build_docs).and_return built_docs
247
260
  col.should_receive(:replace).with(built_docs)
248
261
  criteria.execute
249
262
  end
263
+
264
+ it "sets the correct facets" do
265
+ rsolr.stub!(:post).and_return facet_response
266
+ criteria.should_receive(:hashify_facets_from_response).with(facet_response).and_return({ :a => 1 })
267
+ criteria.execute.facets.should == {:a => 1}
268
+ end
269
+ end
270
+
271
+ let(:facet_response) {
272
+ {
273
+ "response"=>{"start"=>0, "docs"=>[{"popularity_i"=>10, "enabled_b"=>false, "id"=>"offers/1", "user_id_i"=>1, "text_t"=>"Hans Meyer", "type"=>"Offer", "location_p"=>"47,11"}, {"popularity_i"=>1, "enabled_b"=>true, "id"=>"offers/2", "user_id_i"=>2, "text_t"=>"Marek Mintal", "type"=>"Offer", "location_p"=>"46.9981112912042,11.6587158814378"}], "numFound"=>2}, "facet_counts"=>{"facet_fields"=>{"text_t"=>["han", 1, "marek", 1, "meyer", 1, "mintal", 1]}, "facet_ranges"=>{}, "facet_dates"=>{}, "facet_queries"=>{}}, "responseHeader"=>{"QTime"=>4, "params"=>{"fq"=>"type:Offer", "facet.field"=>"text_t", "facet"=>"true", "q"=>"*:*", "wt"=>"ruby"}, "status"=>0}
274
+ }
275
+ }
276
+
277
+ describe "#hashify_facets_from_response" do
278
+ it "returns nil when nothing found" do
279
+ criteria.hashify_facets_from_response({}).should == nil
280
+ end
281
+
282
+ it "returns the correct hash when facets returned" do
283
+ criteria.hashify_facets_from_response(facet_response).should == {
284
+ "text_t" => { "han" => 1, "marek" => 1, "meyer" => 1, "mintal" => 1 }
285
+ }
286
+ end
250
287
  end
251
288
 
252
289
  describe "#build_docs" do
@@ -5,12 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{supernova}
8
- s.version = "0.4.18"
8
+ s.version = "0.6.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tobias Schwab"]
12
12
  s.date = %q{2011-08-04}
13
- s.default_executable = %q{start_solr}
14
13
  s.description = %q{Unified search scopes}
15
14
  s.email = %q{tobias.schwab@dynport.de}
16
15
  s.executables = ["start_solr"]
@@ -95,7 +94,7 @@ Gem::Specification.new do |s|
95
94
  s.homepage = %q{http://github.com/dynport/supernova}
96
95
  s.licenses = ["MIT"]
97
96
  s.require_paths = ["lib"]
98
- s.rubygems_version = %q{1.6.2}
97
+ s.rubygems_version = %q{1.7.2}
99
98
  s.summary = %q{Unified search scopes}
100
99
 
101
100
  if s.respond_to? :specification_version then
@@ -105,8 +104,8 @@ Gem::Specification.new do |s|
105
104
  s.add_runtime_dependency(%q<rsolr>, [">= 0"])
106
105
  s.add_runtime_dependency(%q<will_paginate>, [">= 0"])
107
106
  s.add_runtime_dependency(%q<json>, [">= 0"])
108
- s.add_runtime_dependency(%q<i18n>, [">= 0"])
109
107
  s.add_runtime_dependency(%q<activesupport>, [">= 0"])
108
+ s.add_development_dependency(%q<i18n>, [">= 0"])
110
109
  s.add_development_dependency(%q<activerecord>, ["~> 3.0.7"])
111
110
  s.add_development_dependency(%q<ruby-debug>, [">= 0"])
112
111
  s.add_development_dependency(%q<mysql2>, ["~> 0.2.7"])
@@ -122,8 +121,8 @@ Gem::Specification.new do |s|
122
121
  s.add_dependency(%q<rsolr>, [">= 0"])
123
122
  s.add_dependency(%q<will_paginate>, [">= 0"])
124
123
  s.add_dependency(%q<json>, [">= 0"])
125
- s.add_dependency(%q<i18n>, [">= 0"])
126
124
  s.add_dependency(%q<activesupport>, [">= 0"])
125
+ s.add_dependency(%q<i18n>, [">= 0"])
127
126
  s.add_dependency(%q<activerecord>, ["~> 3.0.7"])
128
127
  s.add_dependency(%q<ruby-debug>, [">= 0"])
129
128
  s.add_dependency(%q<mysql2>, ["~> 0.2.7"])
@@ -140,8 +139,8 @@ Gem::Specification.new do |s|
140
139
  s.add_dependency(%q<rsolr>, [">= 0"])
141
140
  s.add_dependency(%q<will_paginate>, [">= 0"])
142
141
  s.add_dependency(%q<json>, [">= 0"])
143
- s.add_dependency(%q<i18n>, [">= 0"])
144
142
  s.add_dependency(%q<activesupport>, [">= 0"])
143
+ s.add_dependency(%q<i18n>, [">= 0"])
145
144
  s.add_dependency(%q<activerecord>, ["~> 3.0.7"])
146
145
  s.add_dependency(%q<ruby-debug>, [">= 0"])
147
146
  s.add_dependency(%q<mysql2>, ["~> 0.2.7"])
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: supernova
3
3
  version: !ruby/object:Gem::Version
4
- hash: 43
4
+ hash: 7
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 4
9
- - 18
10
- version: 0.4.18
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tobias Schwab
@@ -15,11 +15,9 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-04 00:00:00 +02:00
19
- default_executable: start_solr
18
+ date: 2011-08-04 00:00:00 Z
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
- type: :runtime
23
21
  requirement: &id001 !ruby/object:Gem::Requirement
24
22
  none: false
25
23
  requirements:
@@ -29,11 +27,11 @@ dependencies:
29
27
  segments:
30
28
  - 0
31
29
  version: "0"
32
- name: rsolr
33
30
  version_requirements: *id001
31
+ name: rsolr
34
32
  prerelease: false
35
- - !ruby/object:Gem::Dependency
36
33
  type: :runtime
34
+ - !ruby/object:Gem::Dependency
37
35
  requirement: &id002 !ruby/object:Gem::Requirement
38
36
  none: false
39
37
  requirements:
@@ -43,11 +41,11 @@ dependencies:
43
41
  segments:
44
42
  - 0
45
43
  version: "0"
46
- name: will_paginate
47
44
  version_requirements: *id002
45
+ name: will_paginate
48
46
  prerelease: false
49
- - !ruby/object:Gem::Dependency
50
47
  type: :runtime
48
+ - !ruby/object:Gem::Dependency
51
49
  requirement: &id003 !ruby/object:Gem::Requirement
52
50
  none: false
53
51
  requirements:
@@ -57,11 +55,11 @@ dependencies:
57
55
  segments:
58
56
  - 0
59
57
  version: "0"
60
- name: json
61
58
  version_requirements: *id003
59
+ name: json
62
60
  prerelease: false
63
- - !ruby/object:Gem::Dependency
64
61
  type: :runtime
62
+ - !ruby/object:Gem::Dependency
65
63
  requirement: &id004 !ruby/object:Gem::Requirement
66
64
  none: false
67
65
  requirements:
@@ -71,11 +69,11 @@ dependencies:
71
69
  segments:
72
70
  - 0
73
71
  version: "0"
74
- name: i18n
75
72
  version_requirements: *id004
73
+ name: activesupport
76
74
  prerelease: false
77
- - !ruby/object:Gem::Dependency
78
75
  type: :runtime
76
+ - !ruby/object:Gem::Dependency
79
77
  requirement: &id005 !ruby/object:Gem::Requirement
80
78
  none: false
81
79
  requirements:
@@ -85,11 +83,11 @@ dependencies:
85
83
  segments:
86
84
  - 0
87
85
  version: "0"
88
- name: activesupport
89
86
  version_requirements: *id005
87
+ name: i18n
90
88
  prerelease: false
91
- - !ruby/object:Gem::Dependency
92
89
  type: :development
90
+ - !ruby/object:Gem::Dependency
93
91
  requirement: &id006 !ruby/object:Gem::Requirement
94
92
  none: false
95
93
  requirements:
@@ -101,11 +99,11 @@ dependencies:
101
99
  - 0
102
100
  - 7
103
101
  version: 3.0.7
104
- name: activerecord
105
102
  version_requirements: *id006
103
+ name: activerecord
106
104
  prerelease: false
107
- - !ruby/object:Gem::Dependency
108
105
  type: :development
106
+ - !ruby/object:Gem::Dependency
109
107
  requirement: &id007 !ruby/object:Gem::Requirement
110
108
  none: false
111
109
  requirements:
@@ -115,11 +113,11 @@ dependencies:
115
113
  segments:
116
114
  - 0
117
115
  version: "0"
118
- name: ruby-debug
119
116
  version_requirements: *id007
117
+ name: ruby-debug
120
118
  prerelease: false
121
- - !ruby/object:Gem::Dependency
122
119
  type: :development
120
+ - !ruby/object:Gem::Dependency
123
121
  requirement: &id008 !ruby/object:Gem::Requirement
124
122
  none: false
125
123
  requirements:
@@ -131,11 +129,11 @@ dependencies:
131
129
  - 2
132
130
  - 7
133
131
  version: 0.2.7
134
- name: mysql2
135
132
  version_requirements: *id008
133
+ name: mysql2
136
134
  prerelease: false
137
- - !ruby/object:Gem::Dependency
138
135
  type: :development
136
+ - !ruby/object:Gem::Dependency
139
137
  requirement: &id009 !ruby/object:Gem::Requirement
140
138
  none: false
141
139
  requirements:
@@ -147,11 +145,11 @@ dependencies:
147
145
  - 5
148
146
  - 0
149
147
  version: 4.5.0
150
- name: ZenTest
151
148
  version_requirements: *id009
149
+ name: ZenTest
152
150
  prerelease: false
153
- - !ruby/object:Gem::Dependency
154
151
  type: :development
152
+ - !ruby/object:Gem::Dependency
155
153
  requirement: &id010 !ruby/object:Gem::Requirement
156
154
  none: false
157
155
  requirements:
@@ -161,11 +159,11 @@ dependencies:
161
159
  segments:
162
160
  - 0
163
161
  version: "0"
164
- name: geokit
165
162
  version_requirements: *id010
163
+ name: geokit
166
164
  prerelease: false
167
- - !ruby/object:Gem::Dependency
168
165
  type: :development
166
+ - !ruby/object:Gem::Dependency
169
167
  requirement: &id011 !ruby/object:Gem::Requirement
170
168
  none: false
171
169
  requirements:
@@ -175,11 +173,11 @@ dependencies:
175
173
  segments:
176
174
  - 0
177
175
  version: "0"
178
- name: autotest
179
176
  version_requirements: *id011
177
+ name: autotest
180
178
  prerelease: false
181
- - !ruby/object:Gem::Dependency
182
179
  type: :development
180
+ - !ruby/object:Gem::Dependency
183
181
  requirement: &id012 !ruby/object:Gem::Requirement
184
182
  none: false
185
183
  requirements:
@@ -189,11 +187,11 @@ dependencies:
189
187
  segments:
190
188
  - 0
191
189
  version: "0"
192
- name: autotest-growl
193
190
  version_requirements: *id012
191
+ name: autotest-growl
194
192
  prerelease: false
195
- - !ruby/object:Gem::Dependency
196
193
  type: :development
194
+ - !ruby/object:Gem::Dependency
197
195
  requirement: &id013 !ruby/object:Gem::Requirement
198
196
  none: false
199
197
  requirements:
@@ -205,11 +203,11 @@ dependencies:
205
203
  - 3
206
204
  - 0
207
205
  version: 2.3.0
208
- name: rspec
209
206
  version_requirements: *id013
207
+ name: rspec
210
208
  prerelease: false
211
- - !ruby/object:Gem::Dependency
212
209
  type: :development
210
+ - !ruby/object:Gem::Dependency
213
211
  requirement: &id014 !ruby/object:Gem::Requirement
214
212
  none: false
215
213
  requirements:
@@ -221,11 +219,11 @@ dependencies:
221
219
  - 0
222
220
  - 0
223
221
  version: 1.0.0
224
- name: bundler
225
222
  version_requirements: *id014
223
+ name: bundler
226
224
  prerelease: false
227
- - !ruby/object:Gem::Dependency
228
225
  type: :development
226
+ - !ruby/object:Gem::Dependency
229
227
  requirement: &id015 !ruby/object:Gem::Requirement
230
228
  none: false
231
229
  requirements:
@@ -237,11 +235,11 @@ dependencies:
237
235
  - 6
238
236
  - 0
239
237
  version: 1.6.0
240
- name: jeweler
241
238
  version_requirements: *id015
239
+ name: jeweler
242
240
  prerelease: false
243
- - !ruby/object:Gem::Dependency
244
241
  type: :development
242
+ - !ruby/object:Gem::Dependency
245
243
  requirement: &id016 !ruby/object:Gem::Requirement
246
244
  none: false
247
245
  requirements:
@@ -251,9 +249,10 @@ dependencies:
251
249
  segments:
252
250
  - 0
253
251
  version: "0"
254
- name: rcov
255
252
  version_requirements: *id016
253
+ name: rcov
256
254
  prerelease: false
255
+ type: :development
257
256
  description: Unified search scopes
258
257
  email: tobias.schwab@dynport.de
259
258
  executables:
@@ -336,7 +335,6 @@ files:
336
335
  - spec/supernova/symbol_extensions_spec.rb
337
336
  - spec/supernova_spec.rb
338
337
  - supernova.gemspec
339
- has_rdoc: true
340
338
  homepage: http://github.com/dynport/supernova
341
339
  licenses:
342
340
  - MIT
@@ -366,7 +364,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
366
364
  requirements: []
367
365
 
368
366
  rubyforge_project:
369
- rubygems_version: 1.6.2
367
+ rubygems_version: 1.7.2
370
368
  signing_key:
371
369
  specification_version: 3
372
370
  summary: Unified search scopes