activesearch 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +2 -0
- data/Rakefile +19 -1
- data/activesearch.gemspec +5 -4
- data/lib/activesearch/algolia/worker.rb +2 -2
- data/lib/activesearch/algolia.rb +31 -19
- data/lib/activesearch/base.rb +18 -6
- data/lib/activesearch/mongoid/index.rb +115 -0
- data/lib/activesearch/mongoid.rb +24 -7
- data/lib/activesearch/result.rb +9 -2
- data/lib/activesearch/version.rb +1 -1
- data/spec/engines/algolia_spec.rb +32 -0
- data/spec/{base_spec.rb → engines/base_spec.rb} +13 -13
- data/spec/engines/mongoid_spec.rb +56 -0
- data/spec/models/algolia.rb +4 -6
- data/spec/models/elastic_search.rb +6 -9
- data/spec/models/mongoid.rb +16 -22
- data/spec/spec_helper.rb +43 -53
- data/spec/support/active_mimic.rb +56 -0
- data/spec/support/setup_engine.rb +53 -0
- data/spec/support/shared_examples_for_engines.rb +63 -0
- metadata +33 -12
- data/lib/activesearch/mongoid/model.rb +0 -67
- data/spec/algolia_spec.rb +0 -29
- data/spec/engines_spec.rb +0 -90
- data/spec/mongoid_spec.rb +0 -52
data/spec/models/mongoid.rb
CHANGED
@@ -1,46 +1,40 @@
|
|
1
|
-
require 'mongoid'
|
2
|
-
require 'activesearch/mongoid'
|
3
|
-
|
4
|
-
Mongoid.configure do |config|
|
5
|
-
config.sessions = {:default => {:hosts => ["localhost"], :database => "activesearch_test"}}
|
6
|
-
end
|
7
|
-
|
8
1
|
class MongoidModel
|
9
2
|
include Mongoid::Document
|
10
3
|
include ActiveSearch::Mongoid
|
11
|
-
|
12
|
-
field :title,
|
13
|
-
field :text,
|
14
|
-
field :junk,
|
15
|
-
field :special,
|
16
|
-
field :scope_id,
|
17
|
-
field :
|
18
|
-
|
19
|
-
|
4
|
+
|
5
|
+
field :title, type: String
|
6
|
+
field :text, type: String
|
7
|
+
field :junk, type: String
|
8
|
+
field :special, type: Boolean, default: false
|
9
|
+
field :scope_id, type: Integer
|
10
|
+
field :color, type: String, localize: true
|
11
|
+
field :tags, type: Array
|
12
|
+
|
13
|
+
search_by [:title, :text, :tags, :color, store: [:title, :junk, :scope_id]], unless: :special?
|
20
14
|
end
|
21
15
|
|
22
16
|
class AnotherMongoidModel
|
23
17
|
include Mongoid::Document
|
24
18
|
include ActiveSearch::Mongoid
|
25
|
-
|
19
|
+
|
26
20
|
field :title, type: String
|
27
21
|
field :scope_id, type: Integer
|
22
|
+
field :color, localize: true
|
28
23
|
search_by :options_for_search
|
29
|
-
|
24
|
+
|
30
25
|
def options_for_search
|
31
|
-
[:title,
|
26
|
+
[:title, store: [:title, :virtual, :scope_id, :color]]
|
32
27
|
end
|
33
|
-
|
28
|
+
|
34
29
|
def virtual
|
35
30
|
"virtual"
|
36
31
|
end
|
37
32
|
end
|
38
33
|
|
39
|
-
|
40
34
|
class LocalizedMongoidModel
|
41
35
|
include Mongoid::Document
|
42
36
|
include ActiveSearch::Mongoid
|
43
|
-
|
37
|
+
|
44
38
|
field :title, localize: true
|
45
39
|
field :special_type
|
46
40
|
search_by [:title, store: [:title]]
|
data/spec/spec_helper.rb
CHANGED
@@ -1,61 +1,51 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup
|
4
|
+
Bundler.require
|
5
|
+
|
6
|
+
require 'rspec'
|
7
|
+
|
8
|
+
require 'activesearch/base'
|
1
9
|
require 'active_model'
|
2
10
|
require 'active_attr'
|
3
11
|
require 'sucker_punch'
|
4
12
|
require 'sucker_punch/testing/inline'
|
5
13
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
def type
|
28
|
-
self.class.to_s
|
29
|
-
end
|
30
|
-
|
31
|
-
def save
|
32
|
-
self.id ||= self.class.next_id
|
33
|
-
run_callbacks :save do
|
34
|
-
true
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def destroy
|
39
|
-
run_callbacks :destroy do
|
40
|
-
true
|
41
|
-
end
|
14
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
15
|
+
# in spec/support/ and its subdirectories.
|
16
|
+
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |f| require f }
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
|
20
|
+
require 'database_cleaner'
|
21
|
+
require 'database_cleaner/mongoid/truncation'
|
22
|
+
|
23
|
+
config.backtrace_clean_patterns = [
|
24
|
+
/\/lib\d*\/ruby\//,
|
25
|
+
/bin\//,
|
26
|
+
/gems/,
|
27
|
+
/spec\/spec_helper\.rb/,
|
28
|
+
/lib\/rspec\/(core|expectations|matchers|mocks)/
|
29
|
+
]
|
30
|
+
|
31
|
+
config.before(:suite) do
|
32
|
+
DatabaseCleaner['mongoid'].strategy = :truncation
|
42
33
|
end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
@next_id += 1
|
34
|
+
|
35
|
+
config.before(:each) do
|
36
|
+
DatabaseCleaner.start
|
47
37
|
end
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
38
|
+
|
39
|
+
config.after(:each) do
|
40
|
+
# ElasticSearch engine
|
41
|
+
# Tire::Configuration.client.delete "#{Tire::Configuration.url}/_all"
|
42
|
+
|
43
|
+
# Algolia engine
|
44
|
+
# ActiveSearch::Algolia::Client.new.delete_index
|
45
|
+
|
46
|
+
# Mongoid engine
|
47
|
+
# DatabaseCleaner.clean
|
48
|
+
|
49
|
+
::I18n.locale = 'en'
|
60
50
|
end
|
61
|
-
end
|
51
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
class ActiveMimic
|
2
|
+
extend ActiveModel::Callbacks
|
3
|
+
extend ActiveModel::Naming
|
4
|
+
include ActiveModel::Serialization
|
5
|
+
include ActiveAttr::Attributes
|
6
|
+
include ActiveAttr::MassAssignment
|
7
|
+
|
8
|
+
attribute :id
|
9
|
+
attribute :type
|
10
|
+
|
11
|
+
define_model_callbacks :save
|
12
|
+
define_model_callbacks :destroy
|
13
|
+
|
14
|
+
def self.create(attrs)
|
15
|
+
new(attrs).tap(&:save)
|
16
|
+
end
|
17
|
+
|
18
|
+
def indexable_id
|
19
|
+
"#{self.class.to_s}_#{self.id}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def type
|
23
|
+
self.class.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
def save
|
27
|
+
self.id ||= self.class.next_id
|
28
|
+
run_callbacks :save do
|
29
|
+
true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def destroy
|
34
|
+
run_callbacks :destroy do
|
35
|
+
true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.next_id
|
40
|
+
@next_id ||= 0
|
41
|
+
@next_id += 1
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.localized_attribute(name)
|
45
|
+
attribute "#{name}_translations", type: Hash
|
46
|
+
|
47
|
+
define_method name do
|
48
|
+
send("#{name}_translations") && send("#{name}_translations")[I18n.locale.to_s]
|
49
|
+
end
|
50
|
+
|
51
|
+
define_method "#{name}=" do |value|
|
52
|
+
send("#{name}_translations=", {}) if send("#{name}_translations").nil?
|
53
|
+
send("#{name}_translations").merge!(I18n.locale.to_s => value)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module SetupEngine
|
2
|
+
|
3
|
+
def self.setup(name)
|
4
|
+
# 1. set up the engine (connection)
|
5
|
+
case name
|
6
|
+
when :algolia then setup_algolia
|
7
|
+
when :mongoid then setup_mongoid
|
8
|
+
when :elastic_search then setup_elastic_search
|
9
|
+
end
|
10
|
+
|
11
|
+
# 2. load the test models depending on the engine
|
12
|
+
require File.join(File.dirname(__FILE__), '..', 'models', "#{name}.rb")
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def self.setup_algolia
|
18
|
+
require 'yaml'
|
19
|
+
require 'activesearch/algolia'
|
20
|
+
|
21
|
+
YAML.load_file(File.dirname(__FILE__) + '/../../config/algolia.yml').tap do |config|
|
22
|
+
ActiveSearch::Algolia::Client.configure(config["api_key"], config["app_id"])
|
23
|
+
end
|
24
|
+
|
25
|
+
ActiveSearch::Algolia::Client.new.delete_index
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.setup_mongoid
|
29
|
+
require 'mongoid'
|
30
|
+
|
31
|
+
Mongoid.configure do |config|
|
32
|
+
config.sessions = {
|
33
|
+
:default => {
|
34
|
+
:hosts => ["localhost"],
|
35
|
+
:database => "activesearch_test"
|
36
|
+
}
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
require 'activesearch/mongoid'
|
41
|
+
|
42
|
+
ActiveSearch::Mongoid::Index.create_indexes
|
43
|
+
|
44
|
+
DatabaseCleaner.clean
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.elastic_search
|
48
|
+
# TODO
|
49
|
+
|
50
|
+
# Tire::Configuration.client.delete "#{Tire::Configuration.url}/_all"
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
shared_examples 'an engine' do
|
2
|
+
|
3
|
+
before(:all) do
|
4
|
+
@findable = @model.create(title: "Findable Findable", junk: "Junk field", scope_id: 1)
|
5
|
+
@quite_findable = @model.create(title: "Some title", text: "Findable text", scope_id: 1)
|
6
|
+
@another = @another_model.create(title: "Another <strong>findable</strong> title with tags", scope_id: 1)
|
7
|
+
@junk = @model.create(title: "Junk", junk: "Not Findable junk", scope_id: 1)
|
8
|
+
@special = @model.create(title: "Not findable because it's special", special: true, scope_id: 1)
|
9
|
+
@foreign = @model.create(title: "Findable", scope_id: 2)
|
10
|
+
@tagged = @model.create(title: "Tagged document", tags: ['findable'], scope_id: 1)
|
11
|
+
@localized = @model.create(title: "Localized", color: "Red")
|
12
|
+
I18n.with_locale :es do
|
13
|
+
@localized.color = "Rojo"
|
14
|
+
@localized.save
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should find the expected documents" do
|
19
|
+
results = ActiveSearch.search("findable", scope_id: 1).map { |doc| doc.select { |k,v| %w[title junk virtual].include?(k.to_s) } }
|
20
|
+
results.sort_by { |result| result["title"] }.should == [
|
21
|
+
{
|
22
|
+
"title" => "Another findable title with tags",
|
23
|
+
"virtual" => "virtual"
|
24
|
+
},
|
25
|
+
{
|
26
|
+
"title" => "Findable Findable",
|
27
|
+
"junk" => "Junk field"
|
28
|
+
},
|
29
|
+
{
|
30
|
+
"title" => "Some title"
|
31
|
+
},
|
32
|
+
{
|
33
|
+
"title" => "Tagged document"
|
34
|
+
}
|
35
|
+
]
|
36
|
+
ActiveSearch.search("some text").first["title"].should == "Some title"
|
37
|
+
ActiveSearch.search("junk").first["title"].should == "Junk"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should handle localized fields" do
|
41
|
+
ActiveSearch.search("Localized").first["color"].should == "Red"
|
42
|
+
I18n.with_locale :es do
|
43
|
+
ActiveSearch.search("Localized").first["color"].should == "Rojo"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should find docs even with upcase searches" do
|
48
|
+
ActiveSearch.search("FINDABLE").count.should == 5
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should remove destroyed documents from index" do
|
52
|
+
@findable.destroy
|
53
|
+
ActiveSearch.search("findable").count.should == 4
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should excerpt and highlight" do
|
57
|
+
@model.create(title: <<-LIPSUM, junk: "Junk field", scope_id: 1)
|
58
|
+
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy findable text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
|
59
|
+
LIPSUM
|
60
|
+
ActiveSearch.search("dummy findable").first["highlighted"]["title"].should == "Lorem Ipsum is simply <em>dummy</em> text of the printing and typesetting industry. Lo..."
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activesearch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rodrigo Alvarez
|
8
|
+
- Didier Lafforgue
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2014-04-01 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: activesupport
|
@@ -108,6 +109,20 @@ dependencies:
|
|
108
109
|
- - ~>
|
109
110
|
- !ruby/object:Gem::Version
|
110
111
|
version: '3'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: database_cleaner
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ~>
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: 0.9.1
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 0.9.1
|
111
126
|
- !ruby/object:Gem::Dependency
|
112
127
|
name: tire
|
113
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -167,11 +182,13 @@ dependencies:
|
|
167
182
|
description: ORM agnostic full text search
|
168
183
|
email:
|
169
184
|
- papipo@gmail.com
|
185
|
+
- didier.lafforgue@gmail.com
|
170
186
|
executables: []
|
171
187
|
extensions: []
|
172
188
|
extra_rdoc_files: []
|
173
189
|
files:
|
174
190
|
- .gitignore
|
191
|
+
- .rspec
|
175
192
|
- Gemfile
|
176
193
|
- LICENSE.txt
|
177
194
|
- README.md
|
@@ -186,19 +203,21 @@ files:
|
|
186
203
|
- lib/activesearch/base.rb
|
187
204
|
- lib/activesearch/elastic_search.rb
|
188
205
|
- lib/activesearch/mongoid.rb
|
189
|
-
- lib/activesearch/mongoid/
|
206
|
+
- lib/activesearch/mongoid/index.rb
|
190
207
|
- lib/activesearch/proxy.rb
|
191
208
|
- lib/activesearch/result.rb
|
192
209
|
- lib/activesearch/version.rb
|
193
|
-
- spec/algolia_spec.rb
|
194
|
-
- spec/base_spec.rb
|
195
210
|
- spec/config/mongoid.yml
|
196
|
-
- spec/
|
211
|
+
- spec/engines/algolia_spec.rb
|
212
|
+
- spec/engines/base_spec.rb
|
213
|
+
- spec/engines/mongoid_spec.rb
|
197
214
|
- spec/models/algolia.rb
|
198
215
|
- spec/models/elastic_search.rb
|
199
216
|
- spec/models/mongoid.rb
|
200
|
-
- spec/mongoid_spec.rb
|
201
217
|
- spec/spec_helper.rb
|
218
|
+
- spec/support/active_mimic.rb
|
219
|
+
- spec/support/setup_engine.rb
|
220
|
+
- spec/support/shared_examples_for_engines.rb
|
202
221
|
homepage: ''
|
203
222
|
licenses: []
|
204
223
|
metadata: {}
|
@@ -218,18 +237,20 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
218
237
|
version: '0'
|
219
238
|
requirements: []
|
220
239
|
rubyforge_project:
|
221
|
-
rubygems_version: 2.0.
|
240
|
+
rubygems_version: 2.0.7
|
222
241
|
signing_key:
|
223
242
|
specification_version: 4
|
224
243
|
summary: ActiveSearch lets you plug in a ruby module in any class that will allow
|
225
244
|
you to do full text searches.
|
226
245
|
test_files:
|
227
|
-
- spec/algolia_spec.rb
|
228
|
-
- spec/base_spec.rb
|
229
246
|
- spec/config/mongoid.yml
|
230
|
-
- spec/
|
247
|
+
- spec/engines/algolia_spec.rb
|
248
|
+
- spec/engines/base_spec.rb
|
249
|
+
- spec/engines/mongoid_spec.rb
|
231
250
|
- spec/models/algolia.rb
|
232
251
|
- spec/models/elastic_search.rb
|
233
252
|
- spec/models/mongoid.rb
|
234
|
-
- spec/mongoid_spec.rb
|
235
253
|
- spec/spec_helper.rb
|
254
|
+
- spec/support/active_mimic.rb
|
255
|
+
- spec/support/setup_engine.rb
|
256
|
+
- spec/support/shared_examples_for_engines.rb
|
@@ -1,67 +0,0 @@
|
|
1
|
-
module ActiveSearch
|
2
|
-
module Mongoid
|
3
|
-
class Model
|
4
|
-
include ::Mongoid::Document
|
5
|
-
|
6
|
-
field :_original_type, type: String
|
7
|
-
field :_original_id, type: Moped::BSON::ObjectId
|
8
|
-
field :_keywords
|
9
|
-
field :_stored, type: Hash, default: {}
|
10
|
-
alias_method :to_hash, :_stored
|
11
|
-
|
12
|
-
index({_keywords: 1})
|
13
|
-
index({_original_type: 1, _original_id: 1}, unique: true)
|
14
|
-
|
15
|
-
def store_fields(original, fields, options)
|
16
|
-
if options && options[:store]
|
17
|
-
self._stored = {}
|
18
|
-
options[:store].each do |f|
|
19
|
-
|
20
|
-
if original.fields[f.to_s] && original.fields[f.to_s].localized?
|
21
|
-
self._stored[f] = original.send("#{f}_translations")
|
22
|
-
else
|
23
|
-
self._stored[f] = original.send(f) if original.send(f).present?
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def refresh_keywords(original, fields)
|
30
|
-
self._keywords = fields.select { |f| original.fields[f.to_s] }.inject([]) do |memo,f|
|
31
|
-
|
32
|
-
if original.fields[f.to_s].localized?
|
33
|
-
memo += original.send("#{f}_translations").map do |locale,translation|
|
34
|
-
next if translation.nil?
|
35
|
-
translation.downcase.split.map { |word| "#{locale}:#{word}"}
|
36
|
-
end.flatten
|
37
|
-
else
|
38
|
-
if original[f]
|
39
|
-
memo += if original[f].is_a?(Array)
|
40
|
-
original[f].map { |value| value.nil? ? nil : value.downcase }
|
41
|
-
else
|
42
|
-
original[f].downcase.split
|
43
|
-
end
|
44
|
-
|
45
|
-
else
|
46
|
-
memo
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
self._keywords = self._keywords.map! { |k| ActiveSearch.strip_tags(k) }
|
52
|
-
self._keywords.uniq!
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.deindex(original)
|
56
|
-
ActiveSearch::Mongoid::Model.where(_original_type: original.class.to_s, _original_id: original.id).destroy
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.reindex(original, fields, options)
|
60
|
-
doc = find_or_initialize_by(_original_type: original.class.to_s, _original_id: original.id)
|
61
|
-
doc.store_fields(original, fields, options)
|
62
|
-
doc.refresh_keywords(original, fields)
|
63
|
-
doc.save
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
data/spec/algolia_spec.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
#encoding: utf-8
|
2
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
3
|
-
require 'activesearch/algolia'
|
4
|
-
require_relative 'models/algolia'
|
5
|
-
|
6
|
-
YAML.load_file(File.dirname(__FILE__) + '/../config/algolia.yml').tap do |config|
|
7
|
-
ActiveSearch::Algolia::Client.configure(config["api_key"], config["app_id"])
|
8
|
-
end
|
9
|
-
|
10
|
-
describe ActiveSearch::Algolia do
|
11
|
-
before do
|
12
|
-
ActiveSearch::Algolia::Client.new.delete_index
|
13
|
-
end
|
14
|
-
|
15
|
-
context "retry on errors" do
|
16
|
-
before do
|
17
|
-
times_called = 0
|
18
|
-
@instance = AlgoliaModel.new(title: "Example")
|
19
|
-
ActiveSearch::Algolia::Client.should_receive(:put).exactly(3).times.and_return do
|
20
|
-
times_called += 1
|
21
|
-
raise Errno::ECONNRESET if times_called <= 2
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
subject { -> { @instance.save } }
|
26
|
-
|
27
|
-
it { should_not raise_error }
|
28
|
-
end
|
29
|
-
end
|
data/spec/engines_spec.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
#encoding: utf-8
|
2
|
-
|
3
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
4
|
-
|
5
|
-
def cleanup(engine)
|
6
|
-
case engine
|
7
|
-
when "Algolia"
|
8
|
-
YAML.load_file(File.dirname(__FILE__) + '/../config/algolia.yml').tap do |config|
|
9
|
-
ActiveSearch::Algolia::Client.configure(config["api_key"], config["app_id"])
|
10
|
-
end
|
11
|
-
ActiveSearch::Algolia::Client.new.delete_index
|
12
|
-
when "ElasticSearch"
|
13
|
-
Tire::Configuration.client.delete "#{Tire::Configuration.url}/_all"
|
14
|
-
load File.join(File.dirname(__FILE__), 'models', 'elastic_search.rb')
|
15
|
-
when "Mongoid"
|
16
|
-
Mongoid.purge!
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
Dir[File.join(File.dirname(__FILE__), 'models', '*.rb')].map { |f| File.basename(f, '.rb') }.each do |filename|
|
21
|
-
engine = filename.split('_').collect { |w| w.capitalize }.join
|
22
|
-
next unless engine == "Algolia"
|
23
|
-
describe "ActiveSearch::#{engine}" do
|
24
|
-
before(:all) do
|
25
|
-
I18n.locale = :en
|
26
|
-
require File.join(File.dirname(__FILE__), 'models', filename)
|
27
|
-
end
|
28
|
-
|
29
|
-
before do
|
30
|
-
cleanup(engine)
|
31
|
-
@findable = Object.const_get("#{engine}Model").create(title: "Findable Findable", junk: "Junk field", scope_id: 1)
|
32
|
-
@quite_findable = Object.const_get("#{engine}Model").create(title: "Some title", text: "Findable text", scope_id: 1)
|
33
|
-
@another = Object.const_get("Another#{engine}Model").create(title: "Another <strong>findable</strong> title with tags", scope_id: 1)
|
34
|
-
@junk = Object.const_get("#{engine}Model").create(title: "Junk", junk: "Not Findable junk", scope_id: 1)
|
35
|
-
@special = Object.const_get("#{engine}Model").create(title: "Not findable because it's special", special: true, scope_id: 1)
|
36
|
-
@foreign = Object.const_get("#{engine}Model").create(title: "Findable", scope_id: 2)
|
37
|
-
@tagged = Object.const_get("#{engine}Model").create(title: "Tagged document", tags: ['findable'], scope_id: 1)
|
38
|
-
@localized = Object.const_get("#{engine}Model").create(title: "Localized", color: "Red")
|
39
|
-
I18n.with_locale :es do
|
40
|
-
@localized.color = "Rojo"
|
41
|
-
@localized.save
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
it "should find the expected documents" do
|
46
|
-
results = ActiveSearch.search("findable", scope_id: 1).map { |doc| doc.select { |k,v| %w[title junk virtual].include?(k.to_s) } }
|
47
|
-
results.sort_by { |result| result["title"] }.should == [
|
48
|
-
{
|
49
|
-
"title" => "Another findable title with tags",
|
50
|
-
"virtual" => "virtual"
|
51
|
-
},
|
52
|
-
{
|
53
|
-
"title" => "Findable Findable",
|
54
|
-
"junk" => "Junk field"
|
55
|
-
},
|
56
|
-
{
|
57
|
-
"title" => "Some title"
|
58
|
-
},
|
59
|
-
{
|
60
|
-
"title" => "Tagged document"
|
61
|
-
}
|
62
|
-
]
|
63
|
-
ActiveSearch.search("some text").first["title"].should == "Some title"
|
64
|
-
ActiveSearch.search("junk").first["title"].should == "Junk"
|
65
|
-
end
|
66
|
-
|
67
|
-
it "should handle localized fields" do
|
68
|
-
ActiveSearch.search("Localized").first["color"].should == "Red"
|
69
|
-
I18n.with_locale :es do
|
70
|
-
ActiveSearch.search("Localized").first["color"].should == "Rojo"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
it "should find docs even with upcase searches" do
|
75
|
-
ActiveSearch.search("FINDABLE").count.should == 5
|
76
|
-
end
|
77
|
-
|
78
|
-
it "should remove destroyed documents from index" do
|
79
|
-
@findable.destroy
|
80
|
-
ActiveSearch.search("findable").count.should == 4
|
81
|
-
end
|
82
|
-
|
83
|
-
it "should excerpt and highlight" do
|
84
|
-
Object.const_get("#{engine}Model").create(title: <<-LIPSUM, junk: "Junk field", scope_id: 1)
|
85
|
-
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy findable text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
|
86
|
-
LIPSUM
|
87
|
-
ActiveSearch.search("dummy findable").first["highlighted"]["title"].should == "Lorem Ipsum is simply <em>dummy</em> text of the printing and typesetting industry. Lo..."
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
data/spec/mongoid_spec.rb
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
#encoding: utf-8
|
2
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
3
|
-
require 'mongoid'
|
4
|
-
require 'activesearch/mongoid'
|
5
|
-
|
6
|
-
Mongoid.load!("config/mongoid.yml", :test)
|
7
|
-
|
8
|
-
class LocalizedMongoidModel
|
9
|
-
include Mongoid::Document
|
10
|
-
include ActiveSearch::Mongoid
|
11
|
-
|
12
|
-
field :title, localize: true
|
13
|
-
field :not_localized
|
14
|
-
field :array, type: Array
|
15
|
-
search_by [:title, :not_localized, :array, store: [:title]]
|
16
|
-
end
|
17
|
-
|
18
|
-
|
19
|
-
describe ActiveSearch::Mongoid do
|
20
|
-
before do
|
21
|
-
Mongoid.purge!
|
22
|
-
I18n.locale = :en
|
23
|
-
@localized = LocalizedMongoidModel.create!(title: "<strong>English</strong> English")
|
24
|
-
I18n.with_locale(:es) do
|
25
|
-
@localized.title = "Español Español"
|
26
|
-
@localized.save!
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should be able to find by different locales" do
|
31
|
-
ActiveSearch.search("english").first["title"].should == "<strong>English</strong> English"
|
32
|
-
I18n.with_locale(:es) do
|
33
|
-
ActiveSearch.search("español").first["title"].should == "Español Español"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
it "should store localized keywords with tags stripped" do
|
38
|
-
ActiveSearch::Mongoid::Model.where(_original_type: "LocalizedMongoidModel", _original_id: @localized.id).first._keywords.should == ["en:english", "es:español"]
|
39
|
-
end
|
40
|
-
|
41
|
-
it "handles empty translations" do
|
42
|
-
lambda { LocalizedMongoidModel.create!(title: nil, not_localized: "example") }.should_not raise_error
|
43
|
-
end
|
44
|
-
|
45
|
-
it "handles empty fields" do
|
46
|
-
lambda { LocalizedMongoidModel.create!(title: "Example", not_localized: nil) }.should_not raise_error
|
47
|
-
end
|
48
|
-
|
49
|
-
it "handles nil values in arrays" do
|
50
|
-
lambda { LocalizedMongoidModel.create!(title: "Example", not_localized: "example", array: [nil]) }.should_not raise_error
|
51
|
-
end
|
52
|
-
end
|