make-text-search 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -110,4 +110,5 @@ The query language is the same used by PostgreSQL. See http://www.postgresql.org
110
110
 
111
111
  * Query builder. Add & and | operators
112
112
  * Option :language in #search_text
113
+ * In PostgreSQL, use ts_headline and ts_rank
113
114
  * RDoc-ize methods
@@ -4,6 +4,7 @@ module MakeTextSearch
4
4
  require 'make-text-search/models'
5
5
  require 'make-text-search/schema'
6
6
  require 'make-text-search/filters'
7
+ require 'make-text-search/document'
7
8
 
8
9
  include ModelHelpers
9
10
  class ActiveRecord::ConnectionAdapters::AbstractAdapter; include ConnectionAdapterHelpers; end
@@ -19,11 +19,10 @@ module MakeTextSearch
19
19
  # Schema actions
20
20
 
21
21
  def create_text_search_documents_table(table_name)
22
- connection.execute %[CREATE TABLE #{table_name} (record_type varchar(300) NOT NULL, record_id integer NOT NULL, language varchar(20), document tsvector)]
22
+ connection.execute %[CREATE TABLE #{table_name} (id serial primary key, record_type varchar(300) NOT NULL, record_id integer NOT NULL, language varchar(20), document tsvector)]
23
23
  connection.execute %[CREATE INDEX #{table_name}_idx ON #{table_name} USING gin(document)]
24
24
  end
25
25
 
26
-
27
26
  # Document actions
28
27
 
29
28
  def quote(value)
@@ -35,44 +34,27 @@ module MakeTextSearch
35
34
  record_class = record.class
36
35
  return if record_class.text_search_fields.empty?
37
36
 
38
- table_name = Rails.application.config.make_text_search.table_name
39
- record_type = quote record_class.name
40
- record_id = quote record.id
41
- language = record.text_search_language
42
-
43
- # If language is nil the tsvector will be generated without language
44
- document = "to_tsvector(#{language ? quote(language.to_s) + ", " : ""}#{quote record.text_search_build_document})"
45
-
46
- # Reduce the number of operations in the index using SELECT+UPDATE instead of DELETE+INSERT
47
- if connection.select_value("SELECT count(*) FROM #{table_name} WHERE #{_where_record record}").to_i == 0
48
- connection.insert(%[INSERT INTO #{table_name}
49
- (record_type, record_id, language, document)
50
- VALUES
51
- (#{record_type}, #{record_id}, #{quote language}, #{document})])
52
- else
53
- connection.update(%[UPDATE #{table_name} SET document = #{document} WHERE #{_where_record record}])
37
+ record_type, record_id = record_class.text_search_class_name, record.id
38
+ unless document = Document.find_by_record_type_and_record_id(record_type, record_id)
39
+ document = Document.new
40
+ document.record = record
41
+ document.save!
54
42
  end
55
- end
56
43
 
57
- def remove_document(record)
58
- connection.delete "DELETE FROM #{Rails.application.config.make_text_search.table_name} WHERE #{_where_record record}"
44
+ language = record.text_search_language
45
+ quoted_language = record.connection.quote(language)
46
+ ts_vector = "to_tsvector(#{language ? "#{quoted_language}, " : ""}#{record.connection.quote record.text_search_build_document})"
47
+ Document.update_all "language = #{quoted_language}, document = #{ts_vector}", ["id = ?", document.id]
59
48
  end
60
49
 
61
- def _where_record(record)
62
- "record_type = #{quote record.class.name} AND record_id = #{quote record.id}"
50
+ def remove_document(record)
51
+ Document.delete_all ["record_type = ? AND record_id = ?", record.class.text_search_class_name, record.id]
63
52
  end
64
53
 
65
-
66
54
  # Query actions
67
55
  def scope_search_text(model, query, language = Rails.application.config.make_text_search.default_language)
68
- db_connection = model.connection
69
-
70
- if language
71
- query = "to_tsquery(#{db_connection.quote language}, #{db_connection.quote query})"
72
- else
73
- query = "to_tsquery(#{db_connection.quote query})"
74
- end
75
- model.where %[#{model.table_name}.id IN (SELECT record_id FROM #{Rails.application.config.make_text_search.table_name} WHERE record_type = #{db_connection.quote model.name} AND document @@ #{query})]
56
+ document_query = Document.select("record_id").where("record_type = :type AND document @@ to_tsquery(#{language ? ":language, " : ""}:query)", :type => model.text_search_class_name, :language => language, :query => query)
57
+ model.where %[#{model.table_name}.id IN (#{document_query.to_sql})]
76
58
  end
77
59
 
78
60
  end
@@ -0,0 +1,7 @@
1
+ module MakeTextSearch
2
+ class Document < ActiveRecord::Base
3
+ set_table_name { Rails.application.config.make_text_search.table_name }
4
+
5
+ belongs_to :record, :polymorphic => true
6
+ end
7
+ end
@@ -28,16 +28,26 @@ module MakeTextSearch
28
28
  def search_text(query)
29
29
  connection.text_search_adapter.scope_search_text(self, query)
30
30
  end
31
+
32
+ def text_search_class_name
33
+ klass = self
34
+ while klass and klass.superclass != ActiveRecord::Base
35
+ klass = klass.superclass
36
+ break
37
+ end
38
+
39
+ klass and klass.name
40
+ end
31
41
  end
32
42
 
33
43
  def text_search_update_document
34
- if not self.class.text_search_fields.empty?
44
+ if not self.class.text_search_fields.blank?
35
45
  self.class.connection.text_search_adapter.update_document self
36
46
  end
37
47
  end
38
48
 
39
49
  def text_search_remove_document
40
- if not self.class.text_search_fields.empty?
50
+ if not self.class.text_search_fields.blank?
41
51
  self.class.connection.text_search_adapter.remove_document self
42
52
  end
43
53
  end
data/test/app_template.rb CHANGED
@@ -12,14 +12,25 @@ gem "make-text-search", :path => ENV["MTS_GEM_PATH"]
12
12
 
13
13
  generate "text_search:migration"
14
14
  generate "model", "Post", "title:string", "content:text"
15
+ generate "model", "User", "name:string", "description:text", "type:string"
15
16
 
16
17
  File.open("app/models/post.rb", "a") do |f|
17
18
  f.puts "\nPost.has_text_search :title, :filter => :substrings"
18
19
  f.puts "Post.has_text_search :content, :filter => [:substrings, :strip_html]"
19
20
  end
20
21
 
22
+ File.open("app/models/user.rb", "a") do |f|
23
+ f.puts "\nUser.has_text_search :name, :description"
24
+ end
25
+
26
+ File.open("app/models/admin.rb", "w") do |f|
27
+ f.puts "class Admin < User\nend"
28
+ end
29
+
21
30
  # Copy tests from the gem
22
31
  Dir["#{ENV["MTS_GEM_PATH"]}/test/*_test.rb"].each do |filename|
23
32
  file "test/unit/#{File.basename filename}", File.read(filename)
24
33
  end
25
34
 
35
+ File.unlink "test/fixtures/posts.yml"
36
+ File.unlink "test/fixtures/users.yml"
data/test/basics_test.rb CHANGED
@@ -62,4 +62,13 @@ class BasicsTest < ActiveSupport::TestCase
62
62
  end
63
63
  end
64
64
 
65
+ test "STI classes save the top parent" do
66
+ Admin.create :name => "first admin", :description => "the first user created"
67
+ assert_equal 1, User.count
68
+ assert_equal "first admin", User.first.name
69
+
70
+ assert_equal 1, User.search_text("first & created").count
71
+ assert_equal User.first, Admin.search_text("first & created").first
72
+ end
73
+
65
74
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: make-text-search
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ayose Cazorla
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-10-13 00:00:00 +01:00
18
+ date: 2011-02-14 00:00:00 +00:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -33,9 +33,10 @@ files:
33
33
  - lib/generators/migration.rb
34
34
  - lib/make-text-search/html_entities.dat
35
35
  - lib/make-text-search/filters.rb
36
- - lib/make-text-search/models.rb
37
36
  - lib/make-text-search/adapters/postgresql_ts.rb
38
37
  - lib/make-text-search/schema.rb
38
+ - lib/make-text-search/document.rb
39
+ - lib/make-text-search/models.rb
39
40
  - test/schema_test.rb
40
41
  - test/app_template.rb
41
42
  - test/basics_test.rb