textacular 4.0.1 → 5.3.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 +5 -5
- data/CHANGELOG.md +19 -0
- data/Gemfile +4 -0
- data/README.md +32 -2
- data/Rakefile +18 -2
- data/lib/textacular.rb +41 -15
- data/lib/textacular/full_text_indexer.rb +2 -2
- data/lib/textacular/migration_generator.rb +1 -0
- data/lib/textacular/version.rb +1 -1
- data/spec/config.travis.yml +2 -2
- data/spec/textacular/full_text_indexer_spec.rb +5 -5
- data/spec/textacular/searchable_spec.rb +50 -0
- data/spec/textacular_spec.rb +7 -0
- metadata +23 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 39d5e5ef4609c4ad498b48ba0b2553b5e211cca399fd6df820db27b2925114d6
|
4
|
+
data.tar.gz: b0b76e8c23b19fa21f6e283c449099d5f6e8978d50e788f49a4cf80bc0664ea9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10bf037b59c151203a7f2dd962f7a4acb9abb0638f09fea15eba6f887c34635a28cc4aaa931df5a052da712b858e65080449a04e320b97e88e3b3cf997728182
|
7
|
+
data.tar.gz: e807fa30b6bf512418a06e97833fd48577be25aadd34d26d289df1005f83b0b9f1980e296ad818e05ee7a72357ae0453c2f8cd5eb2aed73161c85fac77e7ec05
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,25 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## 5.3.0
|
6
|
+
|
7
|
+
* Add `#web_search` method to use Postgres' 11+ `websearch_to_tsquery`
|
8
|
+
|
9
|
+
## 5.2.0
|
10
|
+
|
11
|
+
* Active Record 6.0 compatibility
|
12
|
+
|
13
|
+
## 5.1.0
|
14
|
+
|
15
|
+
* ActiveRecord 5.2 compatibility by wrapping string queries with `Arel.sql()`
|
16
|
+
* Adds latest Ruby, Rails and Postgres-dependencies to Travis.
|
17
|
+
* Rewrite development migration code to support Rails 5.0-5.2.
|
18
|
+
|
19
|
+
## 5.0.0
|
20
|
+
|
21
|
+
* ActiveRecord 5.1 compatibility
|
22
|
+
* drop support for ActiveRecord older than 5.0 and Ruby version lower than 2.2.5
|
23
|
+
|
5
24
|
## 4.0.1
|
6
25
|
|
7
26
|
* ActiveRecord 5 compatibility above 5.0.0
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -25,12 +25,20 @@ extending ActiveRecord with scopes making search easy and fun!
|
|
25
25
|
|
26
26
|
### Quick Start
|
27
27
|
|
28
|
-
#### Rails 3, Rails 4
|
28
|
+
#### Rails 3, Rails 4
|
29
29
|
|
30
30
|
In the project's Gemfile add
|
31
31
|
|
32
32
|
```ruby
|
33
|
-
gem 'textacular', '~>
|
33
|
+
gem 'textacular', '~> 4.0'
|
34
|
+
```
|
35
|
+
|
36
|
+
#### Rails > 5.0
|
37
|
+
|
38
|
+
In the project's Gemfile add
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
gem 'textacular', '~> 5.0'
|
34
42
|
```
|
35
43
|
|
36
44
|
#### ActiveRecord outside of Rails
|
@@ -67,6 +75,20 @@ Game.advanced_search(title: 'Street|Fantasy')
|
|
67
75
|
Game.advanced_search(system: '!PS2')
|
68
76
|
```
|
69
77
|
|
78
|
+
The `#web_search` method lets you use Postgres' 11+ `websearch_to_tsquery` function
|
79
|
+
supporting websearch like syntax:
|
80
|
+
|
81
|
+
- unquoted text: text not inside quote marks will be converted to terms separated by & operators, as if processed by plainto_tsquery.
|
82
|
+
- "quoted text": text inside quote marks will be converted to terms separated by <-> operators, as if processed by phraseto_tsquery.
|
83
|
+
- OR: logical or will be converted to the | operator.
|
84
|
+
- -: the logical not operator, converted to the the ! operator.
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
Game.web_search(title: '"Street Fantasy"')
|
88
|
+
Game.web_search(title: 'Street OR Fantasy')
|
89
|
+
Game.web_search(system: '-PS2')
|
90
|
+
```
|
91
|
+
|
70
92
|
Finally, the `#fuzzy_search` method lets you use Postgres's trigram search
|
71
93
|
functionality.
|
72
94
|
|
@@ -140,12 +162,20 @@ end
|
|
140
162
|
You can have Postgresql use an index for the full-text search. To declare a full-text index, in a
|
141
163
|
migration add code like the following:
|
142
164
|
|
165
|
+
#### For basic_search
|
143
166
|
```ruby
|
144
167
|
execute "
|
145
168
|
create index on email_logs using gin(to_tsvector('english', subject));
|
146
169
|
create index on email_logs using gin(to_tsvector('english', email_address));"
|
147
170
|
```
|
148
171
|
|
172
|
+
#### For fuzzy_search
|
173
|
+
```ruby
|
174
|
+
execute "
|
175
|
+
CREATE INDEX trgm_subject_indx ON users USING gist (subject gist_trgm_ops);
|
176
|
+
CREATE INDEX trgm_email_address_indx ON users USING gist (email_address gist_trgm_ops);
|
177
|
+
```
|
178
|
+
|
149
179
|
In the above example, the table email_logs has two text columns that we search against, subject and email_address.
|
150
180
|
You will need to add an index for every text/string column you query against, or else Postgresql will revert to a
|
151
181
|
full table scan instead of using the indexes.
|
data/Rakefile
CHANGED
@@ -43,12 +43,28 @@ namespace :db do
|
|
43
43
|
|
44
44
|
desc 'Run the test database migrations'
|
45
45
|
task :up => :'db:connect' do
|
46
|
-
ActiveRecord::
|
46
|
+
if ActiveRecord.version >= Gem::Version.new('6.0.0')
|
47
|
+
context = ActiveRecord::Migration.new.migration_context
|
48
|
+
migrations = context.migrations
|
49
|
+
schema_migration = context.schema_migration
|
50
|
+
elsif ActiveRecord.version >= Gem::Version.new('5.2')
|
51
|
+
migrations = ActiveRecord::Migration.new.migration_context.migrations
|
52
|
+
schema_migration = nil
|
53
|
+
else
|
54
|
+
migrations = ActiveRecord::Migrator.migrations('db/migrate')
|
55
|
+
schema_migration = nil
|
56
|
+
end
|
57
|
+
ActiveRecord::Migrator.new(:up, migrations, schema_migration).migrate
|
47
58
|
end
|
48
59
|
|
49
60
|
desc 'Reverse the test database migrations'
|
50
61
|
task :down => :'db:connect' do
|
51
|
-
ActiveRecord
|
62
|
+
migrations = if ActiveRecord.version.version >= '5.2'
|
63
|
+
ActiveRecord::Migration.new.migration_context.migrations
|
64
|
+
else
|
65
|
+
ActiveRecord::Migrator.migrations('db/migrate')
|
66
|
+
end
|
67
|
+
ActiveRecord::Migrator.new(:down, migrations, nil).migrate
|
52
68
|
end
|
53
69
|
end
|
54
70
|
task :migrate => :'migrate:up'
|
data/lib/textacular.rb
CHANGED
@@ -12,29 +12,36 @@ module Textacular
|
|
12
12
|
'english'
|
13
13
|
end
|
14
14
|
|
15
|
-
def search(query = "", exclusive = true)
|
16
|
-
basic_search(query, exclusive)
|
15
|
+
def search(query = "", exclusive = true, rank_alias = nil)
|
16
|
+
basic_search(query, exclusive, rank_alias)
|
17
17
|
end
|
18
18
|
|
19
|
-
def basic_search(query = "", exclusive = true)
|
19
|
+
def basic_search(query = "", exclusive = true, rank_alias = nil)
|
20
20
|
exclusive, query = munge_exclusive_and_query(exclusive, query)
|
21
21
|
parsed_query_hash = parse_query_hash(query)
|
22
22
|
similarities, conditions = basic_similarities_and_conditions(parsed_query_hash)
|
23
|
-
assemble_query(similarities, conditions, exclusive)
|
23
|
+
assemble_query(similarities, conditions, exclusive, rank_alias)
|
24
24
|
end
|
25
25
|
|
26
|
-
def advanced_search(query = "", exclusive = true)
|
26
|
+
def advanced_search(query = "", exclusive = true, rank_alias = nil)
|
27
27
|
exclusive, query = munge_exclusive_and_query(exclusive, query)
|
28
28
|
parsed_query_hash = parse_query_hash(query)
|
29
29
|
similarities, conditions = advanced_similarities_and_conditions(parsed_query_hash)
|
30
|
-
assemble_query(similarities, conditions, exclusive)
|
30
|
+
assemble_query(similarities, conditions, exclusive, rank_alias)
|
31
31
|
end
|
32
32
|
|
33
|
-
def fuzzy_search(query = '', exclusive = true)
|
33
|
+
def fuzzy_search(query = '', exclusive = true, rank_alias = nil)
|
34
34
|
exclusive, query = munge_exclusive_and_query(exclusive, query)
|
35
35
|
parsed_query_hash = parse_query_hash(query)
|
36
36
|
similarities, conditions = fuzzy_similarities_and_conditions(parsed_query_hash)
|
37
|
-
assemble_query(similarities, conditions, exclusive)
|
37
|
+
assemble_query(similarities, conditions, exclusive, rank_alias)
|
38
|
+
end
|
39
|
+
|
40
|
+
def web_search(query = '', exclusive = true, rank_alias = nil)
|
41
|
+
exclusive, query = munge_exclusive_and_query(exclusive, query)
|
42
|
+
parsed_query_hash = parse_query_hash(query)
|
43
|
+
similarities, conditions = web_similarities_and_conditions(parsed_query_hash)
|
44
|
+
assemble_query(similarities, conditions, exclusive, rank_alias)
|
38
45
|
end
|
39
46
|
|
40
47
|
private
|
@@ -113,19 +120,38 @@ module Textacular
|
|
113
120
|
end
|
114
121
|
|
115
122
|
def fuzzy_similarity_string(table_name, column, search_term)
|
116
|
-
"COALESCE(similarity(#{table_name}.#{column}, #{search_term}), 0)"
|
123
|
+
"COALESCE(similarity(#{table_name}.#{column}::text, #{search_term}), 0)"
|
117
124
|
end
|
118
125
|
|
119
126
|
def fuzzy_condition_string(table_name, column, search_term)
|
120
|
-
"(#{table_name}.#{column} % #{search_term})"
|
127
|
+
"(#{table_name}.#{column}::text % #{search_term})"
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
def web_similarities_and_conditions(parsed_query_hash)
|
132
|
+
parsed_query_hash.inject([[], []]) do |(similarities, conditions), query_args|
|
133
|
+
similarities << web_similarity_string(*query_args)
|
134
|
+
conditions << web_condition_string(*query_args)
|
135
|
+
|
136
|
+
[similarities, conditions]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def web_similarity_string(table_name, column, search_term)
|
141
|
+
"COALESCE(ts_rank(to_tsvector(#{quoted_language}, #{table_name}.#{column}::text), websearch_to_tsquery(#{quoted_language}, #{search_term}::text)), 0)"
|
142
|
+
end
|
143
|
+
|
144
|
+
def web_condition_string(table_name, column, search_term)
|
145
|
+
"to_tsvector(#{quoted_language}, #{table_name}.#{column}::text) @@ websearch_to_tsquery(#{quoted_language}, #{search_term}::text)"
|
121
146
|
end
|
122
147
|
|
123
|
-
def assemble_query(similarities, conditions, exclusive)
|
124
|
-
|
148
|
+
def assemble_query(similarities, conditions, exclusive, rank_alias)
|
149
|
+
rank_alias ||= 'rank' + rand(100000000000000000).to_s
|
150
|
+
rank = connection.quote_column_name(rank_alias)
|
125
151
|
|
126
|
-
select("#{quoted_table_name + '.*,' if select_values.empty?} #{similarities.join(" + ")} AS #{rank}").
|
152
|
+
select(Arel.sql("#{quoted_table_name + '.*,' if select_values.empty?} #{similarities.join(" + ")} AS #{rank}")).
|
127
153
|
where(conditions.join(exclusive ? " AND " : " OR ")).
|
128
|
-
order("#{rank} DESC")
|
154
|
+
order(Arel.sql("#{rank} DESC"))
|
129
155
|
end
|
130
156
|
|
131
157
|
def select_values
|
@@ -151,7 +177,7 @@ module Textacular
|
|
151
177
|
module Helper
|
152
178
|
class << self
|
153
179
|
def normalize(query)
|
154
|
-
query.to_s.gsub(/\s(?![
|
180
|
+
query.to_s.gsub(/\s(?![\&\!\|])/, '\\\\ ')
|
155
181
|
end
|
156
182
|
end
|
157
183
|
end
|
@@ -16,7 +16,7 @@ class #{model_name}FullTextSearch < ActiveRecord::Migration
|
|
16
16
|
end
|
17
17
|
MIGRATION
|
18
18
|
filename = "#{model_name.underscore}_full_text_search"
|
19
|
-
generator = Textacular::MigrationGenerator.new(
|
19
|
+
generator = Textacular::MigrationGenerator.new(filename, content)
|
20
20
|
generator.generate_migration
|
21
21
|
end
|
22
22
|
|
@@ -52,7 +52,7 @@ MIGRATION
|
|
52
52
|
<<-SQL
|
53
53
|
CREATE index #{index_name_for(model, column)}
|
54
54
|
ON #{model.table_name}
|
55
|
-
USING gin(to_tsvector(
|
55
|
+
USING gin(to_tsvector('#{dictionary}', "#{model.table_name}"."#{column}"::text));
|
56
56
|
SQL
|
57
57
|
end
|
58
58
|
|
data/lib/textacular/version.rb
CHANGED
data/spec/config.travis.yml
CHANGED
@@ -12,7 +12,7 @@ class WebComicWithSearchableNameFullTextSearch < ActiveRecord::Migration
|
|
12
12
|
DROP index IF EXISTS web_comics_name_fts_idx;
|
13
13
|
CREATE index web_comics_name_fts_idx
|
14
14
|
ON web_comics
|
15
|
-
USING gin(to_tsvector(
|
15
|
+
USING gin(to_tsvector('english', "web_comics"."name"::text));
|
16
16
|
SQL
|
17
17
|
end
|
18
18
|
|
@@ -25,7 +25,7 @@ end
|
|
25
25
|
MIGRATION
|
26
26
|
|
27
27
|
generator = double(:migration_generator)
|
28
|
-
expect(Textacular::MigrationGenerator).to receive(:new).with(
|
28
|
+
expect(Textacular::MigrationGenerator).to receive(:new).with(file_name, content).and_return(generator)
|
29
29
|
expect(generator).to receive(:generate_migration)
|
30
30
|
|
31
31
|
Textacular::FullTextIndexer.new.generate_migration('WebComicWithSearchableName')
|
@@ -42,11 +42,11 @@ class WebComicWithSearchableNameAndAuthorFullTextSearch < ActiveRecord::Migratio
|
|
42
42
|
DROP index IF EXISTS web_comics_name_fts_idx;
|
43
43
|
CREATE index web_comics_name_fts_idx
|
44
44
|
ON web_comics
|
45
|
-
USING gin(to_tsvector(
|
45
|
+
USING gin(to_tsvector('english', "web_comics"."name"::text));
|
46
46
|
DROP index IF EXISTS web_comics_author_fts_idx;
|
47
47
|
CREATE index web_comics_author_fts_idx
|
48
48
|
ON web_comics
|
49
|
-
USING gin(to_tsvector(
|
49
|
+
USING gin(to_tsvector('english', "web_comics"."author"::text));
|
50
50
|
SQL
|
51
51
|
end
|
52
52
|
|
@@ -60,7 +60,7 @@ end
|
|
60
60
|
MIGRATION
|
61
61
|
|
62
62
|
generator = double(:migration_generator)
|
63
|
-
expect(Textacular::MigrationGenerator).to receive(:new).with(
|
63
|
+
expect(Textacular::MigrationGenerator).to receive(:new).with(file_name, content).and_return(generator)
|
64
64
|
expect(generator).to receive(:generate_migration)
|
65
65
|
|
66
66
|
Textacular::FullTextIndexer.new.generate_migration('WebComicWithSearchableNameAndAuthor')
|
@@ -113,6 +113,14 @@ RSpec.describe "Searchable" do
|
|
113
113
|
end
|
114
114
|
end
|
115
115
|
|
116
|
+
describe "web search" do # Uses websearch_to_tsquery
|
117
|
+
["hello \\", "tebow!" , "food &"].each do |search_term|
|
118
|
+
it "works with interesting term \"#{search_term}\"" do
|
119
|
+
expect(WebComicWithSearchableName.web_search(search_term)).to be_empty
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
116
124
|
it "does fuzzy searching" do
|
117
125
|
expect(
|
118
126
|
WebComicWithSearchableName.fuzzy_search('Questio')
|
@@ -182,6 +190,14 @@ RSpec.describe "Searchable" do
|
|
182
190
|
expect(
|
183
191
|
WebComicWithSearchableNameAndAuthor.advanced_search("Tycho")
|
184
192
|
).to eq([penny_arcade])
|
193
|
+
|
194
|
+
expect(
|
195
|
+
WebComicWithSearchableNameAndAuthor.web_search("Penny")
|
196
|
+
).to eq([penny_arcade])
|
197
|
+
|
198
|
+
expect(
|
199
|
+
WebComicWithSearchableNameAndAuthor.web_search("Tycho")
|
200
|
+
).to eq([penny_arcade])
|
185
201
|
end
|
186
202
|
|
187
203
|
it "allows includes" do
|
@@ -190,5 +206,39 @@ RSpec.describe "Searchable" do
|
|
190
206
|
).to eq([penny_arcade])
|
191
207
|
end
|
192
208
|
end
|
209
|
+
|
210
|
+
context 'custom rank' do
|
211
|
+
let!(:questionable_content) do
|
212
|
+
WebComicWithSearchableName.create(
|
213
|
+
name: 'Questionable Content',
|
214
|
+
author: nil,
|
215
|
+
)
|
216
|
+
end
|
217
|
+
|
218
|
+
it "is selected for search" do
|
219
|
+
search_result = WebComicWithSearchableNameAndAuthor.search('Questionable Content', true, 'my_rank')
|
220
|
+
expect(search_result.first.attributes['my_rank']).to be_truthy
|
221
|
+
end
|
222
|
+
|
223
|
+
it "is selected for basic_search" do
|
224
|
+
search_result = WebComicWithSearchableNameAndAuthor.basic_search('Questionable Content', true, 'my_rank')
|
225
|
+
expect(search_result.first.attributes['my_rank']).to be_truthy
|
226
|
+
end
|
227
|
+
|
228
|
+
it "is selected for advanced_search" do
|
229
|
+
search_result = WebComicWithSearchableNameAndAuthor.advanced_search('Questionable Content', true, 'my_rank')
|
230
|
+
expect(search_result.first.attributes['my_rank']).to be_truthy
|
231
|
+
end
|
232
|
+
|
233
|
+
it "is selected for fuzzy_search" do
|
234
|
+
search_result = WebComicWithSearchableNameAndAuthor.fuzzy_search('Questionable Content', true, 'my_rank')
|
235
|
+
expect(search_result.first.attributes['my_rank']).to be_truthy
|
236
|
+
end
|
237
|
+
|
238
|
+
it "is selected for web_search" do
|
239
|
+
search_result = WebComicWithSearchableNameAndAuthor.web_search('Questionable Content', true, 'my_rank')
|
240
|
+
expect(search_result.first.attributes['my_rank']).to be_truthy
|
241
|
+
end
|
242
|
+
end
|
193
243
|
end
|
194
244
|
end
|
data/spec/textacular_spec.rb
CHANGED
@@ -181,6 +181,13 @@ RSpec.describe Textacular do
|
|
181
181
|
expect(GameExtendedWithTextacular).to respond_to(:search)
|
182
182
|
end
|
183
183
|
|
184
|
+
describe "#fuzzy_search" do
|
185
|
+
it 'searches non-text columns' do
|
186
|
+
expect(GameExtendedWithTextacular.fuzzy_search(id: mario.id)
|
187
|
+
).to eq([mario])
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
184
191
|
describe "#advanced_search" do
|
185
192
|
context "with a String argument" do
|
186
193
|
it "searches across all :string columns (if not indexes have been specified)" do
|
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:
|
4
|
+
version: 5.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Hamill
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2020-06-10 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: pg
|
@@ -19,14 +19,14 @@ dependencies:
|
|
19
19
|
requirements:
|
20
20
|
- - "~>"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
22
|
+
version: 1.0.0
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 1.0.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: rspec
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,26 +97,40 @@ dependencies:
|
|
97
97
|
- - ">="
|
98
98
|
- !ruby/object:Gem::Version
|
99
99
|
version: '0'
|
100
|
+
- !ruby/object:Gem::Dependency
|
101
|
+
name: byebug
|
102
|
+
requirement: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
type: :development
|
108
|
+
prerelease: false
|
109
|
+
version_requirements: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
100
114
|
- !ruby/object:Gem::Dependency
|
101
115
|
name: activerecord
|
102
116
|
requirement: !ruby/object:Gem::Requirement
|
103
117
|
requirements:
|
104
118
|
- - ">="
|
105
119
|
- !ruby/object:Gem::Version
|
106
|
-
version: '
|
120
|
+
version: '5.0'
|
107
121
|
- - "<"
|
108
122
|
- !ruby/object:Gem::Version
|
109
|
-
version: '
|
123
|
+
version: '6.1'
|
110
124
|
type: :runtime
|
111
125
|
prerelease: false
|
112
126
|
version_requirements: !ruby/object:Gem::Requirement
|
113
127
|
requirements:
|
114
128
|
- - ">="
|
115
129
|
- !ruby/object:Gem::Version
|
116
|
-
version: '
|
130
|
+
version: '5.0'
|
117
131
|
- - "<"
|
118
132
|
- !ruby/object:Gem::Version
|
119
|
-
version: '
|
133
|
+
version: '6.1'
|
120
134
|
description: |-
|
121
135
|
Textacular exposes full text search capabilities from PostgreSQL, extending
|
122
136
|
ActiveRecord with scopes making search easy and fun!
|
@@ -180,8 +194,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
180
194
|
- !ruby/object:Gem::Version
|
181
195
|
version: '0'
|
182
196
|
requirements: []
|
183
|
-
|
184
|
-
rubygems_version: 2.2.2
|
197
|
+
rubygems_version: 3.0.3
|
185
198
|
signing_key:
|
186
199
|
specification_version: 4
|
187
200
|
summary: Textacular exposes full text search capabilities from PostgreSQL
|
@@ -207,4 +220,3 @@ test_files:
|
|
207
220
|
- spec/textacular/migration_generator_spec.rb
|
208
221
|
- spec/textacular/searchable_spec.rb
|
209
222
|
- spec/textacular/trigram_installer_spec.rb
|
210
|
-
has_rdoc:
|