soulmate_rails 0.2.0.alpha → 0.2.1.beta

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,17 +1,22 @@
1
- # Soulmate Rails
1
+ # Soulmate Rails [![Gem Version](https://badge.fury.io/rb/soulmate_rails.png)](http://badge.fury.io/rb/soulmate_rails) [![Build Status](https://travis-ci.org/dhruvasagar/soulmate_rails.png?branch=master)](https://travis-ci.org/dhruvasagar/soulmate_rails) [![Dependency Status](https://gemnasium.com/dhruvasagar/soulmate_rails.png)](https://gemnasium.com/dhruvasagar/soulmate_rails)
2
+ <!--[![Build Status](https://drone.io/github.com/dhruvasagar/soulmate_rails/status.png)](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 of
4
- auto-completion in rails intuitively. It extends the soulmate gem <a
5
- href="http://github.com/seatgeek/soulmate">Soulmate</a> to make it easily
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
- # Some magic calculation returning a number.
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"=>"First3", "last_name"=>"Last3" "id"=>3},
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"=>"First1", "last_name"=>"Last1" "id"=>1},
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
- * `:score` : This is required. Soulmate uses it for sorting the results (in
73
- reverse order, i.e. higher score first). This can be the name of a function
74
- or can also be the name of another attribute with integer values.
75
- * `:aliases` : This is optional. Soulmate uses this as aliases for the term
76
- field and uses it for searching as well. This can be an array of values or
77
- a method name which returns an array of values.
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 MIT License
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
- }.merge( options[:aliases] ? ( respond_to?(options[:aliases]) ? send(options[:aliases]) : options[:aliases] ) : {} )
12
- # NOTE: Not supporting :data for now, will find a better way to use this later.
13
- # .merge( options[:data] ? ( respond_to?(options[:data]) ? send(options[:data]) : options[:data] ) : {} )
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) rescue nil
49
- end.compact
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,8 +1,8 @@
1
1
  module SoulmateRails
2
2
  MAJOR = 0
3
3
  MINOR = 2
4
- PATCH = 0
5
- STATUS = 'alpha'
4
+ PATCH = 1
5
+ STATUS = 'beta'
6
6
 
7
7
  VERSION = [MAJOR, MINOR, PATCH, STATUS].compact.join('.')
8
8
  end
@@ -0,0 +1,9 @@
1
+ class UserAliases < SuperModel::Base
2
+ include SoulmateRails::ModelAdditions
3
+
4
+ autocomplete :name, :score => :id, :aliases => :name_aliases
5
+
6
+ def name_aliases
7
+ self.name.split(' ').map(&:reverse)
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class UserData < SuperModel::Base
2
+ include SoulmateRails::ModelAdditions
3
+
4
+ autocomplete :name, :score => :id, :data => {:source => 'test'}
5
+ end
@@ -0,0 +1,6 @@
1
+ class UserMultiple < SuperModel::Base
2
+ include SoulmateRails::ModelAdditions
3
+
4
+ autocomplete :name, :score => :id
5
+ autocomplete :country, :score => :id
6
+ end
@@ -0,0 +1,5 @@
1
+ class UserSingle < SuperModel::Base
2
+ include SoulmateRails::ModelAdditions
3
+
4
+ autocomplete :name, :score => :id
5
+ end
@@ -1,45 +1,91 @@
1
1
  require 'spec_helper'
2
2
 
3
- module SoulmateRails
4
- class User < SuperModel::Base
5
- include ModelAdditions
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 'single autocomplete' do
10
+ context 'autocomplete for name' do
12
11
  before :each do
13
- @user = User.create(:name => 'Dhruva Sagar')
12
+ @user = UserSingle.create(:name => 'Dhruva Sagar')
14
13
  end
15
14
 
16
15
  it 'should successfully search by name' do
17
- users = User.search_by_name('dhruv')
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 'multiple autocompletes' do
32
+ context 'autocomplete for name and country' do
24
33
  before :each do
25
- # Define another autocomplete for country
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 = User.search_by_name('dhr')
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
- users = User.search_by_country('ind')
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
- after :each do
42
- User.destroy_all
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.0.alpha
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-04 00:00:00.000000000 Z
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: -2339712200945415298
175
+ hash: 270579878346958434
174
176
  required_rubygems_version: !ruby/object:Gem::Requirement
175
177
  none: false
176
178
  requirements:
data/.document DELETED
@@ -1,5 +0,0 @@
1
- lib/**/*.rb
2
- bin/*
3
- -
4
- features/**/*.feature
5
- LICENSE.txt
@@ -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.