soulmate_rails 0.2.0.alpha → 0.2.1.beta
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/README.markdown +54 -19
- data/lib/soulmate_rails/model_additions.rb +31 -5
- data/lib/soulmate_rails/version.rb +2 -2
- data/spec/samples/models/user_aliases.rb +9 -0
- data/spec/samples/models/user_data.rb +5 -0
- data/spec/samples/models/user_multiple.rb +6 -0
- data/spec/samples/models/user_single.rb +5 -0
- data/spec/soulmate_rails/model_additions_spec.rb +63 -17
- metadata +7 -5
- data/.document +0 -5
- data/LICENSE.txt +0 -20
data/README.markdown
CHANGED
@@ -1,17 +1,22 @@
|
|
1
|
-
# Soulmate Rails
|
1
|
+
# Soulmate Rails [](http://badge.fury.io/rb/soulmate_rails) [](https://travis-ci.org/dhruvasagar/soulmate_rails) [](https://gemnasium.com/dhruvasagar/soulmate_rails)
|
2
|
+
<!--[](https://drone.io/github.com/dhruvasagar/soulmate_rails/latest)-->
|
2
3
|
|
3
|
-
Soulmate Rails is a rails plugin that helps to solve the common problem
|
4
|
-
auto-completion in rails intuitively. It extends the
|
5
|
-
href="http://github.com/seatgeek/soulmate">Soulmate</a> to
|
6
|
-
pluggable into a rails project.
|
4
|
+
Soulmate Rails is a rails plugin that helps to solve the common problem
|
5
|
+
building auto-completion back-end in rails intuitively. It extends the
|
6
|
+
soulmate gem <a href="http://github.com/seatgeek/soulmate">Soulmate</a> to
|
7
|
+
make it easily pluggable into a rails project.
|
7
8
|
|
8
9
|
## Getting Started
|
9
|
-
|
10
10
|
### Installation :
|
11
11
|
|
12
12
|
```sh
|
13
13
|
$ gem install soulmate_rails
|
14
14
|
```
|
15
|
+
OR add this to your `Gemfile` :
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'soulmate_rails'
|
19
|
+
```
|
15
20
|
|
16
21
|
### Usage :
|
17
22
|
|
@@ -24,7 +29,7 @@ class User < ActiveRecord::Base
|
|
24
29
|
autocomplete :last_name, :score => :id
|
25
30
|
|
26
31
|
def calculate_score
|
27
|
-
|
32
|
+
100 / self.id # simple score calculator
|
28
33
|
end
|
29
34
|
end
|
30
35
|
|
@@ -33,15 +38,23 @@ end
|
|
33
38
|
1.9.3p385 :003 > User.create(:first_name => 'First3', :last_name => 'Last3')
|
34
39
|
1.9.3p385 :004 > User.search_by_first_name('firs')
|
35
40
|
=> [#<User:0x000000014bb1e8 @new_record=false,
|
36
|
-
@attributes={"first_name"=>"
|
41
|
+
@attributes={"first_name"=>"First1", "last_name"=>"Last1" "id"=>1},
|
37
42
|
@changed_attributes={}>, #<User:0x000000014bb1e9 @new_record=false,
|
38
43
|
@attributes={"first_name"=>"First2", "last_name"=>"Last2" "id"=>2},
|
39
44
|
@changed_attributes={}>, #<User:0x000000014bb1ea @new_record=false,
|
40
|
-
@attributes={"first_name"=>"
|
45
|
+
@attributes={"first_name"=>"First3", "last_name"=>"Last3" "id"=>3},
|
41
46
|
@changed_attributes={}>]
|
42
47
|
1.9.3p385 :005 > User.search_by_last_name('last1')
|
48
|
+
=> [#<User:0x000000014bb1e8 @new_record=false,
|
49
|
+
@attributes={"first_name"=>"First1", "last_name"=>"Last1" "id"=>1},
|
50
|
+
@changed_attributes={}>]
|
51
|
+
1.9.3p385 :006 > User.search_by_last_name('las')
|
43
52
|
=> [#<User:0x000000014bb1e8 @new_record=false,
|
44
53
|
@attributes={"first_name"=>"First3", "last_name"=>"Last3" "id"=>3},
|
54
|
+
@changed_attributes={}>, #<User:0x000000014bb1e9 @new_record=false,
|
55
|
+
@attributes={"first_name"=>"First2", "last_name"=>"Last2" "id"=>2},
|
56
|
+
@changed_attributes={}>, #<User:0x000000014bb1ea @new_record=false,
|
57
|
+
@attributes={"first_name"=>"First1", "last_name"=>"Last1" "id"=>1},
|
45
58
|
@changed_attributes={}>]
|
46
59
|
```
|
47
60
|
|
@@ -50,8 +63,7 @@ The `autocomplete` method takes 2 arguments :
|
|
50
63
|
* attribute name to use for autocompletion.
|
51
64
|
* options that determine how autocompletion works for indexing.
|
52
65
|
|
53
|
-
Methods added by autocomplete :
|
54
|
-
|
66
|
+
### Methods added by autocomplete :
|
55
67
|
* Class Methods
|
56
68
|
* `search_by(attribute, term, options={})` - Generic method to search by
|
57
69
|
an attribute for which an autocomplete was defined.
|
@@ -67,14 +79,36 @@ Methods added by autocomplete :
|
|
67
79
|
`delete` to ensure the callbacks are invoked appropriately by rails and
|
68
80
|
soulmate updates the index.
|
69
81
|
|
70
|
-
Options you can provide to `autocomplete` :
|
82
|
+
### Options you can provide to `autocomplete` :
|
83
|
+
* `:score` : This is required. Soulmate uses it for sorting the results (in
|
84
|
+
reverse order, i.e. higher score first). This can be the name of a function
|
85
|
+
or can also be the name of another attribute with integer values.
|
86
|
+
* `:aliases` : This is optional. Soulmate uses this as aliases for the term
|
87
|
+
field and uses it for searching as well. This can be an array of values or
|
88
|
+
the name of a method which returns an array of values.
|
89
|
+
* `:data` : This is optional. This can either be the name of a method which
|
90
|
+
returns data or a hash or a string. Once you perform your search using
|
91
|
+
`search_by` or `search_by_#{attribute}` it will set the value of :data
|
92
|
+
corresponding to the object to soulmate_data attr_accessor and can be
|
93
|
+
accessed by calling the soulmate_data accessor on the model object.
|
94
|
+
|
95
|
+
### Configuration :
|
96
|
+
Within your rails application inside config/application.rb you can optionally
|
97
|
+
provide redis configuration. Example :
|
71
98
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
99
|
+
```ruby
|
100
|
+
config.soulmate_rails.redis = 'redis://127.0.0.1:6380/0'
|
101
|
+
# or you can assign an existing instance of Redis, Redis::Namespace, etc.
|
102
|
+
# config.soulmate_rails.redis = $redis
|
103
|
+
```
|
104
|
+
|
105
|
+
Alternatively, you can also add configuration in an initializer. Example :
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
Soulmate.redis = 'redis://127.0.0.1:6380/0'
|
109
|
+
# or you can assign an existing instance of Redis, Redis::Namespace, etc.
|
110
|
+
# Soulmate.redis = $redis
|
111
|
+
```
|
78
112
|
|
79
113
|
## Contributing
|
80
114
|
### Reporting an Issue :
|
@@ -88,6 +122,7 @@ Options you can provide to `autocomplete` :
|
|
88
122
|
* Open a Pull Request.
|
89
123
|
|
90
124
|
## License
|
91
|
-
Soulmate Rails is released under the
|
125
|
+
Soulmate Rails is released under the <a
|
126
|
+
href="http://www.opensource.org/licenses/MIT">MIT License</a>
|
92
127
|
|
93
128
|
<!-- vim: set tw=80 colorcolumn=80 -->
|
@@ -2,15 +2,39 @@ module SoulmateRails
|
|
2
2
|
module ModelAdditions
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
|
+
included do
|
6
|
+
class_eval do
|
7
|
+
attr_accessor :soulmate_data
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
5
11
|
def update_index_for(attribute, options={})
|
6
12
|
loader = instance_variable_get("@#{loader_for(attribute)}") || instance_variable_set("@#{loader_for(attribute)}", Soulmate::Loader.new(loader_for(attribute)))
|
7
13
|
item = {
|
8
14
|
'id' => "#{attribute}_#{self.id}",
|
9
15
|
'term' => send(attribute),
|
10
16
|
'score' => ( respond_to?(options[:score]) ? send(options[:score]) : options[:score] )
|
11
|
-
}
|
12
|
-
|
13
|
-
|
17
|
+
}
|
18
|
+
|
19
|
+
if options[:aliases]
|
20
|
+
if options[:aliases].is_a?(Array)
|
21
|
+
item.merge!({'aliases' => options[:aliases]})
|
22
|
+
elsif respond_to?(options[:aliases])
|
23
|
+
aliases = send(options[:aliases])
|
24
|
+
item.merge!({'aliases' => aliases}) if aliases && aliases.is_a?(Array)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
if options[:data]
|
29
|
+
if options[:data].is_a?(Hash)
|
30
|
+
item.merge!({'data' => options[:data]})
|
31
|
+
elsif respond_to?(options[:data])
|
32
|
+
item.merge!({'data' => send(options[:data])})
|
33
|
+
elsif options[:data].is_a?(String)
|
34
|
+
item.merge!({'data' => options[:data]})
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
14
38
|
loader.add(item, options)
|
15
39
|
end
|
16
40
|
|
@@ -45,8 +69,10 @@ module SoulmateRails
|
|
45
69
|
matcher = instance_variable_get("@#{matcher_for(attribute)}") || instance_variable_set("@#{matcher_for(attribute)}", Soulmate::Matcher.new(matcher_for(attribute)))
|
46
70
|
matches = matcher.matches_for_term(term, options)
|
47
71
|
matches = matches.map do |match|
|
48
|
-
find(match['id'].split('_')[-1].to_i)
|
49
|
-
|
72
|
+
object = find(match['id'].split('_')[-1].to_i)
|
73
|
+
object.soulmate_data = match['data'].symbolize_keys if object && match['data']
|
74
|
+
object
|
75
|
+
end
|
50
76
|
end
|
51
77
|
|
52
78
|
def matcher_for(attribute)
|
@@ -1,45 +1,91 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
autocomplete :name, :score => :id
|
8
|
-
end
|
3
|
+
require 'samples/models/user_single'
|
4
|
+
require 'samples/models/user_multiple'
|
5
|
+
require 'samples/models/user_aliases'
|
6
|
+
require 'samples/models/user_data'
|
9
7
|
|
8
|
+
module SoulmateRails
|
10
9
|
describe ModelAdditions do
|
11
|
-
context '
|
10
|
+
context 'autocomplete for name' do
|
12
11
|
before :each do
|
13
|
-
@user =
|
12
|
+
@user = UserSingle.create(:name => 'Dhruva Sagar')
|
14
13
|
end
|
15
14
|
|
16
15
|
it 'should successfully search by name' do
|
17
|
-
|
16
|
+
# By first name
|
17
|
+
users = UserSingle.search_by_name('dhr')
|
18
18
|
user = users.first
|
19
19
|
user.should eq(@user)
|
20
|
+
|
21
|
+
# By last name
|
22
|
+
users = UserSingle.search_by_name('sag')
|
23
|
+
user = users.first
|
24
|
+
user.should eq(@user)
|
25
|
+
end
|
26
|
+
|
27
|
+
after :each do
|
28
|
+
UserSingle.destroy_all
|
20
29
|
end
|
21
30
|
end
|
22
31
|
|
23
|
-
context '
|
32
|
+
context 'autocomplete for name and country' do
|
24
33
|
before :each do
|
25
|
-
|
26
|
-
User.autocomplete(:country, :score => :id)
|
27
|
-
@user = User.create(:name => 'Dhruva Sagar', :country => 'India')
|
34
|
+
@user = UserMultiple.create(:name => 'Dhruva Sagar', :country => 'India')
|
28
35
|
end
|
29
36
|
|
30
37
|
it 'should successfully search by name as well as country' do
|
31
|
-
users =
|
38
|
+
users = UserMultiple.search_by_name('dhr')
|
39
|
+
user = users.first
|
40
|
+
user.should eq(@user)
|
41
|
+
|
42
|
+
users = UserMultiple.search_by_country('ind')
|
43
|
+
user = users.first
|
44
|
+
user.should eq(@user)
|
45
|
+
end
|
46
|
+
|
47
|
+
after :each do
|
48
|
+
UserMultiple.destroy_all
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'autocomplete name with aliases' do
|
53
|
+
before :each do
|
54
|
+
@user = UserAliases.create(:name => 'Dhruva Sagar')
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should successfully search by name' do
|
58
|
+
# By reverse of my first name
|
59
|
+
users = UserAliases.search_by_name('avu')
|
32
60
|
user = users.first
|
33
61
|
user.should eq(@user)
|
34
62
|
|
35
|
-
|
63
|
+
# By reverse of my last name
|
64
|
+
users = UserAliases.search_by_name('rag')
|
36
65
|
user = users.first
|
37
66
|
user.should eq(@user)
|
38
67
|
end
|
68
|
+
|
69
|
+
after :each do
|
70
|
+
UserAliases.destroy_all
|
71
|
+
end
|
39
72
|
end
|
40
73
|
|
41
|
-
|
42
|
-
|
74
|
+
context 'autocomplete name with additional data' do
|
75
|
+
before :each do
|
76
|
+
@user = UserData.create(:name => 'Dhruva Sagar', :country => 'India')
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should successfully search by name and set data' do
|
80
|
+
users = UserData.search_by_name('dhr')
|
81
|
+
user = users.first
|
82
|
+
user.should eq(@user)
|
83
|
+
user.soulmate_data.should eq({:source => 'test'})
|
84
|
+
end
|
85
|
+
|
86
|
+
after :each do
|
87
|
+
UserData.destroy_all
|
88
|
+
end
|
43
89
|
end
|
44
90
|
end
|
45
91
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: soulmate_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1.beta
|
5
5
|
prerelease: 6
|
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: 2013-03-
|
12
|
+
date: 2013-03-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
@@ -132,11 +132,9 @@ executables: []
|
|
132
132
|
extensions: []
|
133
133
|
extra_rdoc_files: []
|
134
134
|
files:
|
135
|
-
- .document
|
136
135
|
- .gitignore
|
137
136
|
- .rvmrc
|
138
137
|
- Gemfile
|
139
|
-
- LICENSE.txt
|
140
138
|
- README.markdown
|
141
139
|
- Rakefile
|
142
140
|
- lib/soulmate/base.rb
|
@@ -149,6 +147,10 @@ files:
|
|
149
147
|
- lib/soulmate_rails/version.rb
|
150
148
|
- soulmate_rails.gemspec
|
151
149
|
- spec/config/test.conf
|
150
|
+
- spec/samples/models/user_aliases.rb
|
151
|
+
- spec/samples/models/user_data.rb
|
152
|
+
- spec/samples/models/user_multiple.rb
|
153
|
+
- spec/samples/models/user_single.rb
|
152
154
|
- spec/samples/stop-words.txt
|
153
155
|
- spec/samples/venues.json
|
154
156
|
- spec/soulmate/loader_spec.rb
|
@@ -170,7 +172,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
170
172
|
version: '0'
|
171
173
|
segments:
|
172
174
|
- 0
|
173
|
-
hash:
|
175
|
+
hash: 270579878346958434
|
174
176
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
175
177
|
none: false
|
176
178
|
requirements:
|
data/.document
DELETED
data/LICENSE.txt
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
Copyright (c) 2011 Eric Waller
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
a copy of this software and associated documentation files (the
|
5
|
-
"Software"), to deal in the Software without restriction, including
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
9
|
-
the following conditions:
|
10
|
-
|
11
|
-
The above copyright notice and this permission notice shall be
|
12
|
-
included in all copies or substantial portions of the Software.
|
13
|
-
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|