texticle 2.0.2 → 2.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +20 -1
- data/README.rdoc +13 -0
- data/Rakefile +32 -1
- data/lib/texticle.rb +27 -18
- data/lib/texticle/searchable.rb +2 -2
- data/spec/texticle/searchable_spec.rb +16 -12
- data/spec/texticle_spec.rb +86 -38
- metadata +35 -15
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
== 2.0.3
|
2
|
+
|
3
|
+
* 1 new feature
|
4
|
+
|
5
|
+
* Allow searching through relations. Model.join(:relation).search(:relation => {:column => "query"})
|
6
|
+
works, and reduces the need for multi-model tables. Huge thanks to Ben Hamill for the pull request.
|
7
|
+
* Allow searching through all model columns irrespective of the column's type; we cast all columns to text
|
8
|
+
in the search query. Performance may degrade when searching through anything but a string column.
|
9
|
+
|
10
|
+
* 2 bugfixes
|
11
|
+
|
12
|
+
* Fix exceptions when adding Texticle to a table-less model.
|
13
|
+
* Column names in a search query are now scoped to the current table.
|
14
|
+
|
15
|
+
* 1 dev improvement
|
16
|
+
|
17
|
+
* Running `rake` from the project root will setup the test environment by creating a test database
|
18
|
+
and running the necessary migrations. `rake` can also be used to run all the project tests.
|
19
|
+
|
1
20
|
== 2.0.2
|
2
21
|
|
3
22
|
* 1 bugfix
|
@@ -25,7 +44,7 @@
|
|
25
44
|
|
26
45
|
require 'texticle/searchable'
|
27
46
|
class Game
|
28
|
-
|
47
|
+
extend Searchable(:title)
|
29
48
|
end
|
30
49
|
|
31
50
|
This also allows Texticle use in Rails without having #search available to all models:
|
data/README.rdoc
CHANGED
@@ -38,6 +38,19 @@ Your models now have access to the search method:
|
|
38
38
|
Game.search_by_title_and_system('Final Fantasy', 'PS2')
|
39
39
|
Game.search_by_title_or_system('Final Fantasy, 'PS3')
|
40
40
|
|
41
|
+
=== Creating Indexes for Super Speed
|
42
|
+
You can have Postgresql use an index for the full-text search. To declare a full-text index, in a
|
43
|
+
migration add code like the following:
|
44
|
+
|
45
|
+
execute "
|
46
|
+
create index on email_logs using gin(to_tsvector('english', subject));
|
47
|
+
create index on email_logs using gin(to_tsvector('english', email_address));"
|
48
|
+
|
49
|
+
In the above example, the table email_logs has two text columns that we search against, subject and email_address.
|
50
|
+
You will need to add an index for every text/string column you query against, or else Postgresql will revert to a
|
51
|
+
full table scan instead of using the indexes.
|
52
|
+
|
53
|
+
|
41
54
|
== REQUIREMENTS:
|
42
55
|
|
43
56
|
* ActiveRecord
|
data/Rakefile
CHANGED
@@ -5,27 +5,58 @@ require 'pg'
|
|
5
5
|
require 'active_record'
|
6
6
|
require 'benchmark'
|
7
7
|
|
8
|
-
|
8
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/spec')
|
9
|
+
|
10
|
+
task :default do
|
11
|
+
config = File.open(File.expand_path(File.dirname(__FILE__) + '/spec/config.yml')).read
|
12
|
+
if config.match /<username>/
|
13
|
+
print "Would you like to create and configure the test database? y/n "
|
14
|
+
continue = STDIN.getc
|
15
|
+
exit 0 unless continue == "Y" || continue == "y"
|
16
|
+
sh "createdb texticle"
|
17
|
+
File.open(File.expand_path(File.dirname(__FILE__) + '/spec/config.yml'), "w") do |writable_config|
|
18
|
+
writable_config << config.sub(/<username>/, `whoami`.chomp)
|
19
|
+
end
|
20
|
+
Rake::Task["db:migrate"].invoke
|
21
|
+
end
|
22
|
+
Rake::Task["test"].invoke
|
23
|
+
end
|
24
|
+
|
25
|
+
task :test do
|
26
|
+
require 'texticle_spec'
|
27
|
+
require 'texticle/searchable_spec'
|
28
|
+
end
|
9
29
|
|
10
30
|
namespace :db do
|
11
31
|
desc 'Run migrations for test database'
|
12
32
|
task :migrate do
|
33
|
+
require 'spec_helper'
|
13
34
|
ActiveRecord::Migration.instance_eval do
|
14
35
|
create_table :games do |table|
|
15
36
|
table.string :system
|
16
37
|
table.string :title
|
38
|
+
table.text :description
|
17
39
|
end
|
18
40
|
create_table :web_comics do |table|
|
19
41
|
table.string :name
|
20
42
|
table.string :author
|
43
|
+
table.text :review
|
44
|
+
table.integer :id
|
45
|
+
end
|
46
|
+
create_table :characters do |table|
|
47
|
+
table.string :name
|
48
|
+
table.string :description
|
49
|
+
table.integer :web_comic_id
|
21
50
|
end
|
22
51
|
end
|
23
52
|
end
|
24
53
|
desc 'Drop tables from test database'
|
25
54
|
task :drop do
|
55
|
+
require 'spec_helper'
|
26
56
|
ActiveRecord::Migration.instance_eval do
|
27
57
|
drop_table :games
|
28
58
|
drop_table :web_comics
|
59
|
+
drop_table :characters
|
29
60
|
end
|
30
61
|
end
|
31
62
|
end
|
data/lib/texticle.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
|
3
3
|
module Texticle
|
4
|
-
|
5
4
|
def search(query = "", exclusive = true)
|
6
|
-
|
5
|
+
@similarities = []
|
6
|
+
@conditions = []
|
7
7
|
|
8
8
|
unless query.is_a?(Hash)
|
9
9
|
exclusive = false
|
@@ -12,20 +12,12 @@ module Texticle
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
conditions = []
|
17
|
-
|
18
|
-
query.each do |column, search_term|
|
19
|
-
column = connection.quote_column_name(column)
|
20
|
-
search_term = connection.quote normalize(Helper.normalize(search_term))
|
21
|
-
similarities << "ts_rank(to_tsvector(#{language}, #{quoted_table_name}.#{column}), to_tsquery(#{language}, #{search_term}))"
|
22
|
-
conditions << "to_tsvector(#{language}, #{column}) @@ to_tsquery(#{language}, #{search_term})"
|
23
|
-
end
|
15
|
+
parse_query_hash(query)
|
24
16
|
|
25
17
|
rank = connection.quote_column_name('rank' + rand.to_s)
|
26
18
|
|
27
|
-
select("#{quoted_table_name + '.*,' if scoped.select_values.empty?} #{similarities.join(" + ")} AS #{rank}").
|
28
|
-
where(conditions.join(exclusive ? " AND " : " OR ")).
|
19
|
+
select("#{quoted_table_name + '.*,' if scoped.select_values.empty?} #{@similarities.join(" + ")} AS #{rank}").
|
20
|
+
where(@conditions.join(exclusive ? " AND " : " OR ")).
|
29
21
|
order("#{rank} DESC")
|
30
22
|
end
|
31
23
|
|
@@ -45,23 +37,41 @@ module Texticle
|
|
45
37
|
else
|
46
38
|
super
|
47
39
|
end
|
40
|
+
rescue ActiveRecord::StatementInvalid
|
41
|
+
super
|
48
42
|
end
|
49
43
|
|
50
44
|
def respond_to?(method, include_private = false)
|
51
45
|
return super if self == ActiveRecord::Base
|
52
46
|
Helper.dynamic_search_method?(method, self.columns) or super
|
53
|
-
rescue
|
47
|
+
rescue StandardError
|
54
48
|
super
|
55
49
|
end
|
56
50
|
|
57
51
|
private
|
58
52
|
|
53
|
+
def parse_query_hash(query, table_name = quoted_table_name)
|
54
|
+
language = connection.quote(searchable_language)
|
55
|
+
table_name = connection.quote_table_name(table_name)
|
56
|
+
|
57
|
+
query.each do |column_or_table, search_term|
|
58
|
+
if search_term.is_a?(Hash)
|
59
|
+
parse_query_hash(search_term, column_or_table)
|
60
|
+
else
|
61
|
+
column = connection.quote_column_name(column_or_table)
|
62
|
+
search_term = connection.quote normalize(Helper.normalize(search_term))
|
63
|
+
@similarities << "ts_rank(to_tsvector(#{language}, #{table_name}.#{column}::text), to_tsquery(#{language}, #{search_term}::text))"
|
64
|
+
@conditions << "to_tsvector(#{language}, #{table_name}.#{column}::text) @@ to_tsquery(#{language}, #{search_term}::text)"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
59
69
|
def normalize(query)
|
60
70
|
query
|
61
71
|
end
|
62
72
|
|
63
73
|
def searchable_columns
|
64
|
-
columns.select {|column| column.type
|
74
|
+
columns.select {|column| [:string, :text].include? column.type }.map(&:name)
|
65
75
|
end
|
66
76
|
|
67
77
|
def searchable_language
|
@@ -91,7 +101,7 @@ module Texticle
|
|
91
101
|
end
|
92
102
|
|
93
103
|
def exclusive_dynamic_search_method?(method, class_columns)
|
94
|
-
string_columns = class_columns.
|
104
|
+
string_columns = class_columns.map(&:name)
|
95
105
|
columns = exclusive_dynamic_search_columns(method)
|
96
106
|
unless columns.empty?
|
97
107
|
columns.all? {|column| string_columns.include?(column) }
|
@@ -101,7 +111,7 @@ module Texticle
|
|
101
111
|
end
|
102
112
|
|
103
113
|
def inclusive_dynamic_search_method?(method, class_columns)
|
104
|
-
string_columns = class_columns.
|
114
|
+
string_columns = class_columns.map(&:name)
|
105
115
|
columns = inclusive_dynamic_search_columns(method)
|
106
116
|
unless columns.empty?
|
107
117
|
columns.all? {|column| string_columns.include?(column) }
|
@@ -116,5 +126,4 @@ module Texticle
|
|
116
126
|
end
|
117
127
|
end
|
118
128
|
end
|
119
|
-
|
120
129
|
end
|
data/lib/texticle/searchable.rb
CHANGED
@@ -1,16 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'fixtures/webcomic'
|
2
3
|
require 'texticle/searchable'
|
3
4
|
|
4
|
-
class WebComic < ActiveRecord::Base
|
5
|
-
# string :name
|
6
|
-
# string :author
|
7
|
-
end
|
8
|
-
|
9
5
|
class SearchableTest < Test::Unit::TestCase
|
10
|
-
|
11
6
|
context "when extending an ActiveRecord::Base subclass" do
|
12
7
|
setup do
|
13
|
-
@qcont = WebComic.create :name => "Questionable Content", :author => "
|
8
|
+
@qcont = WebComic.create :name => "Questionable Content", :author => "Jeph Jaques"
|
14
9
|
@jhony = WebComic.create :name => "Johnny Wander", :author => "Ananth & Yuko"
|
15
10
|
@ddeeg = WebComic.create :name => "Dominic Deegan", :author => "Mookie"
|
16
11
|
@penny = WebComic.create :name => "Penny Arcade", :author => "Tycho & Gabe"
|
@@ -18,11 +13,12 @@ class SearchableTest < Test::Unit::TestCase
|
|
18
13
|
|
19
14
|
teardown do
|
20
15
|
WebComic.delete_all
|
16
|
+
#Object.send(:remove_const, :WebComic) if defined?(WebComic)
|
21
17
|
end
|
22
18
|
|
23
|
-
context "with no
|
19
|
+
context "with no parameters" do
|
24
20
|
setup do
|
25
|
-
WebComic.extend
|
21
|
+
WebComic.extend Searchable
|
26
22
|
end
|
27
23
|
|
28
24
|
should "search across all columns" do
|
@@ -33,18 +29,27 @@ class SearchableTest < Test::Unit::TestCase
|
|
33
29
|
|
34
30
|
context "with one column as parameter" do
|
35
31
|
setup do
|
36
|
-
WebComic.extend
|
32
|
+
WebComic.extend Searchable(:name)
|
37
33
|
end
|
38
34
|
|
39
35
|
should "only search across the given column" do
|
40
36
|
assert_equal [@penny], WebComic.search("Penny")
|
41
37
|
assert_empty WebComic.search("Tycho")
|
42
38
|
end
|
39
|
+
|
40
|
+
should "define :searchable_columns as private" do
|
41
|
+
assert_raise(NoMethodError) { WebComic.searchable_columns }
|
42
|
+
begin
|
43
|
+
WebComic.searchable_columns
|
44
|
+
rescue NoMethodError => error
|
45
|
+
assert_match error.message, /private method/
|
46
|
+
end
|
47
|
+
end
|
43
48
|
end
|
44
49
|
|
45
50
|
context "with two columns as parameters" do
|
46
51
|
setup do
|
47
|
-
WebComic.extend
|
52
|
+
WebComic.extend Searchable(:name, :author)
|
48
53
|
end
|
49
54
|
|
50
55
|
should "only search across the given column" do
|
@@ -53,5 +58,4 @@ class SearchableTest < Test::Unit::TestCase
|
|
53
58
|
end
|
54
59
|
end
|
55
60
|
end
|
56
|
-
|
57
61
|
end
|
data/spec/texticle_spec.rb
CHANGED
@@ -1,25 +1,14 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
require 'spec_helper'
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
# string :title
|
7
|
-
|
8
|
-
def to_s
|
9
|
-
"#{system}: #{title}"
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class NotThere < ActiveRecord::Base
|
14
|
-
|
15
|
-
end
|
3
|
+
require 'fixtures/webcomic'
|
4
|
+
require 'fixtures/character'
|
5
|
+
require 'fixtures/game'
|
16
6
|
|
17
7
|
class TexticleTest < Test::Unit::TestCase
|
18
|
-
|
19
8
|
context "after extending ActiveRecord::Base" do
|
20
|
-
|
21
|
-
|
22
|
-
end
|
9
|
+
# before(:all)
|
10
|
+
ActiveRecord::Base.extend(Texticle)
|
11
|
+
class NotThere < ActiveRecord::Base; end
|
23
12
|
|
24
13
|
should "not break #respond_to?" do
|
25
14
|
assert_nothing_raised do
|
@@ -35,31 +24,85 @@ class TexticleTest < Test::Unit::TestCase
|
|
35
24
|
end
|
36
25
|
|
37
26
|
should "not break #method_missing" do
|
27
|
+
assert_raise(NoMethodError) { ActiveRecord::Base.random }
|
38
28
|
begin
|
39
29
|
ActiveRecord::Base.random
|
40
30
|
rescue NoMethodError => error
|
41
31
|
assert_match error.message, /undefined method `random'/
|
42
32
|
end
|
43
33
|
end
|
34
|
+
|
35
|
+
should "not break #method_missing for table-less classes" do
|
36
|
+
assert !NotThere.table_exists?
|
37
|
+
assert_raise(NoMethodError) { NotThere.random }
|
38
|
+
begin
|
39
|
+
NotThere.random
|
40
|
+
rescue NoMethodError => error
|
41
|
+
assert_match error.message, /undefined method `random'/
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when finding models based on searching a related model" do
|
46
|
+
setup do
|
47
|
+
@qc = WebComic.create :name => "Questionable Content", :author => "Jeph Jaques"
|
48
|
+
@jw = WebComic.create :name => "Johnny Wander", :author => "Ananth & Yuko"
|
49
|
+
@pa = WebComic.create :name => "Penny Arcade", :author => "Tycho & Gabe"
|
50
|
+
|
51
|
+
@gabe = @pa.characters.create :name => 'Gabe', :description => 'the simple one'
|
52
|
+
@tycho = @pa.characters.create :name => 'Tycho', :description => 'the wordy one'
|
53
|
+
@div = @pa.characters.create :name => 'Div', :description => 'a crude divx player with anger management issues'
|
54
|
+
|
55
|
+
@martin = @qc.characters.create :name => 'Martin', :description => 'the insecure protagonist'
|
56
|
+
@faye = @qc.characters.create :name => 'Faye', :description => 'a sarcastic barrista with anger management issues'
|
57
|
+
@pintsize = @qc.characters.create :name => 'Pintsize', :description => 'a crude AnthroPC'
|
58
|
+
|
59
|
+
@ananth = @jw.characters.create :name => 'Ananth', :description => 'Stubble! What is under that hat?!?'
|
60
|
+
@yuko = @jw.characters.create :name => 'Yuko', :description => 'So... small. Carl Sagan haircut.'
|
61
|
+
@john = @jw.characters.create :name => 'John', :description => 'Tall. Anger issues?'
|
62
|
+
@cricket = @jw.characters.create :name => 'Cricket', :description => 'Chirrup!'
|
63
|
+
end
|
64
|
+
|
65
|
+
teardown do
|
66
|
+
WebComic.delete_all
|
67
|
+
Character.delete_all
|
68
|
+
end
|
69
|
+
|
70
|
+
should "look in the related model with nested searching syntax" do
|
71
|
+
assert_equal [@jw], WebComic.joins(:characters).search(:characters => {:description => 'tall'})
|
72
|
+
assert_equal [@pa, @jw, @qc].sort, WebComic.joins(:characters).search(:characters => {:description => 'anger'}).sort
|
73
|
+
assert_equal [@pa, @qc].sort, WebComic.joins(:characters).search(:characters => {:description => 'crude'}).sort
|
74
|
+
end
|
75
|
+
end
|
44
76
|
end
|
45
77
|
|
46
78
|
context "after extending an ActiveRecord::Base subclass" do
|
79
|
+
# before(:all)
|
80
|
+
class ::GameFail < Game; end
|
81
|
+
|
47
82
|
setup do
|
48
|
-
Game.
|
49
|
-
@
|
50
|
-
@
|
51
|
-
@
|
52
|
-
@
|
53
|
-
@
|
54
|
-
@
|
55
|
-
@
|
56
|
-
@takun = Game.create :system => "Saturn", :title => "Magical Tarurūto-kun"
|
83
|
+
@zelda = Game.create :system => "NES", :title => "Legend of Zelda", :description => "A Link to the Past."
|
84
|
+
@mario = Game.create :system => "NES", :title => "Super Mario Bros.", :description => "The original platformer."
|
85
|
+
@sonic = Game.create :system => "Genesis", :title => "Sonic the Hedgehog", :description => "Spiky."
|
86
|
+
@dkong = Game.create :system => "SNES", :title => "Diddy's Kong Quest", :description => "Donkey Kong Country 2"
|
87
|
+
@megam = Game.create :system => nil, :title => "Mega Man", :description => "Beware Dr. Brain"
|
88
|
+
@sfnes = Game.create :system => "SNES", :title => "Street Fighter 2", :description => "Yoga Flame!"
|
89
|
+
@sfgen = Game.create :system => "Genesis", :title => "Street Fighter 2", :description => "Yoga Flame!"
|
90
|
+
@takun = Game.create :system => "Saturn", :title => "Magical Tarurūto-kun", :description => "カッコイイ!"
|
57
91
|
end
|
58
92
|
|
59
93
|
teardown do
|
60
94
|
Game.delete_all
|
61
95
|
end
|
62
96
|
|
97
|
+
should "not break respond_to? when connection is unavailable" do
|
98
|
+
GameFail.establish_connection({:adapter => :postgresql, :database =>'unavailable', :username=>'bad', :pool=>5, :timeout=>5000}) rescue nil
|
99
|
+
|
100
|
+
assert_nothing_raised do
|
101
|
+
GameFail.respond_to?(:search)
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
63
106
|
should "define a #search method" do
|
64
107
|
assert Game.respond_to?(:search)
|
65
108
|
end
|
@@ -108,6 +151,10 @@ class TexticleTest < Test::Unit::TestCase
|
|
108
151
|
should "scope consecutively" do
|
109
152
|
assert_equal [@sfgen], Game.search(:system => "Genesis").search(:title => "Street Fighter")
|
110
153
|
end
|
154
|
+
|
155
|
+
should "cast non-:string columns as text" do
|
156
|
+
assert_equal [@mario], Game.search(:id => @mario.id)
|
157
|
+
end
|
111
158
|
end
|
112
159
|
|
113
160
|
context "when using dynamic search methods" do
|
@@ -116,10 +163,15 @@ class TexticleTest < Test::Unit::TestCase
|
|
116
163
|
assert_equal [@takun], Game.search_by_system("Saturn")
|
117
164
|
end
|
118
165
|
|
119
|
-
should "generate methods for
|
166
|
+
should "generate methods for each :text column" do
|
167
|
+
assert_equal [@mario], Game.search_by_description("platform")
|
168
|
+
end
|
169
|
+
|
170
|
+
should "generate methods for any combination of :string and :text columns" do
|
120
171
|
assert_equal [@mario], Game.search_by_title_and_system("Mario", "NES")
|
121
172
|
assert_equal [@sonic], Game.search_by_system_and_title("Genesis", "Sonic")
|
122
173
|
assert_equal [@mario], Game.search_by_title_and_title("Mario", "Mario")
|
174
|
+
assert_equal [@megam], Game.search_by_title_and_description("Man", "Brain")
|
123
175
|
end
|
124
176
|
|
125
177
|
should "generate methods for inclusive searches" do
|
@@ -130,8 +182,8 @@ class TexticleTest < Test::Unit::TestCase
|
|
130
182
|
assert_equal [@sfgen], Game.search_by_system("Genesis").search_by_title("Street Fighter")
|
131
183
|
end
|
132
184
|
|
133
|
-
should "
|
134
|
-
|
185
|
+
should "generate methods for non-:string columns" do
|
186
|
+
assert_equal [@mario], Game.search_by_id(@mario.id)
|
135
187
|
end
|
136
188
|
|
137
189
|
should "work with #respond_to?" do
|
@@ -140,8 +192,8 @@ class TexticleTest < Test::Unit::TestCase
|
|
140
192
|
assert Game.respond_to?(:search_by_system_and_title)
|
141
193
|
assert Game.respond_to?(:search_by_system_or_title)
|
142
194
|
assert Game.respond_to?(:search_by_title_and_title_and_title)
|
195
|
+
assert Game.respond_to?(:search_by_id)
|
143
196
|
|
144
|
-
assert !Game.respond_to?(:search_by_id)
|
145
197
|
assert !Game.respond_to?(:search_by_title_and_title_or_title)
|
146
198
|
end
|
147
199
|
|
@@ -160,24 +212,20 @@ class TexticleTest < Test::Unit::TestCase
|
|
160
212
|
end
|
161
213
|
|
162
214
|
context "when setting a custom search language" do
|
215
|
+
def Game.searchable_language
|
216
|
+
'spanish'
|
217
|
+
end
|
218
|
+
|
163
219
|
setup do
|
164
|
-
def Game.searchable_language
|
165
|
-
'spanish'
|
166
|
-
end
|
167
220
|
Game.create :system => "PS3", :title => "Harry Potter & the Deathly Hallows"
|
168
221
|
end
|
169
222
|
|
170
223
|
teardown do
|
171
|
-
def Game.searchable_language
|
172
|
-
'english'
|
173
|
-
end
|
174
224
|
Game.delete_all
|
175
225
|
end
|
176
226
|
|
177
227
|
should "still find results" do
|
178
228
|
assert_not_empty Game.search_by_title("harry")
|
179
|
-
p
|
180
229
|
end
|
181
230
|
end
|
182
|
-
|
183
231
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: texticle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,42 +10,63 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2011-
|
14
|
-
default_executable:
|
13
|
+
date: 2011-08-30 00:00:00.000000000 Z
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
16
|
name: pg
|
18
|
-
requirement: &
|
17
|
+
requirement: &70337748621180 !ruby/object:Gem::Requirement
|
19
18
|
none: false
|
20
19
|
requirements:
|
21
|
-
- -
|
20
|
+
- - ~>
|
22
21
|
- !ruby/object:Gem::Version
|
23
22
|
version: 0.11.0
|
24
23
|
type: :development
|
25
24
|
prerelease: false
|
26
|
-
version_requirements: *
|
25
|
+
version_requirements: *70337748621180
|
27
26
|
- !ruby/object:Gem::Dependency
|
28
27
|
name: shoulda
|
29
|
-
requirement: &
|
28
|
+
requirement: &70337748620400 !ruby/object:Gem::Requirement
|
30
29
|
none: false
|
31
30
|
requirements:
|
32
|
-
- -
|
31
|
+
- - ~>
|
33
32
|
- !ruby/object:Gem::Version
|
34
33
|
version: 2.11.3
|
35
34
|
type: :development
|
36
35
|
prerelease: false
|
37
|
-
version_requirements: *
|
36
|
+
version_requirements: *70337748620400
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rake
|
39
|
+
requirement: &70337748619540 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 0.8.0
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *70337748619540
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: ruby-debug19
|
50
|
+
requirement: &70337748618760 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 0.11.6
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *70337748618760
|
38
59
|
- !ruby/object:Gem::Dependency
|
39
60
|
name: activerecord
|
40
|
-
requirement: &
|
61
|
+
requirement: &70337748617780 !ruby/object:Gem::Requirement
|
41
62
|
none: false
|
42
63
|
requirements:
|
43
|
-
- -
|
64
|
+
- - ~>
|
44
65
|
- !ruby/object:Gem::Version
|
45
|
-
version: 3.0
|
66
|
+
version: '3.0'
|
46
67
|
type: :runtime
|
47
68
|
prerelease: false
|
48
|
-
version_requirements: *
|
69
|
+
version_requirements: *70337748617780
|
49
70
|
description: ! "Texticle exposes full text search capabilities from PostgreSQL, extending\n
|
50
71
|
\ ActiveRecord with scopes making search easy and fun!"
|
51
72
|
email:
|
@@ -68,7 +89,6 @@ files:
|
|
68
89
|
- spec/texticle_spec.rb
|
69
90
|
- spec/texticle/searchable_spec.rb
|
70
91
|
- spec/config.yml
|
71
|
-
has_rdoc: true
|
72
92
|
homepage: http://tenderlove.github.com/texticle
|
73
93
|
licenses: []
|
74
94
|
post_install_message:
|
@@ -91,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
111
|
version: '0'
|
92
112
|
requirements: []
|
93
113
|
rubyforge_project: texticle
|
94
|
-
rubygems_version: 1.
|
114
|
+
rubygems_version: 1.8.10
|
95
115
|
signing_key:
|
96
116
|
specification_version: 3
|
97
117
|
summary: Texticle exposes full text search capabilities from PostgreSQL
|