tsearch 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,66 @@
1
+ grammar TQuery
2
+ rule query
3
+ space expression more_query? space <QueryNode>
4
+ end
5
+
6
+ rule more_query
7
+ space query space <QueryNode>
8
+ end
9
+
10
+ rule expression
11
+ term+ space more:more_expression? <ExpressionNode>
12
+ end
13
+
14
+ rule more_expression
15
+ space expression <ExpressionNode>
16
+ end
17
+
18
+ rule grouped_term
19
+ '(' term+ ')' <GroupedTermNode>
20
+ end
21
+
22
+ # TODO support single or double quotes
23
+ rule quoted_term
24
+ '"' quoted_stuff:[^\"]* '"' <QuotedTermNode>
25
+ end
26
+
27
+ rule term
28
+ space (boolean_term / quoted_term / word / grouped_term) space <TermNode>
29
+ end
30
+
31
+ rule word
32
+ word_char+ <WordNode>
33
+ end
34
+
35
+ rule word_char
36
+ letter / digit / '_' / '&' / '.' / '!'
37
+ end
38
+
39
+ rule letter
40
+ [A-Za-z]
41
+ end
42
+
43
+ rule digit
44
+ [0-9]
45
+ end
46
+
47
+ rule space
48
+ [\s]*
49
+ end
50
+
51
+ rule boolean_term
52
+ and_term / or_term
53
+ end
54
+
55
+ rule and_term
56
+ ('and' / '&&') term <AndTermNode>
57
+ end
58
+
59
+ rule or_term
60
+ ('or' / '||') term <OrTermNode>
61
+ end
62
+
63
+ #rule not_term
64
+ # '!' term <NotTermNode>
65
+ #end
66
+ end
@@ -0,0 +1,3 @@
1
+ require 'texticle'
2
+
3
+ ActiveRecord::Base.extend(Texticle)
@@ -0,0 +1,43 @@
1
+ require "test/unit"
2
+ require "texticle"
3
+
4
+ class TexticleTestCase < Test::Unit::TestCase
5
+ unless RUBY_VERSION >= '1.9'
6
+ undef :default_test
7
+ end
8
+
9
+ def setup
10
+ warn "#{name}" if ENV['TESTOPTS'] == '-v'
11
+ end
12
+
13
+ def fake_model
14
+ Class.new do
15
+ @connected = false
16
+ @executed = []
17
+ @named_scopes = []
18
+
19
+ class << self
20
+ attr_accessor :connected, :executed, :named_scopes
21
+
22
+ def connection
23
+ @connected = true
24
+ self
25
+ end
26
+
27
+ def execute sql
28
+ @executed << sql
29
+ end
30
+
31
+ def table_name; 'fake_model'; end
32
+
33
+ def named_scope *args
34
+ @named_scopes << args
35
+ end
36
+
37
+ def quote thing
38
+ "'#{thing}'"
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,74 @@
1
+ require 'helper'
2
+
3
+ class TestFullTextIndex < TexticleTestCase
4
+ def setup
5
+ super
6
+ @fm = fake_model
7
+ end
8
+
9
+ def test_initialize
10
+ fti = Texticle::FullTextIndex.new('ft_index', 'english', @fm) do
11
+ name
12
+ value 'A'
13
+ end
14
+ assert_equal 'name', fti.index_columns['none'].first
15
+ assert_equal 'value', fti.index_columns['A'].first
16
+ end
17
+
18
+ def test_destroy
19
+ fti = Texticle::FullTextIndex.new('ft_index', 'english', @fm) do
20
+ name
21
+ value 'A'
22
+ end
23
+ fti.destroy
24
+ assert @fm.connected
25
+ assert_equal 1, @fm.executed.length
26
+ executed = @fm.executed.first
27
+ assert_match "DROP index IF EXISTS #{fti.instance_variable_get(:@name)}", executed
28
+ end
29
+
30
+ def test_create
31
+ fti = Texticle::FullTextIndex.new('ft_index', 'english', @fm) do
32
+ name
33
+ value 'A'
34
+ end
35
+ fti.create
36
+ assert @fm.connected
37
+ assert_equal 1, @fm.executed.length
38
+ executed = @fm.executed.first
39
+ assert_match fti.to_s, executed
40
+ assert_match "CREATE index #{fti.instance_variable_get(:@name)}", executed
41
+ assert_match "ON #{@fm.table_name}", executed
42
+ end
43
+
44
+ def test_to_s_no_weight
45
+ fti = Texticle::FullTextIndex.new('ft_index', 'english', @fm) do
46
+ name
47
+ end
48
+ assert_equal "to_tsvector('english', coalesce(#{@fm.table_name}.name, ''))", fti.to_s
49
+ end
50
+
51
+ def test_to_s_A_weight
52
+ fti = Texticle::FullTextIndex.new('ft_index', 'english', @fm) do
53
+ name 'A'
54
+ end
55
+ assert_equal "setweight(to_tsvector('english', coalesce(#{@fm.table_name}.name, '')), 'A')", fti.to_s
56
+ end
57
+
58
+ def test_to_s_multi_weight
59
+ fti = Texticle::FullTextIndex.new('ft_index', 'english', @fm) do
60
+ name 'A'
61
+ value 'A'
62
+ description 'B'
63
+ end
64
+ assert_equal "setweight(to_tsvector('english', coalesce(#{@fm.table_name}.name, '') || ' ' || coalesce(#{@fm.table_name}.value, '')), 'A') || ' ' || setweight(to_tsvector('english', coalesce(#{@fm.table_name}.description, '')), 'B')", fti.to_s
65
+ end
66
+
67
+ def test_mixed_weight
68
+ fti = Texticle::FullTextIndex.new('ft_index', 'english', @fm) do
69
+ name
70
+ value 'A'
71
+ end
72
+ assert_equal "setweight(to_tsvector('english', coalesce(#{@fm.table_name}.value, '')), 'A') || ' ' || to_tsvector('english', coalesce(#{@fm.table_name}.name, ''))", fti.to_s
73
+ end
74
+ end
@@ -0,0 +1,60 @@
1
+ require 'helper'
2
+
3
+ class TestTexticle < TexticleTestCase
4
+ def test_index_method
5
+ x = fake_model
6
+ x.class_eval do
7
+ extend Texticle
8
+ index do
9
+ name
10
+ end
11
+ end
12
+ assert_equal 1, x.full_text_indexes.length
13
+ assert_equal 1, x.named_scopes.length
14
+
15
+ x.full_text_indexes.first.create
16
+ assert_match "#{x.table_name}_fts_idx", x.executed.first
17
+ assert_equal :search, x.named_scopes.first.first
18
+ end
19
+
20
+ def test_named_index
21
+ x = fake_model
22
+ x.class_eval do
23
+ extend Texticle
24
+ index('awesome') do
25
+ name
26
+ end
27
+ end
28
+ assert_equal 1, x.full_text_indexes.length
29
+ assert_equal 1, x.named_scopes.length
30
+
31
+ x.full_text_indexes.first.create
32
+ assert_match "#{x.table_name}_awesome_fts_idx", x.executed.first
33
+ assert_equal :search_awesome, x.named_scopes.first.first
34
+ end
35
+
36
+ def test_named_scope_select
37
+ x = fake_model
38
+ x.class_eval do
39
+ extend Texticle
40
+ index('awesome') do
41
+ name
42
+ end
43
+ end
44
+ ns = x.named_scopes.first[1].call('foo')
45
+ assert_match(/^#{x.table_name}\.\*/, ns[:select])
46
+ end
47
+
48
+ def test_double_quoted_queries
49
+ x = fake_model
50
+ x.class_eval do
51
+ extend Texticle
52
+ index('awesome') do
53
+ name
54
+ end
55
+ end
56
+
57
+ ns = x.named_scopes.first[1].call('foo bar "foo bar"')
58
+ assert_match(/'foo' & 'bar' & 'foo bar'/, ns[:select])
59
+ end
60
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tsearch
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 5
9
+ version: 1.0.5
10
+ platform: ruby
11
+ authors:
12
+ - David Harding
13
+ autorequire: texticle
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-18 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Provides easy access to PostgreSQL's tsearch full text search for your ActiveRecord models using named scopes
22
+ email: david@metalogik.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - rails/init.rb
31
+ - lib/texticle/full_text_index.rb
32
+ - lib/texticle/nodes/and_term_node.rb
33
+ - lib/texticle/nodes/boolean_term_node.rb
34
+ - lib/texticle/nodes/expression_node.rb
35
+ - lib/texticle/nodes/grouped_term_node.rb
36
+ - lib/texticle/nodes/not_term_node.rb
37
+ - lib/texticle/nodes/or_term_node.rb
38
+ - lib/texticle/nodes/query_node.rb
39
+ - lib/texticle/nodes/quoted_term_node.rb
40
+ - lib/texticle/nodes/term_node.rb
41
+ - lib/texticle/nodes/word_node.rb
42
+ - lib/texticle/parser.rb
43
+ - lib/texticle/tasks.rb
44
+ - lib/texticle/tquery.rb
45
+ - lib/texticle.rb
46
+ - test/helper.rb
47
+ - test/test_full_text_index.rb
48
+ - test/test_texticle.rb
49
+ - lib/texticle/tquery.treetop
50
+ has_rdoc: true
51
+ homepage: http://github.com/dharding/texticle
52
+ licenses: []
53
+
54
+ post_install_message:
55
+ rdoc_options: []
56
+
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ requirements: []
74
+
75
+ rubyforge_project: tsearch
76
+ rubygems_version: 1.3.6
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: Provides easy access to PostgreSQL's tsearch full text search for your ActiveRecord models
80
+ test_files: []
81
+