textacular 3.1.0 → 3.2.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.
- 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
|
+
[](https://travis-ci.org/textacular/textacular) [](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
|