activesearch 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +21 -4
- data/activesearch.gemspec +1 -0
- data/lib/activesearch/base.rb +19 -13
- data/lib/activesearch/elastic_search.rb +15 -16
- data/lib/activesearch/mongoid.rb +4 -2
- data/lib/activesearch/version.rb +1 -1
- data/spec/base_spec.rb +68 -0
- data/spec/models/elastic_search.rb +2 -2
- data/spec/models/mongoid.rb +7 -3
- data/spec/mongoid_spec.rb +1 -1
- metadata +20 -2
data/README.md
CHANGED
@@ -21,12 +21,24 @@ It works by storing keywords taken from the specified fields and storing them in
|
|
21
21
|
|
22
22
|
##Configuration
|
23
23
|
|
24
|
-
|
24
|
+
call "search_by" from your model:
|
25
25
|
|
26
|
-
search_by :title, :body, store: [:slug]
|
27
|
-
|
28
|
-
|
26
|
+
search_by [:title, :body, store: [:slug]], if: :its_friday
|
27
|
+
|
28
|
+
**IMPORTANT: the first parameter must be either an array, or a symbol.
|
29
|
+
The second parameter must be a conditions hash.**
|
30
|
+
|
31
|
+
the :store option allows you to store that value in the index but it won't be used for search.
|
29
32
|
You can also add :if or :unless conditions in the same way you would do with ActiveModel callbacks.
|
33
|
+
If you need dynamic options, pass a symbol instead:
|
34
|
+
|
35
|
+
search_by :options_for_search
|
36
|
+
|
37
|
+
And define an instance method with that name which must return an array with the options, ie:
|
38
|
+
|
39
|
+
def options_for_search
|
40
|
+
[:field, :another_field]
|
41
|
+
end
|
30
42
|
|
31
43
|
## Querying
|
32
44
|
|
@@ -34,6 +46,11 @@ You can also add :if or :unless conditions in the same way you would do with Act
|
|
34
46
|
|
35
47
|
You can access the stored fields with to_hash, so you don't need to fetch the real document.
|
36
48
|
|
49
|
+
## Why?
|
50
|
+
|
51
|
+
You might wonder why you would like to use ActiveSearch instead of a specific option for your fulltext search index.
|
52
|
+
ActiveSearch provides an uniform API, which is in itself a drop-in replacement in case you want to move from an engine to another.
|
53
|
+
|
37
54
|
## Testing
|
38
55
|
|
39
56
|
Run specs with this command:
|
data/activesearch.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
20
|
gem.add_development_dependency "rspec"
|
21
|
+
gem.add_development_dependency "rspec-mocks"
|
21
22
|
gem.add_development_dependency "bson_ext"
|
22
23
|
gem.add_development_dependency "active_attr"
|
23
24
|
gem.add_development_dependency "mongoid", "~> 2"
|
data/lib/activesearch/base.rb
CHANGED
@@ -1,29 +1,35 @@
|
|
1
1
|
module ActiveSearch
|
2
2
|
module Base
|
3
|
-
def
|
4
|
-
|
5
|
-
self.after_save :reindex, self.search_conditions
|
6
|
-
self.after_destroy :deindex, self.search_conditions
|
3
|
+
def self.included(parent)
|
4
|
+
parent.extend ClassMethods
|
7
5
|
end
|
8
6
|
|
9
7
|
def search_options
|
10
8
|
search_parameters.last.is_a?(Hash) ? search_parameters.last : {}
|
11
9
|
end
|
12
10
|
|
13
|
-
def search_conditions
|
14
|
-
{}.tap do |conditions|
|
15
|
-
conditions.merge!(if: search_options[:if]) if search_options.has_key?(:if)
|
16
|
-
conditions.merge!(unless: search_options[:unless]) if search_options.has_key?(:unless)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
11
|
def search_fields
|
21
12
|
search_parameters.last.is_a?(Hash) ? search_parameters[0...-1] : search_parameters
|
22
13
|
end
|
23
14
|
|
24
|
-
protected
|
25
15
|
def search_parameters
|
26
|
-
|
16
|
+
if self.class.search_parameters.is_a?(Symbol)
|
17
|
+
self.send(self.class.search_parameters)
|
18
|
+
else
|
19
|
+
self.class.search_parameters
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
def search_by(params, conditions = {})
|
25
|
+
after_save :reindex, conditions
|
26
|
+
after_destroy :deindex, conditions
|
27
|
+
@search_parameters = params
|
28
|
+
end
|
29
|
+
|
30
|
+
def search_parameters
|
31
|
+
@search_parameters
|
32
|
+
end
|
27
33
|
end
|
28
34
|
end
|
29
35
|
end
|
@@ -11,8 +11,9 @@ module ActiveSearch
|
|
11
11
|
|
12
12
|
module ElasticSearch
|
13
13
|
def self.included(base)
|
14
|
-
base.
|
15
|
-
|
14
|
+
base.class_eval do
|
15
|
+
include ActiveSearch::Base
|
16
|
+
end
|
16
17
|
end
|
17
18
|
|
18
19
|
def to_indexable
|
@@ -30,7 +31,7 @@ module ActiveSearch
|
|
30
31
|
|
31
32
|
def reindex
|
32
33
|
doc = self.to_indexable
|
33
|
-
properties = self.
|
34
|
+
properties = self.elastic_properties
|
34
35
|
|
35
36
|
elastic_index do
|
36
37
|
unless exists?
|
@@ -47,20 +48,18 @@ module ActiveSearch
|
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
hash[field] = {type: 'string'}
|
56
|
-
end
|
57
|
-
|
58
|
-
(Array(search_options[:store]) - search_fields).each_with_object(props) do |field,hash|
|
59
|
-
hash[field] = {type: 'string', :index => :no}
|
60
|
-
end
|
61
|
-
|
62
|
-
props
|
51
|
+
def elastic_properties
|
52
|
+
props = {}
|
53
|
+
|
54
|
+
search_fields.each_with_object(props) do |field,hash|
|
55
|
+
hash[field] = {type: 'string'}
|
63
56
|
end
|
57
|
+
|
58
|
+
(Array(search_options[:store]) - search_fields).each_with_object(props) do |field,hash|
|
59
|
+
hash[field] = {type: 'string', :index => :no}
|
60
|
+
end
|
61
|
+
|
62
|
+
props
|
64
63
|
end
|
65
64
|
end
|
66
65
|
end
|
data/lib/activesearch/mongoid.rb
CHANGED
@@ -11,12 +11,14 @@ module ActiveSearch
|
|
11
11
|
|
12
12
|
module Mongoid
|
13
13
|
def self.included(base)
|
14
|
-
base.
|
14
|
+
base.class_eval do
|
15
|
+
include Base
|
16
|
+
end
|
15
17
|
end
|
16
18
|
|
17
19
|
protected
|
18
20
|
def reindex
|
19
|
-
ActiveSearch::Mongoid::Model.reindex(self, self.
|
21
|
+
ActiveSearch::Mongoid::Model.reindex(self, self.search_fields, self.search_options)
|
20
22
|
end
|
21
23
|
|
22
24
|
def deindex
|
data/lib/activesearch/version.rb
CHANGED
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'activesearch/base'
|
2
|
+
|
3
|
+
describe ActiveSearch::Base do
|
4
|
+
before do
|
5
|
+
@klass = Class.new do
|
6
|
+
include ActiveSearch::Base
|
7
|
+
|
8
|
+
def self.after_save(*args); end
|
9
|
+
def self.after_destroy(*args); end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "search_by" do
|
15
|
+
let(:call_search_by) do
|
16
|
+
@klass.class_eval do
|
17
|
+
search_by [:field], if: :something_happens, unless: :its_friday
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should rely on after_save and after_destroy callbacks passing conditions" do
|
22
|
+
@klass.should_receive(:after_save).with(:reindex, if: :something_happens, unless: :its_friday)
|
23
|
+
@klass.should_receive(:after_destroy).with(:deindex, if: :something_happens, unless: :its_friday)
|
24
|
+
call_search_by
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should store the parameters in search_parameters" do
|
28
|
+
call_search_by
|
29
|
+
@klass.send(:search_parameters).should == [:field]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "utility methods with options" do
|
34
|
+
before do
|
35
|
+
@klass.stub(:search_parameters).and_return([:field, store: [:another_field]])
|
36
|
+
end
|
37
|
+
|
38
|
+
it "search_options should return the hash at the end of the parameters" do
|
39
|
+
@klass.new.search_options.should == {store: [:another_field]}
|
40
|
+
end
|
41
|
+
|
42
|
+
it "search_fields should return all parameters except the options" do
|
43
|
+
@klass.new.search_fields.should == [:field]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "search_by with dynamic parameters" do
|
48
|
+
before do
|
49
|
+
@klass.class_eval do
|
50
|
+
def options_for_search
|
51
|
+
[@field]
|
52
|
+
end
|
53
|
+
|
54
|
+
def initialize(field)
|
55
|
+
@field = field
|
56
|
+
end
|
57
|
+
|
58
|
+
search_by :options_for_search
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should work" do
|
63
|
+
@klass.new(:first).send(:search_parameters).should == [:first]
|
64
|
+
@klass.new(:second).send(:search_parameters).should == [:second]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -20,7 +20,7 @@ class ElasticSearchModel < ActiveMimic
|
|
20
20
|
attribute :junk
|
21
21
|
attribute :special, default: false
|
22
22
|
|
23
|
-
search_by :title, :text, store: [:title, :junk], if: lambda { !self.special }
|
23
|
+
search_by [:title, :text, store: [:title, :junk]], if: lambda { !self.special }
|
24
24
|
|
25
25
|
end
|
26
26
|
|
@@ -29,5 +29,5 @@ class AnotherElasticSearchModel < ActiveMimic
|
|
29
29
|
include ElasticSearchRefresh
|
30
30
|
|
31
31
|
attribute :title, type: String
|
32
|
-
search_by :title, store: [:title]
|
32
|
+
search_by [:title, store: [:title]]
|
33
33
|
end
|
data/spec/models/mongoid.rb
CHANGED
@@ -11,7 +11,7 @@ class MongoidModel
|
|
11
11
|
field :text, type: String
|
12
12
|
field :junk, type: String
|
13
13
|
field :special, type: Boolean, default: false
|
14
|
-
search_by :title, :text, store: [:title, :junk], unless: :special
|
14
|
+
search_by [:title, :text, store: [:title, :junk]], unless: :special
|
15
15
|
end
|
16
16
|
|
17
17
|
class AnotherMongoidModel
|
@@ -19,7 +19,11 @@ class AnotherMongoidModel
|
|
19
19
|
include ActiveSearch::Mongoid
|
20
20
|
|
21
21
|
field :title, type: String
|
22
|
-
search_by
|
22
|
+
search_by :options_for_search
|
23
|
+
|
24
|
+
def options_for_search
|
25
|
+
[:title, :text, store: [:title]]
|
26
|
+
end
|
23
27
|
end
|
24
28
|
|
25
29
|
|
@@ -29,5 +33,5 @@ class LocalizedMongoidModel
|
|
29
33
|
|
30
34
|
field :title, localize: true
|
31
35
|
field :special_type
|
32
|
-
search_by :title, store: [:title]
|
36
|
+
search_by [:title, store: [:title]]
|
33
37
|
end
|
data/spec/mongoid_spec.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activesearch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -27,6 +27,22 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec-mocks
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
30
46
|
- !ruby/object:Gem::Dependency
|
31
47
|
name: bson_ext
|
32
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,6 +144,7 @@ files:
|
|
128
144
|
- lib/activesearch/mongoid/model.rb
|
129
145
|
- lib/activesearch/result.rb
|
130
146
|
- lib/activesearch/version.rb
|
147
|
+
- spec/base_spec.rb
|
131
148
|
- spec/config/mongoid.yml
|
132
149
|
- spec/engines_spec.rb
|
133
150
|
- spec/models/elastic_search.rb
|
@@ -160,6 +177,7 @@ specification_version: 3
|
|
160
177
|
summary: ActiveSearch lets you plug in a ruby module in any class that will allow
|
161
178
|
you to do full text searches.
|
162
179
|
test_files:
|
180
|
+
- spec/base_spec.rb
|
163
181
|
- spec/config/mongoid.yml
|
164
182
|
- spec/engines_spec.rb
|
165
183
|
- spec/models/elastic_search.rb
|