public
Description: Ambition adapter for Sphinx
Clone URL: git://github.com/technicalpickles/ambitious-sphinx.git
Search Repo:
Merged in from paging branch.
Fri Feb 29 16:26:04 -0800 2008
commit  2414d0c29ce705ff193d2e5b63c9e4f5493b8fa7
tree    b576d7b9c8822cdacc93cee307971186bfee18b2
parent  2f1350285f55c6ea69b6dae00294d14fc183a1da parent  753416af4550d0bc834f7891526e128d16c116d6
...
 
 
 
1
 
2
3
4
5
6
7
 
8
9
10
11
12
13
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
0
@@ -1,14 +1,18 @@
0
+ambitious-sphinx.gemspec
0
+config/ultrasphinx/default.base
0
+config/ultrasphinx/development.conf
0
 lib/ambition/adapters/ambitious_sphinx/base.rb
0
+lib/ambition/adapters/ambitious_sphinx/page.rb
0
 lib/ambition/adapters/ambitious_sphinx/query.rb
0
 lib/ambition/adapters/ambitious_sphinx/select.rb
0
 lib/ambition/adapters/ambitious_sphinx/slice.rb
0
 lib/ambition/adapters/ambitious_sphinx/sort.rb
0
 lib/ambition/adapters/ambitious_sphinx.rb
0
 LICENSE
0
+Manifest
0
 README
0
 test/helper.rb
0
 test/select_test.rb
0
 test/slice_test.rb
0
 test/sort_test.rb
0
-Manifest
...
1
2
3
 
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 
 
 
 
 
 
 
 
 
26
27
...
 
1
2
3
4
5
6
7
8
 
 
 
 
 
9
 
 
 
 
 
 
 
 
 
 
 
10
11
12
13
14
15
16
17
18
19
20
0
@@ -1,28 +1,21 @@
0
-
0
 require 'ambition'
0
 
0
+# stub out rails stuff enough so that ultrasphinx will be happy
0
 RAILS_ROOT = "./" unless defined? RAILS_ROOT
0
 RAILS_ENV = "development" unless defined? RAILS_ENV
0
 
0
 require 'active_record'
0
 require 'ultrasphinx'
0
-require 'ambition/adapters/ambitious_sphinx/base'
0
-require 'ambition/adapters/ambitious_sphinx/query'
0
-require 'ambition/adapters/ambitious_sphinx/select'
0
-require 'ambition/adapters/ambitious_sphinx/sort'
0
-require 'ambition/adapters/ambitious_sphinx/slice'
0
 
0
-##
0
-# This is where you inject Ambition into your target.
0
-#
0
-# Use `extend' if you are injecting a class, `include' if you are
0
-# injecting instances of that class.
0
-#
0
-# You must also set the `ambition_adapter' class variable on your target
0
-# class, regardless of whether you are injecting instances or the class itself.
0
-#
0
-# You probably want something like this:
0
-#
0
+module Ambition::Adapters
0
+ module AmbitiousSphinx
0
+ end
0
+end
0
+
0
+%w(base page query select sort slice).each do |f|
0
+ require "ambition/adapters/ambitious_sphinx/#{f}"
0
+end
0
+
0
 ActiveRecord::Base.extend Ambition::API
0
 ActiveRecord::Base.ambition_adapter = Ambition::Adapters::AmbitiousSphinx
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
33
34
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
0
@@ -1,34 +1,28 @@
0
-module Ambition #:nodoc:
0
- module Adapters #:nodoc:
0
- module AmbitiousSphinx #:nodoc:
0
- class Base
0
- # Does the string contain a field (in terms of Ultrasphinx's querying).
0
- # This is basically checking for a colon. Typically, you'd see something like:
0
- #
0
- # name:"some search terms"
0
- def has_field? str
0
- str =~ /:/
0
- end
0
-
0
- # Does the string contain a query operator? This includes AND, OR, and NOT.
0
- def has_operator? str
0
- str =~ /(AND|OR|NOT)/
0
- end
0
-
0
- # Does the string need to be quoted? It needs to be quoted unless it doesn't
0
- # have an operator or field.
0
- def needs_quoting? str
0
- not (has_operator?(str) or has_field?(str))
0
- end
0
-
0
- # Add quotes to the string if it needs it.
0
- def quotify str
0
- if needs_quoting?(str)
0
- %Q("#{str}")
0
- else
0
- str
0
- end
0
- end
0
+module Ambition::Adapters::AmbitiousSphinx
0
+ # Helper for the other
0
+ class Base
0
+ # Does the string have an Ultrasphinx field?
0
+ def has_field? str
0
+ str =~ /:/
0
+ end
0
+
0
+ # Does the string have any Ultrasphinx operators?
0
+ def has_operator? str
0
+ str =~ /(AND|OR|NOT)/
0
+ end
0
+
0
+ # Should this string be quotified? It needs to happen if the string doesn't
0
+ # have an operator or a field.
0
+ def needs_quoting? str
0
+ not (has_operator?(str) or has_field?(str))
0
+ end
0
+
0
+ # Quote the string if it needs it.
0
+ def quotify str
0
+ if needs_quoting?(str)
0
+ %Q("#{str}")
0
+ else
0
+ str
0
       end
0
     end
0
   end
...
1
2
3
4
5
6
7
8
9
 
 
 
 
 
 
 
10
11
12
13
14
 
 
 
 
 
 
 
 
 
 
 
15
16
17
18
19
 
 
 
 
 
 
 
 
20
21
22
23
24
 
 
 
 
 
 
 
 
25
26
27
 
 
28
29
30
31
32
33
34
 
 
 
 
35
36
37
...
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
 
 
 
 
9
10
11
12
13
14
15
16
17
18
19
20
 
 
 
 
21
22
23
24
25
26
27
28
29
 
 
 
 
30
31
32
33
34
35
36
37
38
 
 
39
40
41
 
 
 
 
 
 
42
43
44
45
46
47
48
0
@@ -1,37 +1,48 @@
0
-module Ambition #:nodoc:
0
- module Adapters #:nodoc:
0
- module AmbitiousSphinx #:nodoc:
0
- # Responsible for taking the clauses that Ambition has generated,
0
- # and ultimately doing a Ultrasphinx::Search based on them
0
- class Query < Base
0
- def kick
0
- Ultrasphinx::Search.new(to_hash).results
0
- end
0
+module Ambition::Adapters::AmbitiousSphinx
0
+ # Responsible for taking the clauses that Ambition has generated, and ultimately doing a
0
+ # Ultrasphinx::Search based on them
0
+ class Query < Base
0
+ def kick
0
+ Ultrasphinx::Search.new(to_hash).results
0
+ end
0
 
0
- # Not entirely sure what this is for, so unimplemented so far.
0
- def size
0
- raise "Not implemented yet."
0
- end
0
+ # Some magic to add pagination. This gets called if you were to do:
0
+ #
0
+ # Meal.select {'bacon'}.page(5)
0
+ #
0
+ # When +page+ is invoked, it's actually being invoked on +Ambition::Context+.
0
+ # It has +method_missing+? voodoo which will try to pass the method onto
0
+ # the +Query+. That's this class.
0
+ def page(number)
0
+ stash[:page] = number
0
+ context
0
+ end
0
 
0
- # Builds a hash of options for Ultrasphinx::Search based on the clauses Ambition
0
- # has generated.
0
- def to_hash
0
- hash = {}
0
+ # Not entirely sure when this is used, so unimplemented so far.
0
+ def size
0
+ raise "Not implemented yet."
0
+ end
0
+
0
+ # Builds a hash of options for Ultrasphinx::Search based on the clauses Ambition has generated.
0
+ def to_hash
0
+ hash = {}
0
 
0
- unless (query = clauses[:select]).blank?
0
- query_s = query.join(' ').squeeze(' ').strip
0
- hash[:query] = quotify(query_s)
0
- end
0
+ unless (query = clauses[:select]).blank?
0
+ query_s = query.join(' ').squeeze(' ').strip
0
+ hash[:query] = quotify(query_s)
0
+ end
0
+
0
+ unless (page = stash[:page]).blank?
0
+ hash[:page] = page
0
+ end
0
 
0
- hash
0
- end
0
+ hash
0
+ end
0
 
0
- # Prints out the query that would be executed.
0
- def to_s
0
- hash = to_hash
0
- hash[:query]
0
- end
0
- end
0
+ # Prints out the query that would be executed.
0
+ def to_s
0
+ hash = to_hash
0
+ hash[:query]
0
     end
0
   end
0
 end
...
1
2
3
4
5
6
7
8
9
10
11
12
13
 
 
 
 
 
 
 
 
 
 
14
15
16
17
18
19
20
21
22
23
24
 
 
 
 
 
 
 
 
 
 
25
26
27
28
29
30
31
 
 
 
 
 
 
32
33
34
35
36
37
38
 
 
 
 
 
 
39
40
41
42
43
 
 
 
 
44
45
46
47
48
 
 
 
 
49
50
51
52
53
54
55
56
57
58
59
60
61
 
 
 
 
 
 
 
 
 
 
 
 
62
63
64
65
66
67
68
69
70
71
72
73
74
75
 
 
 
 
 
 
 
 
 
 
 
 
 
76
77
78
79
80
81
 
 
 
 
 
82
83
84
85
86
87
 
 
 
 
 
88
89
90
91
92
93
 
 
 
 
 
94
95
96
97
98
99
 
 
 
 
 
100
101
102
103
104
105
106
 
 
 
 
107
108
109
...
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
 
 
 
 
 
 
 
 
 
 
12
13
14
15
16
17
18
19
20
21
22
 
 
 
 
 
 
23
24
25
26
27
28
29
 
 
 
 
 
 
30
31
32
33
34
35
36
 
 
 
 
37
38
39
40
41
 
 
 
 
42
43
44
45
46
 
 
 
 
 
 
 
 
 
 
 
 
47
48
49
50
51
52
53
54
55
56
57
58
59
 
 
 
 
 
 
 
 
 
 
 
 
 
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 
 
 
 
 
74
75
76
77
78
79
 
 
 
 
 
80
81
82
83
84
85
 
 
 
 
 
86
87
88
89
90
91
 
 
 
 
 
92
93
94
95
96
97
 
 
 
 
 
 
98
99
100
101
102
103
104
0
@@ -1,109 +1,104 @@
0
-module Ambition #:nodoc:
0
- module Adapters #:nodoc:
0
- module AmbitiousSphinx #:nodoc:
0
- # Select is responsible for taking pure Ruby, and mangling it until it resembles
0
- # the syntax that Ultrasphinx[http://blog.evanweaver.com/files/doc/fauna/ultrasphinx/files/README.html] uses.
0
- class Select < Base
0
-
0
- # Handles method calls, like
0
- #
0
- # u.name
0
- def call(method)
0
- "#{method.to_s}:"
0
- end
0
+module Ambition::Adapters::AmbitiousSphinx
0
+ # Select is responsible for taking pure Ruby, and mangling it until it resembles
0
+ # the syntax that Ultrasphinx[http://blog.evanweaver.com/files/doc/fauna/ultrasphinx/files/README.html] uses.
0
+ class Select < Base
0
+ # Handles method calls, like
0
+ #
0
+ # u.name
0
+ def call(method)
0
+ "#{method.to_s}:"
0
+ end
0
 
0
- # Should we be supporting chained calls like:
0
- #
0
- # u.name.downcase
0
- #
0
- # ?
0
- #
0
- # I don't think Sphinx would be able to handle this.
0
- def chained_call(*methods)
0
- raise "Not implemented yet."
0
- end
0
+ # Should we be supporting chained calls like:
0
+ #
0
+ # u.name.downcase
0
+ #
0
+ # ?
0
+ #
0
+ # I don't think Sphinx would be able to handle this.
0
+ def chained_call(*methods)
0
+ raise "Not implemented yet."
0
+ end
0
 
0
- # Handles generating an Ultrasphinx query for code like:
0
- #
0
- # 'foo' && 'bar'
0
- def both(left, right)
0
- "#{quotify left} AND #{quotify right}"
0
- end
0
+ # Handles generating an Ultrasphinx query for code like:
0
+ #
0
+ # 'foo' && 'bar'
0
+ def both(left, right)
0
+ "#{quotify left} AND #{quotify right}"
0
+ end
0
 
0
- # Handles generating an Ultrasphinx query for code like:
0
- #
0
- # 'foo' || 'bar'
0
- def either(left, right)
0
- "#{quotify left} OR #{quotify right}"
0
- end
0
+ # Handles generating an Ultrasphinx query for code like:
0
+ #
0
+ # 'foo' || 'bar'
0
+ def either(left, right)
0
+ "#{quotify left} OR #{quotify right}"
0
+ end
0
 
0
- # Sphinx doesn't support equality.
0
- def ==(left, right)
0
- raise "Not applicable to sphinx."
0
- end
0
+ # Sphinx doesn't support equality.
0
+ def ==(left, right)
0
+ raise "Not applicable to sphinx."
0
+ end
0
 
0
- # Sphinx doesn't support inequality.
0
- def not_equal(left, right)
0
- raise "Not applicable to sphinx."
0
- end
0
+ # Sphinx doesn't support inequality.
0
+ def not_equal(left, right)
0
+ raise "Not applicable to sphinx."
0
+ end
0
 
0
- # Handles generating an Ultrasphinx query for code like:
0
- #
0
- # u.name =~ 'bob'
0
- #
0
- # Some cavaets:
0
- # * left hand side _must_ be a field, like u.name
0
- # * right hand side _must not_ be a regular expression. Pattern matching is generally not
0
- # supported by full text search engines
0
- def =~(left, right)
0
- raise if right.is_a? Regexp
0
- "#{left}#{quotify right}"
0
- end
0
+ # Handles generating an Ultrasphinx query for code like:
0
+ #
0
+ # u.name =~ 'bob'
0
+ #
0
+ # Some cavaets:
0
+ # * left hand side _must_ be a field, like u.name
0
+ # * right hand side _must not_ be a regular expression. Pattern matching is generally not
0
+ # supported by full text search engines
0
+ def =~(left, right)
0
+ raise if right.is_a? Regexp
0
+ "#{left}#{quotify right}"
0
+ end
0
 
0
- # Handles generating an Ultrasphinx query for code like:
0
- #
0
- # u.name !~ 'bob'
0
- #
0
- # Some cavaets:
0
- # * left hand side _must_ be a field, like u.name
0
- # * right hand side _must not_ be a regular expression. Pattern matching is generally not
0
- # supported by full text search engines
0
- def not_regexp(left, right)
0
- # could be DRYer, but this is more readable than: "NOT #{self.=~(left,right)}"
0
- raise if right.is_a? Regexp
0
- "NOT #{left}#{quotify right}"
0
- end
0
+ # Handles generating an Ultrasphinx query for code like:
0
+ #
0
+ # u.name !~ 'bob'
0
+ #
0
+ # Some cavaets:
0
+ # * left hand side _must_ be a field, like u.name
0
+ # * right hand side _must not_ be a regular expression. Pattern matching is generally not
0
+ # supported by full text search engines
0
+ def not_regexp(left, right)
0
+ # could be DRYer, but this is more readable than: "NOT #{self.=~(left,right)}"
0
+ raise if right.is_a? Regexp
0
+ "NOT #{left}#{quotify right}"
0
+ end
0
 
0
- # Not supported by Sphinx. If you need this kind of comparison, you probably should be
0
- # using ambitious-activerecord instead.
0
- def <(left, right)
0
- raise "Not applicable to sphinx."
0
- end
0
+ # Not supported by Sphinx. If you need this kind of comparison, you probably should be
0
+ # using ambitious-activerecord.
0
+ def <(left, right)
0
+ raise "Not applicable to sphinx."
0
+ end
0
 
0
- # Not supported by Sphinx. If you need this kind of comparison, you probably should be
0
- # using ambitious-activerecord instead.
0
- def >(left, right)
0
- raise "Not applicable to sphinx."
0
- end
0
+ # Not supported by Sphinx. If you need this kind of comparison, you probably should be
0
+ # using ambitious-activerecord.
0
+ def >(left, right)
0
+ raise "Not applicable to sphinx."
0
+ end
0
 
0
- # Not supported by Sphinx. If you need this kind of comparison, you probably should be
0
- # using ambitious-activerecord instead.
0
- def >=(left, right)
0
- raise "Not applicable to sphinx."
0
- end
0
+ # Not supported by Sphinx. If you need this kind of comparison, you probably should be
0
+ # using ambitious-activerecord.
0
+ def >=(left, right)
0
+ raise "Not applicable to sphinx."
0
+ end
0
 
0
- # Not supported by Sphinx. If you need this kind of comparison, you probably should be
0
- # using ambitious-activerecord instead.
0
- def <=(left, right)
0
- raise "Not applicable to sphinx."
0
- end
0
+ # Not supported by Sphinx. If you need this kind of comparison, you probably should be
0
+ # using ambitious-activerecord.
0
+ def <=(left, right)
0
+ raise "Not applicable to sphinx."
0
+ end
0
 
0
- # Not supported by Sphinx. If you need this kind of comparison, you probably should be
0
- # using ambitious-activerecord instead.
0
- def include?(left, right)
0
- raise "Not applicable to sphinx."
0
- end
0
- end
0
+ # Not supported by Sphinx. If you need this kind of comparison, you probably should be
0
+ # using ambitious-activerecord.
0
+ def include?(left, right)
0
+ raise "Not applicable to sphinx."
0
     end
0
   end
0
 end
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
 
 
 
 
 
15
16
17
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
0
@@ -1,17 +1,9 @@
0
-module Ambition #:nodoc:
0
- module Adapters #:nodoc:
0
- module AmbitiousSphinx #:nodoc:
0
- # Slicing would normally let you choose a 'slice' of the search results.
0
- #
0
- # We don't support it at this time because of limitations of Ultrasphinx.
0
- # It allows you to select what 'page' of results to select, but not a specific range.
0
- class Slice < Base
0
-
0
- # Not implemented.
0
- def slice(start, length)
0
- raise "Not supported by Ultrasphinx"
0
- end
0
- end
0
+module Ambition::Adapters::AmbitiousSphinx
0
+ # Slice would normally handle slicing, but we don't support it yet.
0
+ class Slice < Base
0
+ # Not implemented
0
+ def slice(start, length)
0
+ raise "Not implemented."
0
     end
0
   end
0
 end
...
1
2
3
4
5
6
7
8
9
10
 
 
 
 
 
 
 
11
12
13
14
15
 
 
 
 
16
17
18
19
20
 
 
 
 
21
22
23
24
25
 
 
 
 
26
27
28
29
30
 
 
 
 
31
32
33
34
35
36
 
 
 
37
38
39
...
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
 
 
 
 
9
10
11
12
13
 
 
 
 
14
15
16
17
18
 
 
 
 
19
20
21
22
23
 
 
 
 
24
25
26
27
28
 
 
 
 
 
29
30
31
32
33
34
0
@@ -1,39 +1,34 @@
0
-module Ambition #:nodoc:
0
- module Adapters #:nodoc:
0
- module AmbitiousSphinx #:nodoc:
0
- # Allows you to sort queries by particular fields.
0
- # It is unsure how well this is supported by Ultrasphinx.
0
- class Sort < Base
0
- # Not implemented yet.
0
- def sort_by(method)
0
- raise "Not implemented yet."
0
- end
0
+module Ambition::Adapters::AmbitiousSphinx
0
+ # +Sort+ would normally handle sorting, but we don't support it yet.
0
+ class Sort < Base
0
+ # Not implemented
0
+ def sort_by(method)
0
+ raise "Not implemented."
0
+ end
0
 
0
- # Not implemented yet.
0
- def reverse_sort_by(method)
0
- raise "Not implemented yet."
0
- end
0
+ # Not implemented
0
+ def reverse_sort_by(method)
0
+ raise "Not implemented."
0
+ end
0
 
0
- # Not implemented yet.
0
- def chained_sort_by(receiver, method)
0
- raise "Not implemented yet."
0
- end
0
+ # Not implemented
0
+ def chained_sort_by(receiver, method)
0
+ raise "Not implemented."
0
+ end
0
 
0
- # Not implemented yet.
0
- def chained_reverse_sort_by(receiver, method)
0
- raise "Not implemented yet."
0
- end
0
+ # Not implemented
0
+ def chained_reverse_sort_by(receiver, method)
0
+ raise "Not implemented."
0
+ end
0
 
0
- # Not implemented yet.
0
- def to_proc(symbol)
0
- raise "Not implemented yet."
0
- end
0
+ # Not implemented
0
+ def to_proc(symbol)
0
+ raise "Not implemented."
0
+ end
0
 
0
- # Not implemented yet.
0
- def rand
0
- raise "Not implemented yet."
0
- end
0
- end
0
+ # Not implemented
0
+ def rand
0
+ raise "Not implemented."
0
     end
0
   end
0
 end

Comments

    No one has commented yet.