mongoid-searchable 0.1.0

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/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2011 Jason Coene
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.
data/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # Mongoid Searchable
2
+
3
+ Mongoid Searchable provides simple field search for your Mongoid models using the full-text search technique described in the [MongoDB documentation](http://www.mongodb.org/display/DOCS/Full+Text+Search+in+Mongo).
4
+
5
+ ## Getting Started
6
+
7
+ First, add mongoid-searchable to your Gemfile:
8
+
9
+ ```ruby
10
+ gem 'mongoid-searchable'
11
+ ```
12
+
13
+ Next, include the module and tell it how to search your model:
14
+
15
+ ```ruby
16
+ class City
17
+ include Mongoid::Document
18
+ include Mongoid::Searchable
19
+
20
+ field :name, :type => String
21
+ field :population, :type => Integer
22
+ field :boroughs, :type => Array
23
+ field :officials, :type => Hash
24
+
25
+ searchable :name, :population, :boroughs, :officials
26
+ end
27
+ ```
28
+
29
+ You can now use the *search* method on your model to find what you're looking for:
30
+
31
+ ```ruby
32
+ # Create a few example cities
33
+ City.create :name => 'New York, NY', :population => 18_897_109,
34
+ :boroughs => ['Manhattan', 'Brooklyn', 'Queens', 'The Bronx', 'Staten Island'],
35
+ :officials => { 'Mayor' => 'Michael Bloomberg', 'Governor' => 'Andrew Cuomo' }
36
+ City.create :name => 'Rochester, NY', :population => 1_098_201,
37
+ :officials => { 'Mayor' => 'Thomas Richards', 'Governor' => 'Andrew Cuomo' }
38
+ City.create :name => 'Rochester, MN', :population => 186_011,
39
+ :officials => { 'Mayor' => 'Ardell Brede', 'Governor' => 'Mark Dayton' }
40
+
41
+ City.search('ny') # => 2 records
42
+ City.search('rochester') # => 2 records
43
+ City.search('manhattan') # => 1 record
44
+ ```
45
+
46
+ You can also choose to match all or any tokens. The default is to match **all** terms:
47
+
48
+ ```ruby
49
+ City.search('rochester ny') # => 1 record (defaults to all)
50
+ City.search('rochester ny', :match => :any) # => 3 records
51
+ ```
52
+
53
+ We can match partial or exact words as well. The default is to match **partial** words:
54
+
55
+ ```ruby
56
+ City.search('roch') # => 2 records
57
+ City.search('roch', :exact => true) # => 0 records
58
+ ```
59
+
60
+ You can chain other criteria on to your search, as per Mongoid convention:
61
+
62
+ ```ruby
63
+ City.search('ny').where(:population.gt => 2_000_000) # => 1 record
64
+ City.search('rochester').where(:population.lt => 500_000) # => 1 record
65
+ ```
66
+
67
+ ## Customization
68
+
69
+ You can also pass additional arguments to *searchable* to provide more control over the behavior.
70
+
71
+ **Changing the field name:** You can specify the field to use for keyword storage using **as**. The default is to use the *keywords* field:
72
+
73
+ ```ruby
74
+ class Person
75
+ ...
76
+ searchable :name, :as => :search_fields
77
+ ...
78
+ end
79
+ ```
80
+
81
+ **Turning off indexing:** You can also turn off indexing on your keyword field using **index**. This isn't recommended and defaults to *on*:
82
+
83
+ ```ruby
84
+ class Person
85
+ ...
86
+ searchable :name, :index => false
87
+ ...
88
+ end
89
+ ```
90
+
91
+ ## Enhancements and Pull Requests
92
+
93
+ If you find the project useful but it doesn't meet all of your needs, feel free to fork it and send a pull request.
94
+
95
+ ## License
96
+
97
+ MIT license, go wild.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'bundler'
4
+ require 'rspec/core/rake_task'
5
+
6
+ Bundler::GemHelper.install_tasks
7
+
8
+ desc 'Run all specs in the spec directory'
9
+ RSpec::Core::RakeTask.new(:spec)
10
+
11
+ task :default => :spec
@@ -0,0 +1,5 @@
1
+ module Mongoid
2
+ module Searchable
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,88 @@
1
+ require 'mongoid'
2
+
3
+ module Mongoid
4
+
5
+ module Searchable
6
+
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ cattr_accessor :keywords_field, :searchable_fields
11
+ end
12
+
13
+ module ClassMethods
14
+
15
+ def searchable(*fields)
16
+ options = { :as => :keywords, :index => true }.merge(fields.extract_options!)
17
+
18
+ self.keywords_field = options[:as].to_sym
19
+ self.searchable_fields = fields.map(&:to_s)
20
+
21
+ field keywords_field
22
+ index :keywords if options[:index]
23
+
24
+ before_save :build_keywords
25
+
26
+ end
27
+
28
+ def search(query, options={})
29
+ keywords = query.to_s.split(' ').map { |s| s.downcase.gsub(/[^a-z0-9]/, '') }.select { |s| s.length >= 2 }.uniq
30
+ options[:match] ||= :all
31
+ options[:exact] ||= false
32
+
33
+ if options[:exact]
34
+ match = keywords.collect{|k| /^#{Regexp.escape(k)}$/ }
35
+ else
36
+ match = keywords.collect{|k| /#{Regexp.escape(k)}/ }
37
+ end
38
+
39
+ raise "Please define one or more fields as searchable before attempting to search." if keywords_field.nil? or searchable_fields.nil?
40
+
41
+ if keywords.any?
42
+ if options[:match].to_sym == :all
43
+ all_in(keywords_field.to_sym => match)
44
+ elsif options[:match].to_sym == :any
45
+ any_in(keywords_field.to_sym => match)
46
+ else
47
+ where()
48
+ end
49
+ else
50
+ where()
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ module InstanceMethods
57
+
58
+ def clean_keywords(value)
59
+ words = []
60
+
61
+ if value.is_a?(String) or value.is_a?(Numeric)
62
+ words << value.to_s.split(' ').map { |s| s.downcase.gsub(/[^a-z0-9]/, '') }.select { |s| s.length >= 2 }
63
+ elsif value.is_a?(Array) && value.any?
64
+ value.each do |v|
65
+ words << clean_keywords(v)
66
+ end
67
+ elsif value.is_a?(Hash) && value.any?
68
+ value.each do |k,v|
69
+ words << clean_keywords(v)
70
+ end
71
+ end
72
+
73
+ words.flatten.uniq
74
+ end
75
+
76
+ def build_keywords
77
+ keywords = []
78
+ self.class.searchable_fields.each do |f|
79
+ keywords << clean_keywords(send("#{f}"))
80
+ end
81
+ write_attribute(self.class.keywords_field, keywords.flatten.uniq)
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+
88
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongoid-searchable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jason Coene
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-09-08 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: mongoid
16
+ requirement: &70209780623120 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70209780623120
25
+ - !ruby/object:Gem::Dependency
26
+ name: bson_ext
27
+ requirement: &70209780602240 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '1.3'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70209780602240
36
+ - !ruby/object:Gem::Dependency
37
+ name: growl
38
+ requirement: &70209780588960 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70209780588960
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: &70209780575180 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.9.2
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70209780575180
58
+ - !ruby/object:Gem::Dependency
59
+ name: rspec
60
+ requirement: &70209780540880 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: '2.6'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70209780540880
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-rspec
71
+ requirement: &70209780534900 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 0.4.3
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70209780534900
80
+ description: Mongoid Searchable allows you to easily perform full-text search your
81
+ Mongoid models.
82
+ email:
83
+ - jcoene@gmail.com
84
+ executables: []
85
+ extensions: []
86
+ extra_rdoc_files: []
87
+ files:
88
+ - lib/mongoid/searchable/version.rb
89
+ - lib/mongoid/searchable.rb
90
+ - MIT-LICENSE
91
+ - Rakefile
92
+ - Gemfile
93
+ - README.md
94
+ homepage: http://github.com/jcoene/mongoid-searchable
95
+ licenses: []
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubyforge_project:
114
+ rubygems_version: 1.8.6
115
+ signing_key:
116
+ specification_version: 3
117
+ summary: Simple keyword search for your Mongoid models.
118
+ test_files: []