textacular 3.1.0 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +19 -13
- data/Rakefile +2 -0
- data/lib/textacular.rb +2 -0
- data/lib/textacular/full_text_indexer.rb +4 -20
- data/lib/textacular/migration_generator.rb +31 -0
- data/lib/textacular/tasks.rb +5 -0
- data/lib/textacular/trigram_installer.rb +18 -0
- data/lib/textacular/version.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- metadata +51 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3370755c291011043272f5b45c44d4c9d9ad8445
|
4
|
+
data.tar.gz: b0c0b7c22dd7c79b7a343af679ba5ab9cee2e817
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d426b395d05e45de9ac1341f7b19ae3cf35533801e2c62dba488c221c15e0a78602e4ee349f720186701dc39586899671508068f837bfdf0852a7012c9475dc
|
7
|
+
data.tar.gz: 031698a4ae0185a3e73fd4a191f04e1a497258958378056469228e826f28b138d0aaa5b182b209841322c47fa803f31824d2751a2b13feebb86f1e361c1f76c5
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/textacular/textacular.png)](https://travis-ci.org/textacular/textacular) [![Code Climate](https://codeclimate.com/github/textacular/textacular.png)](https://codeclimate.com/github/textacular/textacular)
|
1
2
|
# textacular
|
2
3
|
|
3
4
|
Further documentation available at http://textacular.github.com/textacular.
|
@@ -48,9 +49,12 @@ Game.basic_search(title: 'Mario', system: 'Nintendo')
|
|
48
49
|
```
|
49
50
|
|
50
51
|
The `#advanced_search` method lets you use Postgres's search syntax like '|',
|
51
|
-
'&' and '!' ('or', 'and', and 'not') as well as some other craziness.
|
52
|
-
|
53
|
-
|
52
|
+
'&' and '!' ('or', 'and', and 'not') as well as some other craziness. The ideal
|
53
|
+
use for advanced_search is to take a search DSL you make up for your users and
|
54
|
+
translate it to PG's syntax. If for some reason you want to put user input
|
55
|
+
directly into an advanced search, you should be sure to catch exceptions from
|
56
|
+
syntax errors. Check [the Postgres docs]
|
57
|
+
(http://www.postgresql.org/docs/9.2/static/datatype-textsearch.html) for more:
|
54
58
|
|
55
59
|
```ruby
|
56
60
|
Game.advanced_search(title: 'Street|Fantasy')
|
@@ -58,29 +62,31 @@ Game.advanced_search(system: '!PS2')
|
|
58
62
|
```
|
59
63
|
|
60
64
|
Finally, the `#fuzzy_search` method lets you use Postgres's trigram search
|
61
|
-
|
65
|
+
functionality.
|
62
66
|
|
63
67
|
In order to use this, you'll need to make sure your database has the `pg_trgm`
|
64
|
-
module installed.
|
68
|
+
module installed. Create and run a migration to install the module:
|
65
69
|
|
66
70
|
```
|
67
|
-
rake textacular:
|
71
|
+
rake textacular:create_trigram_migration
|
72
|
+
rake db:migrate
|
68
73
|
```
|
69
74
|
|
70
|
-
|
71
|
-
task, or you might have to manually run a command. For Postgres 9.1 and above,
|
72
|
-
you'll want to run
|
75
|
+
Once that's installed, you can use it like this:
|
73
76
|
|
74
|
-
```
|
75
|
-
|
77
|
+
```ruby
|
78
|
+
Comic.fuzzy_search(title: 'Questio') # matches Questionable Content
|
76
79
|
```
|
77
80
|
|
78
|
-
|
81
|
+
Note that fuzzy searches are subject to a similarity threshold imposed by the `pg_trgm` module. The default is 0.3, meaning that at least 30% of the total string must match your search content. For example:
|
79
82
|
|
80
83
|
```ruby
|
81
|
-
Comic.fuzzy_search(title: '
|
84
|
+
Comic.fuzzy_search(title: 'Pearls') # matches Pearls Before Swine
|
85
|
+
Comic.fuzzy_search(title: 'Pear') # does not match Pearls Before Swine
|
82
86
|
```
|
83
87
|
|
88
|
+
For more info, view the `pg_trgm` documentation, specifically [F.35.2. Functions and Operators](http://www.postgresql.org/docs/9.1/static/pgtrgm.html).
|
89
|
+
|
84
90
|
Searches are also chainable:
|
85
91
|
|
86
92
|
```ruby
|
data/Rakefile
CHANGED
data/lib/textacular.rb
CHANGED
@@ -5,6 +5,8 @@ require 'textacular/version'
|
|
5
5
|
module Textacular
|
6
6
|
autoload :FullTextIndexer, 'textacular/full_text_indexer'
|
7
7
|
autoload :PostgresModuleInstaller, 'textacular/postgres_module_installer'
|
8
|
+
autoload :TrigramInstaller, 'textacular/trigram_installer'
|
9
|
+
autoload :MigrationGenerator, 'textacular/migration_generator'
|
8
10
|
|
9
11
|
def self.searchable_language
|
10
12
|
'english'
|
@@ -1,9 +1,6 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
1
|
class Textacular::FullTextIndexer
|
4
2
|
def generate_migration(model_name)
|
5
|
-
|
6
|
-
io.puts(<<-MIGRATION)
|
3
|
+
content = <<-MIGRATION
|
7
4
|
class #{model_name}FullTextSearch < ActiveRecord::Migration
|
8
5
|
def self.up
|
9
6
|
execute(<<-SQL.strip)
|
@@ -18,26 +15,13 @@ class #{model_name}FullTextSearch < ActiveRecord::Migration
|
|
18
15
|
end
|
19
16
|
end
|
20
17
|
MIGRATION
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
def stream_output(now = Time.now.utc, &block)
|
25
|
-
if !@output_stream && defined?(Rails)
|
26
|
-
FileUtils.mkdir_p(File.dirname(migration_file_name(now)))
|
27
|
-
File.open(migration_file_name(now), 'w', &block)
|
28
|
-
else
|
29
|
-
@output_stream ||= $stdout
|
30
|
-
|
31
|
-
yield @output_stream
|
32
|
-
end
|
18
|
+
filename = "#{model_name.underscore}_full_text_search"
|
19
|
+
generator = Textacular::MigrationGenerator.new(content, filename)
|
20
|
+
generator.generate_migration
|
33
21
|
end
|
34
22
|
|
35
23
|
private
|
36
24
|
|
37
|
-
def migration_file_name(now = Time.now.utc)
|
38
|
-
File.join(Rails.root, 'db', 'migrate',"#{now.strftime('%Y%m%d%H%M%S')}_full_text_search.rb")
|
39
|
-
end
|
40
|
-
|
41
25
|
def up_migration(model_name)
|
42
26
|
migration_with_type(model_name, :up)
|
43
27
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
class Textacular::MigrationGenerator
|
4
|
+
def initialize(filename, content)
|
5
|
+
@filename = filename
|
6
|
+
@content = content
|
7
|
+
end
|
8
|
+
|
9
|
+
def generate_migration
|
10
|
+
stream_output do |io|
|
11
|
+
io.puts(@content)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def stream_output(now = Time.now.utc, &block)
|
16
|
+
if !@output_stream && defined?(Rails)
|
17
|
+
FileUtils.mkdir_p(File.dirname(migration_file_name(now)))
|
18
|
+
File.open(migration_file_name(now), 'w', &block)
|
19
|
+
else
|
20
|
+
@output_stream ||= $stdout
|
21
|
+
|
22
|
+
yield @output_stream
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def migration_file_name(now = Time.now.utc)
|
29
|
+
File.join(Rails.root, 'db', 'migrate',"#{now.strftime('%Y%m%d%H%M%S')}_#{@filename}.rb")
|
30
|
+
end
|
31
|
+
end
|
data/lib/textacular/tasks.rb
CHANGED
@@ -15,4 +15,9 @@ namespace :textacular do
|
|
15
15
|
|
16
16
|
puts "Trigram text search module successfully installed into '#{installer.db_name}' database."
|
17
17
|
end
|
18
|
+
|
19
|
+
desc "Create trigram installer migration"
|
20
|
+
task :create_trigram_migration => [:environment] do
|
21
|
+
installer = Textacular::TrigramInstaller.new.generate_migration
|
22
|
+
end
|
18
23
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Textacular::TrigramInstaller
|
2
|
+
def generate_migration
|
3
|
+
content = <<-MIGRATION
|
4
|
+
class InstallTrigram < ActiveRecord::Migration
|
5
|
+
def self.up
|
6
|
+
ActiveRecord::Base.connection.execute("CREATE EXTENSION pg_trgm;")
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.down
|
10
|
+
ActiveRecord::Base.connection.execute("DROP EXTENSION pg_trgm;")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
MIGRATION
|
14
|
+
filename = "install_trigram"
|
15
|
+
generator = Textacular::MigrationGenerator.new(content, filename)
|
16
|
+
generator.generate_migration
|
17
|
+
end
|
18
|
+
end
|
data/lib/textacular/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -6,6 +6,7 @@ require 'pry'
|
|
6
6
|
require 'active_record'
|
7
7
|
require 'textacular'
|
8
8
|
require 'textacular/searchable'
|
9
|
+
require 'flexmock/test_unit'
|
9
10
|
|
10
11
|
config = YAML.load_file File.expand_path(File.dirname(__FILE__) + '/config.yml')
|
11
12
|
ActiveRecord::Base.establish_connection config.merge(:adapter => :postgresql)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: textacular
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Hamill
|
@@ -10,98 +10,126 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2014-04-10 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: pg
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
requirements:
|
19
|
-
- - ~>
|
19
|
+
- - "~>"
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: 0.14.0
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
|
-
- - ~>
|
26
|
+
- - "~>"
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
version: 0.14.0
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: minitest
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - "~>"
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 4.x
|
36
|
+
type: :development
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 4.x
|
29
43
|
- !ruby/object:Gem::Dependency
|
30
44
|
name: shoulda
|
31
45
|
requirement: !ruby/object:Gem::Requirement
|
32
46
|
requirements:
|
33
|
-
- - ~>
|
47
|
+
- - "~>"
|
34
48
|
- !ruby/object:Gem::Version
|
35
49
|
version: 2.11.3
|
36
50
|
type: :development
|
37
51
|
prerelease: false
|
38
52
|
version_requirements: !ruby/object:Gem::Requirement
|
39
53
|
requirements:
|
40
|
-
- - ~>
|
54
|
+
- - "~>"
|
41
55
|
- !ruby/object:Gem::Version
|
42
56
|
version: 2.11.3
|
43
57
|
- !ruby/object:Gem::Dependency
|
44
58
|
name: rake
|
45
59
|
requirement: !ruby/object:Gem::Requirement
|
46
60
|
requirements:
|
47
|
-
- - ~>
|
61
|
+
- - "~>"
|
48
62
|
- !ruby/object:Gem::Version
|
49
63
|
version: 0.9.0
|
50
64
|
type: :development
|
51
65
|
prerelease: false
|
52
66
|
version_requirements: !ruby/object:Gem::Requirement
|
53
67
|
requirements:
|
54
|
-
- - ~>
|
68
|
+
- - "~>"
|
55
69
|
- !ruby/object:Gem::Version
|
56
70
|
version: 0.9.0
|
57
71
|
- !ruby/object:Gem::Dependency
|
58
72
|
name: pry
|
59
73
|
requirement: !ruby/object:Gem::Requirement
|
60
74
|
requirements:
|
61
|
-
- -
|
75
|
+
- - ">="
|
62
76
|
- !ruby/object:Gem::Version
|
63
77
|
version: '0'
|
64
78
|
type: :development
|
65
79
|
prerelease: false
|
66
80
|
version_requirements: !ruby/object:Gem::Requirement
|
67
81
|
requirements:
|
68
|
-
- -
|
82
|
+
- - ">="
|
69
83
|
- !ruby/object:Gem::Version
|
70
84
|
version: '0'
|
71
85
|
- !ruby/object:Gem::Dependency
|
72
86
|
name: pry-doc
|
73
87
|
requirement: !ruby/object:Gem::Requirement
|
74
88
|
requirements:
|
75
|
-
- -
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
type: :development
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: flexmock
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
76
104
|
- !ruby/object:Gem::Version
|
77
105
|
version: '0'
|
78
106
|
type: :development
|
79
107
|
prerelease: false
|
80
108
|
version_requirements: !ruby/object:Gem::Requirement
|
81
109
|
requirements:
|
82
|
-
- -
|
110
|
+
- - ">="
|
83
111
|
- !ruby/object:Gem::Version
|
84
112
|
version: '0'
|
85
113
|
- !ruby/object:Gem::Dependency
|
86
114
|
name: activerecord
|
87
115
|
requirement: !ruby/object:Gem::Requirement
|
88
116
|
requirements:
|
89
|
-
- -
|
117
|
+
- - ">="
|
90
118
|
- !ruby/object:Gem::Version
|
91
119
|
version: '3.0'
|
92
|
-
- - <
|
120
|
+
- - "<"
|
93
121
|
- !ruby/object:Gem::Version
|
94
|
-
version: '4.
|
122
|
+
version: '4.2'
|
95
123
|
type: :runtime
|
96
124
|
prerelease: false
|
97
125
|
version_requirements: !ruby/object:Gem::Requirement
|
98
126
|
requirements:
|
99
|
-
- -
|
127
|
+
- - ">="
|
100
128
|
- !ruby/object:Gem::Version
|
101
129
|
version: '3.0'
|
102
|
-
- - <
|
130
|
+
- - "<"
|
103
131
|
- !ruby/object:Gem::Version
|
104
|
-
version: '4.
|
132
|
+
version: '4.2'
|
105
133
|
description: |-
|
106
134
|
Textacular exposes full text search capabilities from PostgreSQL, extending
|
107
135
|
ActiveRecord with scopes making search easy and fun!
|
@@ -118,10 +146,12 @@ files:
|
|
118
146
|
- Rakefile
|
119
147
|
- lib/textacular.rb
|
120
148
|
- lib/textacular/full_text_indexer.rb
|
149
|
+
- lib/textacular/migration_generator.rb
|
121
150
|
- lib/textacular/postgres_module_installer.rb
|
122
151
|
- lib/textacular/rails.rb
|
123
152
|
- lib/textacular/searchable.rb
|
124
153
|
- lib/textacular/tasks.rb
|
154
|
+
- lib/textacular/trigram_installer.rb
|
125
155
|
- lib/textacular/version.rb
|
126
156
|
- spec/config.yml.example
|
127
157
|
- spec/fixtures/character.rb
|
@@ -140,17 +170,17 @@ require_paths:
|
|
140
170
|
- lib
|
141
171
|
required_ruby_version: !ruby/object:Gem::Requirement
|
142
172
|
requirements:
|
143
|
-
- -
|
173
|
+
- - ">="
|
144
174
|
- !ruby/object:Gem::Version
|
145
175
|
version: '0'
|
146
176
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
177
|
requirements:
|
148
|
-
- -
|
178
|
+
- - ">="
|
149
179
|
- !ruby/object:Gem::Version
|
150
180
|
version: '0'
|
151
181
|
requirements: []
|
152
182
|
rubyforge_project:
|
153
|
-
rubygems_version: 2.
|
183
|
+
rubygems_version: 2.2.2
|
154
184
|
signing_key:
|
155
185
|
specification_version: 4
|
156
186
|
summary: Textacular exposes full text search capabilities from PostgreSQL
|