supernova 0.6.7 → 0.6.8
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/Gemfile +4 -5
- data/Gemfile.lock +30 -29
- data/VERSION +1 -1
- data/lib/supernova.rb +2 -1
- data/lib/supernova/criteria.rb +68 -28
- data/lib/supernova/solr.rb +41 -2
- data/lib/supernova/solr_criteria.rb +27 -13
- data/lib/supernova/solr_indexer.rb +7 -4
- data/spec/integration/solr_spec.rb +27 -12
- data/spec/spec_helper.rb +1 -0
- data/spec/supernova/criteria_spec.rb +158 -10
- data/spec/supernova/solr_criteria_spec.rb +77 -20
- data/spec/supernova/solr_indexer_spec.rb +21 -7
- data/spec/supernova/solr_spec.rb +13 -26
- data/spec/supernova_spec.rb +2 -2
- data/supernova.gemspec +20 -24
- metadata +144 -233
data/Gemfile
CHANGED
@@ -6,22 +6,21 @@ source "http://rubygems.org"
|
|
6
6
|
# Add dependencies to develop your gem here.
|
7
7
|
# Include everything needed to run rake, tests, features, etc.
|
8
8
|
|
9
|
-
gem "rsolr"
|
10
9
|
gem "will_paginate"
|
11
10
|
gem "json"
|
12
11
|
gem "activesupport"
|
13
|
-
gem "typhoeus"
|
12
|
+
gem "typhoeus", '0.3.3'
|
14
13
|
|
15
14
|
group :development do
|
16
15
|
gem "i18n"
|
17
16
|
gem 'activerecord', '~>3.0.7', :require => "active_record"
|
18
|
-
gem "ruby-debug"
|
19
|
-
gem "mysql2", "~> 0.2.
|
17
|
+
gem "ruby-debug#{RUBY_VERSION != "1.8.7" ? "19" : ""}"
|
18
|
+
gem "mysql2", "~> 0.2.18"
|
20
19
|
gem "ZenTest", "4.5.0"
|
21
20
|
gem "geokit"
|
22
21
|
gem "autotest"
|
23
22
|
gem "autotest-growl"
|
24
|
-
gem "rspec", "~> 2.
|
23
|
+
gem "rspec", "~> 2.8.0"
|
25
24
|
gem "bundler", "~> 1.0.0"
|
26
25
|
gem "jeweler", "~> 1.6.0"
|
27
26
|
gem "rcov", ">= 0"
|
data/Gemfile.lock
CHANGED
@@ -12,13 +12,14 @@ GEM
|
|
12
12
|
arel (~> 2.0.10)
|
13
13
|
tzinfo (~> 0.3.23)
|
14
14
|
activesupport (3.0.9)
|
15
|
+
archive-tar-minitar (0.5.2)
|
15
16
|
arel (2.0.10)
|
16
17
|
autotest (4.4.6)
|
17
18
|
ZenTest (>= 4.4.1)
|
18
19
|
autotest-growl (0.2.9)
|
19
20
|
builder (2.1.2)
|
20
|
-
columnize (0.3.
|
21
|
-
diff-lcs (1.1.
|
21
|
+
columnize (0.3.6)
|
22
|
+
diff-lcs (1.1.3)
|
22
23
|
geokit (1.6.0)
|
23
24
|
git (1.2.5)
|
24
25
|
i18n (0.5.0)
|
@@ -27,33 +28,34 @@ GEM
|
|
27
28
|
git (>= 1.2.5)
|
28
29
|
rake
|
29
30
|
json (1.5.3)
|
30
|
-
|
31
|
-
|
32
|
-
mime-types (1.
|
33
|
-
mysql2 (0.2.
|
31
|
+
linecache19 (0.5.12)
|
32
|
+
ruby_core_source (>= 0.1.4)
|
33
|
+
mime-types (1.17.2)
|
34
|
+
mysql2 (0.2.18)
|
34
35
|
rake (0.9.2)
|
35
|
-
rbx-require-relative (0.0.5)
|
36
36
|
rcov (0.9.9)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
rspec-
|
41
|
-
|
42
|
-
|
43
|
-
rspec-core (2.3.1)
|
44
|
-
rspec-expectations (2.3.0)
|
37
|
+
rspec (2.8.0)
|
38
|
+
rspec-core (~> 2.8.0)
|
39
|
+
rspec-expectations (~> 2.8.0)
|
40
|
+
rspec-mocks (~> 2.8.0)
|
41
|
+
rspec-core (2.8.0)
|
42
|
+
rspec-expectations (2.8.0)
|
45
43
|
diff-lcs (~> 1.1.2)
|
46
|
-
rspec-mocks (2.
|
47
|
-
ruby-debug (0.
|
48
|
-
columnize (>= 0.1)
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
44
|
+
rspec-mocks (2.8.0)
|
45
|
+
ruby-debug-base19 (0.11.25)
|
46
|
+
columnize (>= 0.3.1)
|
47
|
+
linecache19 (>= 0.5.11)
|
48
|
+
ruby_core_source (>= 0.1.4)
|
49
|
+
ruby-debug19 (0.11.6)
|
50
|
+
columnize (>= 0.3.1)
|
51
|
+
linecache19 (>= 0.5.11)
|
52
|
+
ruby-debug-base19 (>= 0.11.19)
|
53
|
+
ruby_core_source (0.1.5)
|
54
|
+
archive-tar-minitar (>= 0.5.2)
|
55
|
+
typhoeus (0.3.3)
|
54
56
|
mime-types
|
55
57
|
tzinfo (0.3.29)
|
56
|
-
will_paginate (
|
58
|
+
will_paginate (3.0.3)
|
57
59
|
|
58
60
|
PLATFORMS
|
59
61
|
ruby
|
@@ -69,10 +71,9 @@ DEPENDENCIES
|
|
69
71
|
i18n
|
70
72
|
jeweler (~> 1.6.0)
|
71
73
|
json
|
72
|
-
mysql2 (~> 0.2.
|
74
|
+
mysql2 (~> 0.2.18)
|
73
75
|
rcov
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
typhoeus
|
76
|
+
rspec (~> 2.8.0)
|
77
|
+
ruby-debug19
|
78
|
+
typhoeus (= 0.3.3)
|
78
79
|
will_paginate
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.6.
|
1
|
+
0.6.8
|
data/lib/supernova.rb
CHANGED
data/lib/supernova/criteria.rb
CHANGED
@@ -17,12 +17,33 @@ class Supernova::Criteria
|
|
17
17
|
def select(*args)
|
18
18
|
self.new.send(:select, *args)
|
19
19
|
end
|
20
|
+
|
21
|
+
def immutable_by_default!
|
22
|
+
@immutable_by_default = true
|
23
|
+
end
|
24
|
+
|
25
|
+
def mutable_by_default!
|
26
|
+
@immutable_by_default = false
|
27
|
+
end
|
28
|
+
|
29
|
+
def immutable_by_default?
|
30
|
+
@immutable_by_default == true
|
31
|
+
end
|
20
32
|
end
|
21
33
|
|
22
34
|
def initialize(clazz = nil)
|
23
35
|
self.clazz = clazz
|
24
36
|
self.filters = {}
|
25
37
|
self.search_options = {}
|
38
|
+
self.immutable! if self.class.immutable_by_default?
|
39
|
+
end
|
40
|
+
|
41
|
+
def immutable!
|
42
|
+
@immutable = true
|
43
|
+
end
|
44
|
+
|
45
|
+
def immutable?
|
46
|
+
@immutable == true
|
26
47
|
end
|
27
48
|
|
28
49
|
def for_classes(clazzes)
|
@@ -33,8 +54,8 @@ class Supernova::Criteria
|
|
33
54
|
merge_search_options :attribute_mapping, mapping
|
34
55
|
end
|
35
56
|
|
36
|
-
def order(
|
37
|
-
merge_search_options :order,
|
57
|
+
def order(*order_options)
|
58
|
+
merge_search_options :order, order_options
|
38
59
|
end
|
39
60
|
|
40
61
|
def limit(limit_option)
|
@@ -58,12 +79,13 @@ class Supernova::Criteria
|
|
58
79
|
end
|
59
80
|
|
60
81
|
def without(filters)
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
82
|
+
self_or_clone.tap do |soc|
|
83
|
+
soc.filters[:without] ||= Hash.new
|
84
|
+
filters.each do |key, value|
|
85
|
+
soc.filters[:without][key] ||= Array.new
|
86
|
+
soc.filters[:without][key] << value if !soc.filters[:without][key].include?(value)
|
87
|
+
end
|
65
88
|
end
|
66
|
-
self
|
67
89
|
end
|
68
90
|
|
69
91
|
def select(*fields)
|
@@ -115,32 +137,49 @@ class Supernova::Criteria
|
|
115
137
|
end
|
116
138
|
|
117
139
|
def merge_filters(key, value)
|
118
|
-
merge_filters_or_search_options(
|
140
|
+
merge_filters_or_search_options(:filters, key, value)
|
119
141
|
end
|
120
142
|
|
121
143
|
def merge_filters_array(key, fields)
|
122
|
-
|
123
|
-
|
124
|
-
|
144
|
+
self_or_clone.tap do |soc|
|
145
|
+
soc.search_options[key] ||= Array.new
|
146
|
+
fields.flatten.each do |field|
|
147
|
+
soc.search_options[key] << field if !soc.search_options[key].include?(field)
|
148
|
+
end
|
125
149
|
end
|
126
|
-
|
150
|
+
end
|
151
|
+
|
152
|
+
def clone
|
153
|
+
Marshal.load(Marshal.dump(self))
|
154
|
+
end
|
155
|
+
|
156
|
+
def self_or_clone
|
157
|
+
immutable? ? clone : self
|
127
158
|
end
|
128
159
|
|
129
160
|
def merge_search_options(key, value)
|
130
|
-
merge_filters_or_search_options(
|
161
|
+
merge_filters_or_search_options(:search_options, key, value)
|
162
|
+
end
|
163
|
+
|
164
|
+
def except(key)
|
165
|
+
self_or_clone.tap do |soc|
|
166
|
+
soc.search_options.delete(key)
|
167
|
+
end
|
131
168
|
end
|
132
169
|
|
133
|
-
def merge_filters_or_search_options(
|
134
|
-
|
135
|
-
reference
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
170
|
+
def merge_filters_or_search_options(reference_method, key, value)
|
171
|
+
self_or_clone.tap do |soc|
|
172
|
+
reference = soc.send(reference_method)
|
173
|
+
if value.is_a?(Hash)
|
174
|
+
reference[key] ||= Hash.new
|
175
|
+
reference[key].merge!(value)
|
176
|
+
elsif [:select, :order].include?(key)
|
177
|
+
reference[key] ||= Array.new
|
178
|
+
reference[key] += (value || [])
|
179
|
+
else
|
180
|
+
reference[key] = value
|
181
|
+
end
|
142
182
|
end
|
143
|
-
self
|
144
183
|
end
|
145
184
|
|
146
185
|
def to_parameters
|
@@ -158,7 +197,7 @@ class Supernova::Criteria
|
|
158
197
|
end
|
159
198
|
|
160
199
|
def populated?
|
161
|
-
instance_variables.include?("@results")
|
200
|
+
instance_variables.map(&:to_s).include?("@results")
|
162
201
|
end
|
163
202
|
|
164
203
|
def execute
|
@@ -186,17 +225,18 @@ class Supernova::Criteria
|
|
186
225
|
end
|
187
226
|
|
188
227
|
def merge(other_criteria)
|
228
|
+
ret = self_or_clone
|
189
229
|
other_criteria.filters.each do |key, value|
|
190
|
-
|
230
|
+
ret = ret.merge_filters(key, value)
|
191
231
|
end
|
192
232
|
other_criteria.search_options.each do |key, value|
|
193
|
-
|
233
|
+
ret = ret.merge_search_options(key, value)
|
194
234
|
end
|
195
|
-
|
235
|
+
ret
|
196
236
|
end
|
197
237
|
|
198
238
|
def method_missing(*args, &block)
|
199
|
-
if Supernova::Collection.instance_methods.include?(args.first.to_s)
|
239
|
+
if Supernova::Collection.instance_methods.map(&:to_s).include?(args.first.to_s)
|
200
240
|
populate
|
201
241
|
@results.send(*args, &block)
|
202
242
|
elsif self.named_scope_defined?(args.first)
|
data/lib/supernova/solr.rb
CHANGED
@@ -1,15 +1,54 @@
|
|
1
1
|
require "supernova/solr_criteria"
|
2
2
|
|
3
3
|
module Supernova::Solr
|
4
|
+
class ConnectionDummy
|
5
|
+
def add(row)
|
6
|
+
deprication_warning("add")
|
7
|
+
Supernova::Solr.add(row)
|
8
|
+
end
|
9
|
+
|
10
|
+
def commit
|
11
|
+
deprication_warning("commit!")
|
12
|
+
Supernova::Solr.commit!
|
13
|
+
end
|
14
|
+
|
15
|
+
def deprication_warning(instead)
|
16
|
+
puts "DEPRICATION WARNING: calling #{caller.first[/\`(.*?)\'/, 1]} is depricated. Use Supernova::Solr.#{instead} instead. Called from #{filter_callers(caller).at(1)}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def filter_callers(callers)
|
20
|
+
callers.reject { |c| c.include?("/gems/")}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
4
24
|
class << self
|
5
25
|
attr_accessor :url
|
6
26
|
|
27
|
+
def select_url
|
28
|
+
"#{url}/select"
|
29
|
+
end
|
30
|
+
|
7
31
|
def connection
|
8
|
-
|
32
|
+
ConnectionDummy.new
|
33
|
+
end
|
34
|
+
|
35
|
+
def update_request(payload)
|
36
|
+
Typhoeus::Request.post("#{url}/update",
|
37
|
+
:body => %(<?xml version="1.0" encoding="UTF-8"?>#{payload}), :headers => { "Content-Type" => "text/xml"}
|
38
|
+
)
|
9
39
|
end
|
10
40
|
|
11
41
|
def truncate!
|
12
|
-
|
42
|
+
update_request("<delete><query>*:*</query></delete>")
|
43
|
+
end
|
44
|
+
|
45
|
+
def commit!
|
46
|
+
update_request("<commit />")
|
47
|
+
end
|
48
|
+
|
49
|
+
# only to be used for testing
|
50
|
+
def add(row)
|
51
|
+
Supernova::SolrIndexer.new.index_with_json([row])
|
13
52
|
end
|
14
53
|
end
|
15
54
|
|
@@ -1,16 +1,17 @@
|
|
1
|
-
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
2
|
|
3
3
|
class Supernova::SolrCriteria < Supernova::Criteria
|
4
4
|
# move this into separate methods (test each separatly)
|
5
5
|
def to_params
|
6
6
|
solr_options = { :fq => [], :q => "*:*" }
|
7
|
+
solr_options[:wt] = search_options[:wt] if search_options[:wt]
|
7
8
|
solr_options[:fq] += fq_from_with(self.filters[:with])
|
8
9
|
if self.filters[:without]
|
9
10
|
self.filters[:without].each do |field, values|
|
10
11
|
solr_options[:fq] += values.map { |value| "!#{solr_field_from_field(field)}:#{value}" }
|
11
12
|
end
|
12
13
|
end
|
13
|
-
solr_options[:sort] = convert_search_order(self.search_options[:order]) if self.search_options[:order]
|
14
|
+
solr_options[:sort] = convert_search_order(self.search_options[:order].join(", ")) if self.search_options[:order]
|
14
15
|
if self.search_options[:search].is_a?(Array)
|
15
16
|
solr_options[:q] = self.search_options[:search].map { |query| "(#{query})" }.join(" AND ")
|
16
17
|
end
|
@@ -22,7 +23,7 @@ class Supernova::SolrCriteria < Supernova::Criteria
|
|
22
23
|
solr_options[:fq] << "{!geofilt}"
|
23
24
|
end
|
24
25
|
if self.search_options[:select]
|
25
|
-
self.search_options[:select] << :id
|
26
|
+
self.search_options[:select] << "id" if !self.search_options[:select].map(&:to_s).include?("id")
|
26
27
|
solr_options[:fl] = self.search_options[:select].compact.map { |field| solr_field_from_field(field) }.join(",")
|
27
28
|
end
|
28
29
|
solr_options[:fq] << "type:#{self.clazz}" if self.clazz
|
@@ -40,13 +41,13 @@ class Supernova::SolrCriteria < Supernova::Criteria
|
|
40
41
|
end
|
41
42
|
|
42
43
|
def convert_search_order(order)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
44
|
+
order.split(/\s*,\s*/).map do |chunk|
|
45
|
+
if chunk.match(/(.*?) (asc|desc)/i)
|
46
|
+
"#{solr_field_from_field($1)} #{$2}"
|
47
|
+
else
|
48
|
+
chunk
|
49
|
+
end
|
50
|
+
end.join(",")
|
50
51
|
end
|
51
52
|
|
52
53
|
def solr_field_from_field(field)
|
@@ -147,6 +148,10 @@ class Supernova::SolrCriteria < Supernova::Criteria
|
|
147
148
|
end
|
148
149
|
end
|
149
150
|
|
151
|
+
def format(the_format)
|
152
|
+
merge_search_options(:wt, the_format)
|
153
|
+
end
|
154
|
+
|
150
155
|
def set_first_responding_attribute(doc, solr_key, value)
|
151
156
|
[reverse_lookup_solr_field(solr_key), solr_key].each do |key|
|
152
157
|
meth = :"#{key}="
|
@@ -166,8 +171,12 @@ class Supernova::SolrCriteria < Supernova::Criteria
|
|
166
171
|
end
|
167
172
|
end
|
168
173
|
|
174
|
+
def execute_raw
|
175
|
+
JSON.parse(Typhoeus::Request.post(Supernova::Solr.select_url, :params => to_params.merge(:wt => "json")).body)
|
176
|
+
end
|
177
|
+
|
169
178
|
def execute
|
170
|
-
response =
|
179
|
+
response = execute_raw
|
171
180
|
collection = Supernova::Collection.new(current_page, per_page == 0 ? 1 : per_page, response["response"]["numFound"])
|
172
181
|
collection.original_response = response
|
173
182
|
collection.facets = hashify_facets_from_response(response)
|
@@ -175,8 +184,13 @@ class Supernova::SolrCriteria < Supernova::Criteria
|
|
175
184
|
collection
|
176
185
|
end
|
177
186
|
|
187
|
+
def only_ids
|
188
|
+
self_or_clone.except(:select).select("id")
|
189
|
+
end
|
190
|
+
|
178
191
|
def ids
|
179
|
-
|
180
|
-
|
192
|
+
only_ids.execute.tap do |col|
|
193
|
+
col.replace(col.map { |h| h["id"].split("/").last.to_i })
|
194
|
+
end
|
181
195
|
end
|
182
196
|
end
|
@@ -232,6 +232,7 @@ class Supernova::SolrIndexer
|
|
232
232
|
end
|
233
233
|
|
234
234
|
def index_with_json(rows)
|
235
|
+
return false if rows.empty?
|
235
236
|
options && options[:use_json_file] ? index_with_json_file(rows) : index_with_json_string(rows)
|
236
237
|
end
|
237
238
|
|
@@ -246,11 +247,13 @@ class Supernova::SolrIndexer
|
|
246
247
|
index_rows(query_db(query))
|
247
248
|
end
|
248
249
|
|
250
|
+
# just to be backwards compatible
|
249
251
|
def index_directly(rows)
|
250
|
-
rows
|
251
|
-
|
252
|
-
|
253
|
-
|
252
|
+
index_with_json(rows)
|
253
|
+
# rows.each do |row|
|
254
|
+
# row = Supernova::Solr.connection.add(row)
|
255
|
+
# end
|
256
|
+
# Supernova::Solr.connection.commit if rows.any?
|
254
257
|
end
|
255
258
|
|
256
259
|
def index_with_json_file(rows)
|