textacular 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,164 @@
1
+ # Change Log
2
+
3
+ ## 3.0.0
4
+
5
+ * All deprecations have been resolved. This breaks backwards compatibility.
6
+ * Rename gem to Textacular.
7
+
8
+ ## 2.2.0
9
+
10
+ * 1 DEPRECATION
11
+ * The whole gem is being renamed and will no longer be maintained as Texticle.
12
+ The new name it Textacular.
13
+ * 1 new feature
14
+ * Expand gemspec to allow Rails 4.
15
+
16
+ ## 2.1.1
17
+
18
+ * 1 bugfix
19
+ * Include `lib/textacular/version.rb` in the gemspec so the gem will load. Sorry!
20
+
21
+
22
+ ## 2.1.0
23
+
24
+ * 1 DEPRECATION
25
+ * `search` aliases new `advanced_search` method (same functionality as before), but will
26
+ alias `basic_search` in 3.0! Should print warnings.
27
+ * 3 new features
28
+ * Generate full text search indexes from a rake task (sort of like in 1.x). Supply a specific
29
+ model name.
30
+ * New search methods: `basic_search`, `advanced_search` and `fuzzy_search`. Basic allows special
31
+ characters like &, and % in search terms. Fuzzy is based on Postgres's trigram matching extension
32
+ pg_trgm. Advanced is the same functionality from `search` previously.
33
+ * Rake task that installs pg_trgm now works on Postgres 9.1 and up.
34
+ * 2 dev improvements
35
+ * Test database configuration not automatically generated from a rake task and ignored by git.
36
+ * New interactive developer console (powered by pry).
37
+
38
+
39
+ ## 2.0.3
40
+
41
+ * 1 new feature
42
+ * Allow searching through relations. Model.join(:relation).search(:relation => {:column => "query"})
43
+ works, and reduces the need for multi-model tables. Huge thanks to Ben Hamill for the pull request.
44
+ * Allow searching through all model columns irrespective of the column's type; we cast all columns to text
45
+ in the search query. Performance may degrade when searching through anything but a string column.
46
+ * 2 bugfixes
47
+ * Fix exceptions when adding Textacular to a table-less model.
48
+ * Column names in a search query are now scoped to the current table.
49
+ * 1 dev improvement
50
+ * Running `rake` from the project root will setup the test environment by creating a test database
51
+ and running the necessary migrations. `rake` can also be used to run all the project tests.
52
+
53
+
54
+ ## 2.0.2
55
+
56
+ * 1 bugfix
57
+ * Our #respond_to? overwritten method was causing failures when a model didn't have
58
+ a table (e.g. if migrations hadn't been run yet). Not the case anymore.
59
+
60
+
61
+ ## 2.0.1
62
+
63
+ * 1 new feature
64
+ * Can now define #searchable_language to specify the language used for the query. This changes
65
+ what's considered a stop word on Postgres' side. 'english' is the default language.
66
+ * 1 bugfix
67
+ * We were only specifying a language in to_tsvector() and not in to_tsquery(), which could
68
+ cause queries to fail if the default database language wasn't set to 'english'.
69
+
70
+
71
+ ## 2.0.pre4
72
+
73
+ * 1 new feature
74
+ * Searchable is now available to specify which columns you want searched:
75
+
76
+ ```ruby
77
+ require 'textacular/searchable'
78
+ class Game
79
+ extend Searchable(:title)
80
+ end
81
+ ```
82
+
83
+ This also allows Textacular use in Rails without having #search available to all models:
84
+
85
+ ```
86
+ gem 'textacular', '~> 2.0.pre4', :require => 'textacular/searchable'
87
+ ```
88
+ * 1 bugfix
89
+ * ActiveRecord::Base.extend(Textacular) doesn't break #method_missing and #respond_to? anymore
90
+
91
+
92
+ ## 2.0.pre3
93
+
94
+ * 1 new feature
95
+ * #select calls now limit the columns that are searched
96
+ * 1 bugfix
97
+ * #search calls without an argument assume an empty string as a search term (it errored out previously)
98
+
99
+
100
+ ## 2.0.pre2
101
+
102
+ * 1 bugfix
103
+ * #respond_to? wasn't overwritten correctly
104
+
105
+ ## 2.0.pre
106
+
107
+ * Complete refactoring of Textacular
108
+ * For users:
109
+ * Textacular should only be used for its simplicity; if you need to deeply configure your text search, please give `gem install pg_search` a try.
110
+ * `#search` method is now included in all ActiveRecord models by default, and searches across a model's :string columns.
111
+ * `#search_by_<column>` dynamic methods are now available.
112
+ * `#search` can now be chained; `Game.search_by_title("Street Fighter").search_by_system("PS3")` works.
113
+ * `#search` now accepts a hash to specify columns to be searched, e.g. `Game.search(:name => "Mario")`
114
+ * No more access to `#rank` values for results (though they're still ordered by rank).
115
+ * No way to give different weights to different columns in this release.
116
+ * For devs:
117
+ * We now have actual tests to run against; this will make accepting pull requests much more enjoyable.
118
+
119
+
120
+ ## HEAD (unreleased)
121
+
122
+ * 1 minor bugfix
123
+ * Multiple named indices are now supported.
124
+
125
+
126
+ ## 1.0.4 / 2010-08-19
127
+
128
+ * 2 major enhancements
129
+ * use Rails.root instead of RAILS_ROOT
130
+ * refactored tasks to ease maintainance and patchability
131
+ * 3 minor enhancements
132
+ * fix timestamp for migrationfile
133
+ * fixed deprecation warning for rails3 (dropping rails2-support)
134
+ * prevented warning about defined constant
135
+
136
+
137
+ ## 1.0.3 / 2010-07-07
138
+
139
+ * 1 major enhancement
140
+ * Added Rails 3 support.
141
+ * 1 bugfix
142
+ * Model names that end in double 's's (like Address) don't choke the rake tasks anymore.
143
+
144
+
145
+ ## 1.0.2 / 2009-10-17
146
+
147
+ * 1 bugfix
148
+ * Generated migration now uses UTC time rather than local time.
149
+
150
+
151
+ ## 1.0.1 / 2009-04-14
152
+
153
+ * 1 minor enhancement
154
+ * Textical adds a rake task to generate FTS index migrations. Just run:
155
+
156
+ ```
157
+ rake textical:migration
158
+ ```
159
+
160
+
161
+ ## 1.0.0 / 2009-04-14
162
+
163
+ * 1 major enhancement
164
+ * Birthday!
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,143 @@
1
+ # textacular
2
+
3
+ Further documentation available at http://textacular.github.com/textacular.
4
+
5
+
6
+ ## DESCRIPTION:
7
+
8
+ Textacular exposes full text search capabilities from PostgreSQL,
9
+ extending ActiveRecord with scopes making search easy and fun!
10
+
11
+
12
+ ## FEATURES/PROBLEMS:
13
+
14
+ * Only works with PostgreSQL
15
+
16
+
17
+ ## SYNOPSIS:
18
+
19
+ ### Quick Start
20
+
21
+ #### Rails 3 (or 4!)
22
+
23
+ In the project's Gemfile add
24
+
25
+ gem 'textacular', '~> 3.0', require: 'textacular/rails'
26
+
27
+
28
+ #### ActiveRecord outside of Rails
29
+
30
+ ```ruby
31
+ require 'textacular'
32
+
33
+ ActiveRecord::Base.extend(Textacular)
34
+ ```
35
+
36
+
37
+ ### Usage
38
+
39
+ Your models now have access to search methods:
40
+
41
+ The `#basic_search` method is what you might expect: it looks literally for what
42
+ you send to it, doing nothing fancy with the input:
43
+
44
+ ```ruby
45
+ Game.basic_search('Sonic') # will search through the model's :string columns
46
+ Game.basic_search(title: 'Mario', system: 'Nintendo')
47
+ ```
48
+
49
+ The `#advanced_search` method lets you use Postgres's search syntax like '|',
50
+ '&' and '!' ('or', 'and', and 'not') as well as some other craziness. Check [the
51
+ Postgres
52
+ docs](http://www.postgresql.org/docs/9.2/static/datatype-textsearch.html) for more:
53
+
54
+ ```ruby
55
+ Game.advanced_search(title: 'Street|Fantasy')
56
+ Game.advanced_search(system: '!PS2')
57
+ ```
58
+
59
+ Finally, the `#fuzzy_search` method lets you use Postgres's trigram search
60
+ funcionality:
61
+
62
+ ```ruby
63
+ Comic.fuzzy_search(title: 'Questio') # matches Questionable Content
64
+ ```
65
+
66
+ Searches are also chainable:
67
+
68
+ ```ruby
69
+ Game.fuzzy_search(title: 'tree').basic_search(system: 'SNES')
70
+ ```
71
+
72
+
73
+ ### Setting Language
74
+
75
+ To set proper searching dictionary just override class method on your model:
76
+
77
+ ```ruby
78
+ def self.searchable_language
79
+ 'russian'
80
+ end
81
+ ```
82
+
83
+ And all your queries would go right! And don`t forget to change the migration for indexes, like shown below.
84
+
85
+
86
+ ### Creating Indexes for Super Speed
87
+ You can have Postgresql use an index for the full-text search. To declare a full-text index, in a
88
+ migration add code like the following:
89
+
90
+ ```ruby
91
+ execute "
92
+ create index on email_logs using gin(to_tsvector('english', subject));
93
+ create index on email_logs using gin(to_tsvector('english', email_address));"
94
+ ```
95
+
96
+ In the above example, the table email_logs has two text columns that we search against, subject and email_address.
97
+ You will need to add an index for every text/string column you query against, or else Postgresql will revert to a
98
+ full table scan instead of using the indexes.
99
+
100
+ If you create these indexes, you should also switch to sql for your schema_format in `config/application.rb`:
101
+
102
+ ```ruby
103
+ config.active_record.schema_format = :sql
104
+ ```
105
+
106
+
107
+ ## REQUIREMENTS:
108
+
109
+ * ActiveRecord
110
+ * Ruby 1.9.2
111
+
112
+
113
+ ## INSTALL:
114
+
115
+ ```
116
+ $ gem install textacular
117
+ ```
118
+
119
+
120
+ ## LICENSE:
121
+
122
+ (The MIT License)
123
+
124
+ Copyright (c) 2011 Aaron Patterson
125
+
126
+ Permission is hereby granted, free of charge, to any person obtaining
127
+ a copy of this software and associated documentation files (the
128
+ 'Software'), to deal in the Software without restriction, including
129
+ without limitation the rights to use, copy, modify, merge, publish,
130
+ distribute, sublicense, and/or sell copies of the Software, and to
131
+ permit persons to whom the Software is furnished to do so, subject to
132
+ the following conditions:
133
+
134
+ The above copyright notice and this permission notice shall be
135
+ included in all copies or substantial portions of the Software.
136
+
137
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
138
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
139
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
140
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
141
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
142
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
143
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,154 @@
1
+ require 'rubygems'
2
+
3
+ require 'rake'
4
+ require 'yaml'
5
+ require 'pg'
6
+ require 'active_record'
7
+ require 'benchmark'
8
+
9
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/spec')
10
+
11
+ task :default do
12
+ Rake::Task["db:setup"].invoke
13
+ Rake::Task["test"].invoke
14
+ end
15
+
16
+ desc "Fire up an interactive terminal to play with"
17
+ task :console do
18
+ require 'pry'
19
+ require File.expand_path(File.dirname(__FILE__) + '/lib/textacular')
20
+
21
+ config = YAML.load_file File.expand_path(File.dirname(__FILE__) + '/spec/config.yml')
22
+ ActiveRecord::Base.establish_connection config.merge(:adapter => :postgresql)
23
+
24
+ class Character < ActiveRecord::Base
25
+ belongs_to :web_comic
26
+ end
27
+
28
+ class WebComic < ActiveRecord::Base
29
+ has_many :characters
30
+ end
31
+
32
+ class Game < ActiveRecord::Base
33
+ end
34
+
35
+ # add ability to reload console
36
+ def reload
37
+ reload_msg = '# Reloading the console...'
38
+ puts CodeRay.scan(reload_msg, :ruby).term
39
+ Pry.save_history
40
+ exec('rake console')
41
+ end
42
+
43
+ # start the console! :-)
44
+ welcome = <<-EOS
45
+ Welcome to the Textacular devloper console. You have some classes you can play with:
46
+
47
+ class Character < ActiveRecord::Base
48
+ # string :name
49
+ # string :description
50
+ # integer :web_comic_id
51
+
52
+ belongs_to :web_comic
53
+ end
54
+
55
+ class WebComic < ActiveRecord::Base
56
+ # string :name
57
+ # string :author
58
+ # integer :id
59
+
60
+ has_many :characters
61
+ end
62
+
63
+ class Game < ActiveRecord::Base
64
+ # string :system
65
+ # string :title
66
+ # text :description
67
+ end
68
+ EOS
69
+
70
+ puts CodeRay.scan(welcome, :ruby).term
71
+ Pry.start
72
+ end
73
+
74
+ task :test do
75
+ require 'textacular_spec'
76
+ require 'textacular/searchable_spec'
77
+ require 'textacular/full_text_indexer_spec'
78
+ end
79
+
80
+ namespace :db do
81
+ desc 'Create and configure the test database'
82
+ task :setup do
83
+ spec_directory = "#{File.expand_path(File.dirname(__FILE__))}/spec"
84
+
85
+ STDOUT.puts "Detecting database configuration..."
86
+
87
+ if File.exists?("#{spec_directory}/config.yml")
88
+ STDOUT.puts "Configuration detected. Skipping confguration."
89
+ else
90
+ STDOUT.puts "Would you like to create and configure the test database? y/N"
91
+ continue = STDIN.gets.chomp
92
+
93
+ unless continue =~ /^[y]$/i
94
+ STDOUT.puts "Done."
95
+ exit 0
96
+ end
97
+
98
+ STDOUT.puts "Creating database..."
99
+ `createdb textacular`
100
+
101
+ STDOUT.puts "Writing configuration file..."
102
+
103
+ config_example = File.read("#{spec_directory}/config.yml.example")
104
+
105
+ File.open("#{spec_directory}/config.yml", "w") do |config|
106
+ config << config_example.sub(/<username>/, `whoami`.chomp)
107
+ end
108
+
109
+ STDOUT.puts "Running migrations..."
110
+ Rake::Task["db:migrate"].invoke
111
+
112
+ STDOUT.puts 'Done.'
113
+ end
114
+ end
115
+
116
+ desc 'Run migrations for test database'
117
+ task :migrate do
118
+ config = YAML.load_file File.expand_path(File.dirname(__FILE__) + '/spec/config.yml')
119
+ ActiveRecord::Base.establish_connection config.merge(:adapter => :postgresql)
120
+
121
+ ActiveRecord::Migration.instance_eval do
122
+ create_table :games do |table|
123
+ table.string :system
124
+ table.string :title
125
+ table.text :description
126
+ end
127
+ create_table :web_comics do |table|
128
+
129
+ table.string :name
130
+ table.string :author
131
+ table.text :review
132
+ table.integer :id
133
+ end
134
+
135
+ create_table :characters do |table|
136
+ table.string :name
137
+ table.string :description
138
+ table.integer :web_comic_id
139
+ end
140
+ end
141
+ end
142
+
143
+ desc 'Drop tables from test database'
144
+ task :drop do
145
+ config = YAML.load_file File.expand_path(File.dirname(__FILE__) + '/spec/config.yml')
146
+ ActiveRecord::Base.establish_connection config.merge(:adapter => :postgresql)
147
+
148
+ ActiveRecord::Migration.instance_eval do
149
+ drop_table :games
150
+ drop_table :web_comics
151
+ drop_table :characters
152
+ end
153
+ end
154
+ end