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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b24050eefed5b21eb1b0d085fa964effdc06c2d8
|
4
|
+
data.tar.gz: 780df5ddeb72407c972869ab11a9a6e015018554
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1e5576e03f3f0ae6a610ddef63bf3c661e68520ef8fdae55ca4e98c9676f14fb038de8088b416c59b085515ea4568aa5b58500085003bae87ee80c375e66cc7
|
7
|
+
data.tar.gz: f1caac8c129064500ec93a3f13f7854ab83f698ed7e27f8729ae9fc21cf2a2a999a23fd75663304590bb1490ef0e979e2f3a2fff4ff7abd71b4aa884eb7e23c1
|
data/.rspec
ADDED
data/Rakefile
CHANGED
@@ -1 +1,19 @@
|
|
1
|
-
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler/setup'
|
6
|
+
|
7
|
+
require 'rake'
|
8
|
+
require 'rspec'
|
9
|
+
require 'rspec/core/rake_task'
|
10
|
+
require 'rubygems/package_task'
|
11
|
+
|
12
|
+
# === Gems install tasks ===
|
13
|
+
Bundler::GemHelper.install_tasks
|
14
|
+
|
15
|
+
RSpec::Core::RakeTask.new('spec') do |spec|
|
16
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
17
|
+
end
|
18
|
+
|
19
|
+
task :default => :spec
|
data/activesearch.gemspec
CHANGED
@@ -6,8 +6,8 @@ require 'activesearch/version'
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
7
|
gem.name = "activesearch"
|
8
8
|
gem.version = ActiveSearch::VERSION
|
9
|
-
gem.authors = [
|
10
|
-
gem.email = [
|
9
|
+
gem.authors = ['Rodrigo Alvarez', 'Didier Lafforgue']
|
10
|
+
gem.email = ['papipo@gmail.com', 'didier.lafforgue@gmail.com']
|
11
11
|
gem.description = %q{ORM agnostic full text search}
|
12
12
|
gem.summary = %q{ActiveSearch lets you plug in a ruby module in any class that will allow you to do full text searches.}
|
13
13
|
gem.homepage = ""
|
@@ -16,15 +16,16 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
|
-
|
19
|
+
|
20
20
|
gem.add_dependency "activesupport"
|
21
21
|
gem.add_dependency "sucker_punch"
|
22
22
|
gem.add_dependency "actionpack"
|
23
|
-
|
23
|
+
|
24
24
|
gem.add_development_dependency "rspec"
|
25
25
|
gem.add_development_dependency "rspec-mocks"
|
26
26
|
gem.add_development_dependency "active_attr"
|
27
27
|
gem.add_development_dependency "mongoid", "~> 3"
|
28
|
+
gem.add_development_dependency "database_cleaner", "~> 0.9.1"
|
28
29
|
gem.add_development_dependency "tire"
|
29
30
|
gem.add_development_dependency "parallel_tests"
|
30
31
|
gem.add_development_dependency "httparty"
|
@@ -2,7 +2,7 @@ require "sucker_punch"
|
|
2
2
|
|
3
3
|
class ActiveSearch::Algolia::Worker
|
4
4
|
include SuckerPunch::Job
|
5
|
-
|
5
|
+
|
6
6
|
def perform(msg)
|
7
7
|
begin
|
8
8
|
case msg[:task]
|
@@ -10,7 +10,7 @@ class ActiveSearch::Algolia::Worker
|
|
10
10
|
::ActiveSearch::Algolia::Client.new.save(msg[:id], msg[:doc])
|
11
11
|
when :deindex
|
12
12
|
client = ::ActiveSearch::Algolia::Client.new
|
13
|
-
client.query("", tags: "original_id:#{msg[:id]}")["hits"].each do |hit|
|
13
|
+
client.query("", tags: "original_type:#{msg[:type]},original_id:#{msg[:id]}")["hits"].each do |hit|
|
14
14
|
client.delete(hit["objectID"])
|
15
15
|
end
|
16
16
|
end
|
data/lib/activesearch/algolia.rb
CHANGED
@@ -4,13 +4,21 @@ require "activesearch/base"
|
|
4
4
|
require "activesearch/proxy"
|
5
5
|
|
6
6
|
module ActiveSearch
|
7
|
+
|
7
8
|
def self.search(text, conditions = {}, options = {})
|
9
|
+
locale = options[:locale] || I18n.locale
|
10
|
+
conditions[:locale] ||= locale
|
11
|
+
|
8
12
|
Proxy.new(text, conditions, options) do |text, conditions|
|
9
13
|
Algolia::Client.new.query(text, tags: conditions_to_tags(conditions))["hits"].map! do |hit|
|
10
14
|
if hit["_tags"]
|
11
15
|
hit["_tags"].each do |tag|
|
12
|
-
|
13
|
-
|
16
|
+
# preserve other ":" characters
|
17
|
+
_segments = tag.split(':')
|
18
|
+
|
19
|
+
unless _segments.empty? || _segments[1..-1].empty?
|
20
|
+
hit[_segments.first] = _segments[1..-1].join(':')
|
21
|
+
end
|
14
22
|
end
|
15
23
|
hit.delete("_tags")
|
16
24
|
end
|
@@ -20,8 +28,9 @@ module ActiveSearch
|
|
20
28
|
end
|
21
29
|
|
22
30
|
protected
|
31
|
+
|
23
32
|
def self.conditions_to_tags(conditions)
|
24
|
-
conditions.
|
33
|
+
conditions.map { |c| c.join(':') }.join(',')
|
25
34
|
end
|
26
35
|
|
27
36
|
module Algolia
|
@@ -33,32 +42,35 @@ module ActiveSearch
|
|
33
42
|
|
34
43
|
protected
|
35
44
|
def reindex
|
36
|
-
Worker.new.async.perform(task: :reindex, id: "#{indexable_id}_#{
|
45
|
+
Worker.new.async.perform(task: :reindex, id: "#{indexable_id}_#{search_locale}", doc: to_indexable)
|
37
46
|
end
|
38
47
|
|
39
48
|
def deindex
|
40
|
-
Worker.new.async.perform(task: :deindex, id:
|
49
|
+
Worker.new.async.perform(task: :deindex, id: self.id, type: self.class.to_s)
|
41
50
|
end
|
42
51
|
|
43
52
|
def to_indexable
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
53
|
+
{}.tap do |doc|
|
54
|
+
_locale = search_locale
|
55
|
+
|
56
|
+
search_fields.each do |field|
|
57
|
+
if content = send(field)
|
58
|
+
doc[field.to_s] = if content.is_a?(Hash) && content.has_key?(_locale)
|
59
|
+
ActiveSearch.strip_tags(content[_locale])
|
60
|
+
else
|
61
|
+
ActiveSearch.strip_tags(content)
|
62
|
+
end
|
51
63
|
end
|
52
64
|
end
|
53
|
-
end
|
54
65
|
|
55
|
-
|
56
|
-
|
57
|
-
|
66
|
+
(Array(search_options[:store]) - search_fields).each do |field|
|
67
|
+
doc["_tags"] ||= []
|
68
|
+
doc["_tags"] << "#{field}:#{self.send(field)}"
|
69
|
+
end
|
70
|
+
doc["_tags"] << "locale:#{_locale}"
|
71
|
+
doc["_tags"] << "original_type:#{self.class.to_s}"
|
72
|
+
doc["_tags"] << "original_id:#{self.id}"
|
58
73
|
end
|
59
|
-
doc["_tags"] << "locale:#{I18n.locale}"
|
60
|
-
doc["_tags"] << "original_id:#{indexable_id}"
|
61
|
-
doc
|
62
74
|
end
|
63
75
|
end
|
64
76
|
end
|
data/lib/activesearch/base.rb
CHANGED
@@ -7,25 +7,37 @@ module ActiveSearch
|
|
7
7
|
value.gsub(/<\/?[^>]*>/, '')
|
8
8
|
when Hash
|
9
9
|
value.each_with_object({}) { |(k,v),h| h[k] = strip_tags(v) }
|
10
|
+
when Array
|
11
|
+
value.map { |v| strip_tags(v) }
|
10
12
|
else
|
11
13
|
value
|
12
14
|
end
|
13
15
|
end
|
14
|
-
|
16
|
+
|
15
17
|
module Base
|
16
18
|
def self.included(parent)
|
17
19
|
parent.extend ClassMethods
|
18
20
|
parent.class_attribute :search_parameters, instance_reader: false
|
19
21
|
end
|
20
|
-
|
22
|
+
|
21
23
|
def search_options
|
22
24
|
search_parameters.last.is_a?(Hash) ? search_parameters.last : {}
|
23
25
|
end
|
24
|
-
|
26
|
+
|
25
27
|
def search_fields
|
26
28
|
search_parameters.last.is_a?(Hash) ? search_parameters[0...-1] : search_parameters
|
27
29
|
end
|
28
|
-
|
30
|
+
|
31
|
+
def search_locale
|
32
|
+
search_locale = search_options[:locale] || I18n.locale.to_s
|
33
|
+
|
34
|
+
if search_locale.respond_to?(:call)
|
35
|
+
search_locale.call
|
36
|
+
else
|
37
|
+
search_locale
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
29
41
|
def search_parameters
|
30
42
|
if self.class.search_parameters.is_a?(Symbol)
|
31
43
|
self.send(self.class.search_parameters)
|
@@ -33,14 +45,14 @@ module ActiveSearch
|
|
33
45
|
self.class.search_parameters
|
34
46
|
end
|
35
47
|
end
|
36
|
-
|
48
|
+
|
37
49
|
module ClassMethods
|
38
50
|
def search_by(params, conditions = {})
|
39
51
|
after_save :reindex, conditions
|
40
52
|
after_destroy :deindex, conditions
|
41
53
|
self.search_parameters = params
|
42
54
|
end
|
43
|
-
|
55
|
+
|
44
56
|
end
|
45
57
|
end
|
46
58
|
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module ActiveSearch
|
2
|
+
module Mongoid
|
3
|
+
class Index
|
4
|
+
|
5
|
+
include ::Mongoid::Document
|
6
|
+
|
7
|
+
## fields ##
|
8
|
+
field :original_type, type: String
|
9
|
+
field :original_id, type: Moped::BSON::ObjectId
|
10
|
+
field :language, type: String
|
11
|
+
field :locale, type: String
|
12
|
+
field :content, type: Array
|
13
|
+
field :stored, type: Hash, default: {}
|
14
|
+
alias_method :to_hash, :stored
|
15
|
+
|
16
|
+
## indexes ##
|
17
|
+
index({ content: 'text', locale: 1 })
|
18
|
+
index({ original_type: 1, original_id: 1, locale: 1 }, unique: true)
|
19
|
+
|
20
|
+
## methods ##
|
21
|
+
|
22
|
+
def store_language(original)
|
23
|
+
self.locale = original.search_locale
|
24
|
+
self.language = self.class.locale_to_language(self.locale)
|
25
|
+
end
|
26
|
+
|
27
|
+
def store_fields(original)
|
28
|
+
self.stored = {}
|
29
|
+
|
30
|
+
fields = (original.search_fields + (original.search_options[:store] || [])).uniq
|
31
|
+
|
32
|
+
fields.each do |f|
|
33
|
+
if original.send(f).present?
|
34
|
+
self.stored[f] = ActiveSearch.strip_tags(original.send(f))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def refresh_content(original)
|
40
|
+
self.content = original.to_indexable.values.flatten
|
41
|
+
end
|
42
|
+
|
43
|
+
## class methods ##
|
44
|
+
|
45
|
+
def self.search(query, conditions = {})
|
46
|
+
language = self.locale_to_language(conditions[:locale] || I18n.locale)
|
47
|
+
|
48
|
+
filter = {}
|
49
|
+
conditions.each do |key, value|
|
50
|
+
if key == :locale
|
51
|
+
filter['locale'] = value.to_s
|
52
|
+
else
|
53
|
+
filter["stored.#{key}"] = value
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
session = ::Mongoid.session('default')
|
58
|
+
results = session.command({
|
59
|
+
'text' => collection.name,
|
60
|
+
'search' => query,
|
61
|
+
'language' => language,
|
62
|
+
'filter' => filter
|
63
|
+
})
|
64
|
+
if results.has_key?('results')
|
65
|
+
results['results'].map do |result|
|
66
|
+
result['obj']['stored'].merge(result['obj'].slice('locale', 'original_type', 'original_id'))
|
67
|
+
end
|
68
|
+
else
|
69
|
+
[]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.deindex(original)
|
74
|
+
# delete the records in all the locales
|
75
|
+
self.where(original_type: original.class.to_s, original_id: original.id).destroy
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.reindex(original, fields, options)
|
79
|
+
# re-index only in the current locale (unless another locale has been specified)
|
80
|
+
locale = original.search_locale
|
81
|
+
|
82
|
+
# find the exact index scoped by the locale or build a new one
|
83
|
+
doc = find_or_initialize_by(original_type: original.class.to_s, original_id: original.id, locale: locale)
|
84
|
+
|
85
|
+
doc.store_language(original)
|
86
|
+
doc.store_fields(original) #, fields, options)
|
87
|
+
doc.refresh_content(original)
|
88
|
+
|
89
|
+
# save it (create or update it)
|
90
|
+
doc.save
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.locale_to_language(locale)
|
94
|
+
{
|
95
|
+
dk: 'danish',
|
96
|
+
nl: 'dutch',
|
97
|
+
en: 'english',
|
98
|
+
fi: 'finnish',
|
99
|
+
fr: 'french',
|
100
|
+
de: 'german',
|
101
|
+
hu: 'hungarian',
|
102
|
+
it: 'italian',
|
103
|
+
nb: 'norwegian',
|
104
|
+
br: 'portuguese',
|
105
|
+
pt: 'portuguese',
|
106
|
+
ro: 'romanian',
|
107
|
+
ru: 'russian',
|
108
|
+
es: 'spanish',
|
109
|
+
se: 'swedish',
|
110
|
+
tr: 'turkish'
|
111
|
+
}[locale.to_sym] || 'english'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
data/lib/activesearch/mongoid.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
require 'activesearch/base'
|
2
2
|
require 'activesearch/proxy'
|
3
|
-
require 'activesearch/mongoid/
|
3
|
+
require 'activesearch/mongoid/index'
|
4
4
|
|
5
5
|
module ActiveSearch
|
6
6
|
|
7
7
|
def self.search(text, conditions = {}, options = {})
|
8
|
+
locale = options[:locale] || I18n.locale
|
9
|
+
conditions[:locale] ||= locale
|
10
|
+
|
8
11
|
Proxy.new(text, conditions, options) do |text, conditions|
|
9
|
-
text
|
10
|
-
conditions.keys.each { |k| conditions["_stored.#{k}"] = conditions.delete(k) }
|
11
|
-
conditions.merge!(:_keywords.in => text + text.map { |word| "#{I18n.locale}:#{word}"})
|
12
|
-
Mongoid::Model.where(conditions)
|
12
|
+
ActiveSearch::Mongoid::Index.search(text, conditions)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -20,13 +20,30 @@ module ActiveSearch
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
def to_indexable
|
24
|
+
{}.tap do |doc|
|
25
|
+
_locale = search_locale
|
26
|
+
|
27
|
+
search_fields.each do |field|
|
28
|
+
if content = send(field)
|
29
|
+
doc[field.to_s] = if content.is_a?(Hash) && content.has_key?(_locale)
|
30
|
+
ActiveSearch.strip_tags(content[_locale])
|
31
|
+
else
|
32
|
+
ActiveSearch.strip_tags(content)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
23
39
|
protected
|
40
|
+
|
24
41
|
def reindex
|
25
|
-
ActiveSearch::Mongoid::
|
42
|
+
ActiveSearch::Mongoid::Index.reindex(self, self.search_fields, self.search_options)
|
26
43
|
end
|
27
44
|
|
28
45
|
def deindex
|
29
|
-
ActiveSearch::Mongoid::
|
46
|
+
ActiveSearch::Mongoid::Index.deindex(self)
|
30
47
|
end
|
31
48
|
end
|
32
49
|
end
|
data/lib/activesearch/result.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'action_view'
|
2
2
|
require 'active_support/core_ext'
|
3
|
+
require 'active_support/core_ext/hash/slice'
|
3
4
|
|
4
5
|
module ActiveSearch
|
5
6
|
class Result < Hash
|
@@ -9,16 +10,22 @@ module ActiveSearch
|
|
9
10
|
include ActionView::Helpers::TextHelper
|
10
11
|
|
11
12
|
def initialize(result, text, options = {})
|
13
|
+
locale = (options[:locale] || I18n.locale).to_s
|
14
|
+
|
12
15
|
@text = text
|
13
16
|
result.to_hash.each do |k,v|
|
14
|
-
unless v.nil?
|
15
|
-
self[k.to_s] = v.respond_to?(:has_key?) && v.has_key?(
|
17
|
+
unless v.nil?
|
18
|
+
self[k.to_s] = v.respond_to?(:has_key?) && v.has_key?(locale) ? v[locale] : v
|
16
19
|
end
|
17
20
|
end
|
18
21
|
|
19
22
|
self.build_highlighted_fields(options[:radius])
|
20
23
|
end
|
21
24
|
|
25
|
+
def slice(*keys)
|
26
|
+
::Hash.new.update(self).slice(*keys)
|
27
|
+
end
|
28
|
+
|
22
29
|
protected
|
23
30
|
|
24
31
|
def build_highlighted_fields(radius = nil)
|
data/lib/activesearch/version.rb
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'ActiveSearch::Algolia' do
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
SetupEngine.setup(:algolia)
|
8
|
+
|
9
|
+
# can not use the rspec let method
|
10
|
+
@model = AlgoliaModel
|
11
|
+
@another_model = AnotherAlgoliaModel
|
12
|
+
end
|
13
|
+
|
14
|
+
include_examples 'an engine'
|
15
|
+
|
16
|
+
context 'retry on errors' do
|
17
|
+
|
18
|
+
before do
|
19
|
+
times_called = 0
|
20
|
+
@instance = AlgoliaModel.new(title: 'Example')
|
21
|
+
ActiveSearch::Algolia::Client.should_receive(:put).exactly(3).times.and_return do
|
22
|
+
times_called += 1
|
23
|
+
raise Errno::ECONNRESET if times_called <= 2
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
subject { -> { @instance.save } }
|
28
|
+
|
29
|
+
it { should_not raise_error }
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -1,64 +1,64 @@
|
|
1
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ActiveSearch::Base do
|
4
4
|
before do
|
5
5
|
@klass = Class.new do
|
6
6
|
include ActiveSearch::Base
|
7
|
-
|
7
|
+
|
8
8
|
def self.after_save(*args); end
|
9
9
|
def self.after_destroy(*args); end
|
10
|
-
|
10
|
+
|
11
11
|
end
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
context "search_by" do
|
15
15
|
let(:call_search_by) do
|
16
16
|
@klass.class_eval do
|
17
17
|
search_by [:field], if: :something_happens, unless: :its_friday
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
it "should rely on after_save and after_destroy callbacks passing conditions" do
|
22
22
|
@klass.should_receive(:after_save).with(:reindex, if: :something_happens, unless: :its_friday)
|
23
23
|
@klass.should_receive(:after_destroy).with(:deindex, if: :something_happens, unless: :its_friday)
|
24
24
|
call_search_by
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
it "should store the parameters in search_parameters" do
|
28
28
|
call_search_by
|
29
29
|
@klass.send(:search_parameters).should == [:field]
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
context "utility methods with options" do
|
34
34
|
before do
|
35
35
|
@klass.stub(:search_parameters).and_return([:field, store: [:another_field]])
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
it "search_options should return the hash at the end of the parameters" do
|
39
39
|
@klass.new.search_options.should == {store: [:another_field]}
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
it "search_fields should return all parameters except the options" do
|
43
43
|
@klass.new.search_fields.should == [:field]
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
context "search_by with virtual parameters" do
|
48
48
|
before do
|
49
49
|
@klass.class_eval do
|
50
50
|
def options_for_search
|
51
51
|
[@field]
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
def initialize(field)
|
55
55
|
@field = field
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
search_by :options_for_search
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
it "should work" do
|
63
63
|
@klass.new(:first).send(:search_parameters).should == [:first]
|
64
64
|
@klass.new(:second).send(:search_parameters).should == [:second]
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'ActiveSearch::Mongoid' do
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
SetupEngine.setup(:mongoid)
|
8
|
+
|
9
|
+
# can not use the rspec let method
|
10
|
+
@model = MongoidModel
|
11
|
+
@another_model = AnotherMongoidModel
|
12
|
+
end
|
13
|
+
|
14
|
+
include_examples 'an engine'
|
15
|
+
|
16
|
+
describe 'localized content' do
|
17
|
+
|
18
|
+
before(:all) do
|
19
|
+
@localized = LocalizedMongoidModel.create!(title: "<strong>English</strong> English")
|
20
|
+
I18n.with_locale(:es) do
|
21
|
+
@localized.title = "Español Español"
|
22
|
+
@localized.save!
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should be able to find by different locales" do
|
27
|
+
ActiveSearch.search("english").first["title"].should == "English English"
|
28
|
+
I18n.with_locale(:es) do
|
29
|
+
ActiveSearch.search("español").first["title"].should == "Español Español"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "finds by a different locale" do
|
34
|
+
ActiveSearch.search("español", {}, { locale: 'es'}).first["title"].should == "Español Español"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should store content with tags stripped" do
|
38
|
+
index = ActiveSearch::Mongoid::Index.where(original_type: "LocalizedMongoidModel", original_id: @localized.id, locale: 'en')
|
39
|
+
index.first.content.should == ["English English"]
|
40
|
+
end
|
41
|
+
|
42
|
+
it "handles empty translations" do
|
43
|
+
lambda { LocalizedMongoidModel.create!(title: nil, not_localized: "example") }.should_not raise_error
|
44
|
+
end
|
45
|
+
|
46
|
+
it "handles empty fields" do
|
47
|
+
lambda { LocalizedMongoidModel.create!(title: "Example", not_localized: nil) }.should_not raise_error
|
48
|
+
end
|
49
|
+
|
50
|
+
it "handles nil values in arrays" do
|
51
|
+
lambda { LocalizedMongoidModel.create!(title: "Example", not_localized: "example", array: [nil]) }.should_not raise_error
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/spec/models/algolia.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
require 'activesearch/algolia'
|
2
|
-
|
3
1
|
class AlgoliaModel < ActiveMimic
|
4
2
|
include ActiveSearch::Algolia
|
5
|
-
|
3
|
+
|
6
4
|
attribute :title
|
7
5
|
attribute :text
|
8
6
|
attribute :junk
|
@@ -10,19 +8,19 @@ class AlgoliaModel < ActiveMimic
|
|
10
8
|
attribute :scope_id, type: Integer
|
11
9
|
attribute :tags, type: Array
|
12
10
|
localized_attribute :color
|
13
|
-
|
11
|
+
|
14
12
|
search_by [:title, :text, :tags, :color, store: [:title, :junk, :scope_id]], if: lambda { !self.special }
|
15
13
|
|
16
14
|
end
|
17
15
|
|
18
16
|
class AnotherAlgoliaModel < ActiveMimic
|
19
17
|
include ActiveSearch::Algolia
|
20
|
-
|
18
|
+
|
21
19
|
attribute :title, type: String
|
22
20
|
attribute :scope_id, type: Integer
|
23
21
|
localized_attribute :color
|
24
22
|
search_by [:title, store: [:title, :virtual, :scope_id, :color]]
|
25
|
-
|
23
|
+
|
26
24
|
def virtual
|
27
25
|
"virtual"
|
28
26
|
end
|
@@ -1,11 +1,9 @@
|
|
1
|
-
require 'activesearch/elastic_search'
|
2
|
-
|
3
1
|
module ElasticSearchRefresh
|
4
|
-
|
2
|
+
|
5
3
|
def save
|
6
4
|
super.tap { Tire.index('_all') { refresh }}
|
7
5
|
end
|
8
|
-
|
6
|
+
|
9
7
|
def destroy
|
10
8
|
super.tap { Tire.index('_all') { refresh }}
|
11
9
|
end
|
@@ -14,13 +12,12 @@ end
|
|
14
12
|
class ElasticSearchModel < ActiveMimic
|
15
13
|
include ActiveSearch::ElasticSearch
|
16
14
|
include ElasticSearchRefresh
|
17
|
-
|
15
|
+
|
18
16
|
attribute :title
|
19
|
-
attribute :text
|
20
17
|
attribute :junk
|
21
18
|
attribute :special, default: false
|
22
19
|
attribute :tags, type: Array
|
23
|
-
|
20
|
+
|
24
21
|
search_by [:title, :text, :tags, store: [:title, :junk]], if: lambda { !self.special }
|
25
22
|
|
26
23
|
end
|
@@ -28,10 +25,10 @@ end
|
|
28
25
|
class AnotherElasticSearchModel < ActiveMimic
|
29
26
|
include ActiveSearch::ElasticSearch
|
30
27
|
include ElasticSearchRefresh
|
31
|
-
|
28
|
+
|
32
29
|
attribute :title, type: String
|
33
30
|
search_by [:title, store: [:title, :virtual]]
|
34
|
-
|
31
|
+
|
35
32
|
def virtual
|
36
33
|
"virtual"
|
37
34
|
end
|