textacular 3.0.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.
@@ -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