ambitious-sphinx 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2007 Josh Nichols and Dan Croak
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest ADDED
@@ -0,0 +1,16 @@
1
+ ambitious-sphinx.gemspec
2
+ config/ultrasphinx/default.base
3
+ config/ultrasphinx/development.conf
4
+ lib/ambition/adapters/ambitious_sphinx/base.rb
5
+ lib/ambition/adapters/ambitious_sphinx/query.rb
6
+ lib/ambition/adapters/ambitious_sphinx/select.rb
7
+ lib/ambition/adapters/ambitious_sphinx/slice.rb
8
+ lib/ambition/adapters/ambitious_sphinx/sort.rb
9
+ lib/ambition/adapters/ambitious_sphinx.rb
10
+ LICENSE
11
+ Manifest
12
+ README
13
+ test/helper.rb
14
+ test/select_test.rb
15
+ test/slice_test.rb
16
+ test/sort_test.rb
data/README ADDED
@@ -0,0 +1,82 @@
1
+ = An Ambitious Sphinx Adapter
2
+
3
+ I don't know about you, but I like me some sexy full-text searching.
4
+
5
+ == The basics
6
+
7
+ Want to find all meals that mention bacon?
8
+
9
+ Meal.select {'bacon'}
10
+
11
+ What about bacon bits and sour cream?
12
+
13
+ Meal.select {'bacon bits' && 'sour cream'}
14
+
15
+ Maybe with bacon in the name, or cheese in the recipe?
16
+
17
+ Meal.select {|m| m.name =~ 'bacon' || m.recipe =~ 'cheese'}
18
+
19
+ Cheese in the name, but not grilled?
20
+
21
+ Meal.select {|m| m.name =~ 'bacon' && m.name !~ 'grilled'}
22
+
23
+ == Pagination
24
+
25
+ You're going to want to use pagination. Ultrasphinx, the underlying library, only supports it, as in, you can't just get all the objects matching your query. You _have_ to use paging.
26
+
27
+ It's pretty simple:
28
+
29
+ Meal.select {'bacon'}.page(2)
30
+ Meal.select {'bacon'}.page(3)
31
+
32
+ == Big honking disclaimer
33
+
34
+ We're still learning a lot about how sphinx and ambition work, so things are likely to change a lot, and features are likely to be missing.
35
+
36
+ == Getting Started
37
+
38
+
39
+ === Installing
40
+
41
+ sudo gem install ambitious-sphinx
42
+
43
+ === Add it to your app
44
+
45
+ Require our files somewhere, like at the end of config/environment.rb, maybe create config/initializers/sphinx.rb
46
+
47
+ require 'ultrasphinx'
48
+ require 'ambition/adapters/ambitious_sphinx'
49
+
50
+ === Sphinx and Ultrasphinx
51
+
52
+ You will also need to go through the motions of setting up ultrasphinx.
53
+
54
+ This includes:
55
+
56
+ * Configuring/installing sphinx
57
+ * Modifying your model to indicate what's to be indexed
58
+ * Bootstrapping ultrasphinx
59
+
60
+ All this is discussed in detail in ultrasphinx's README
61
+
62
+ == Playing with the code base
63
+
64
+ In addition to the other dependencies, you'll need to:
65
+
66
+ gem install echoe redgreen mocha test-spec
67
+
68
+ Run the tests with:
69
+
70
+ rake test
71
+
72
+
73
+ == More information on Sphinx:
74
+
75
+ -> http://www.sphinxsearch.com/
76
+ -> http://blog.evanweaver.com/articles/2007/07/09/ultrasphinx-searching-the-world-in-231-seconds/
77
+ -> http://blog.evanweaver.com/files/doc/fauna/ultrasphinx/files/README.html
78
+
79
+ == More information on Ambition:
80
+
81
+ -> http://ambition.rubyforge.org
82
+ -> http://groups.google.com/group/ambition-rb/
@@ -0,0 +1,60 @@
1
+
2
+ # Gem::Specification for Ambitious-sphinx-0.1.0
3
+ # Originally generated by Echoe
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{ambitious-sphinx}
7
+ s.version = "0.1.0"
8
+
9
+ s.specification_version = 2 if s.respond_to? :specification_version=
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.authors = ["Josh Nichols"]
13
+ s.date = %q{2008-02-29}
14
+ s.description = %q{An ambitious adapter for sphinx}
15
+ s.email = %q{josh@technicalpickles.com}
16
+ s.files = ["ambitious-sphinx.gemspec", "config/ultrasphinx/default.base", "config/ultrasphinx/development.conf", "lib/ambition/adapters/ambitious_sphinx/base.rb", "lib/ambition/adapters/ambitious_sphinx/query.rb", "lib/ambition/adapters/ambitious_sphinx/select.rb", "lib/ambition/adapters/ambitious_sphinx/slice.rb", "lib/ambition/adapters/ambitious_sphinx/sort.rb", "lib/ambition/adapters/ambitious_sphinx.rb", "LICENSE", "Manifest", "README", "test/helper.rb", "test/select_test.rb", "test/slice_test.rb", "test/sort_test.rb"]
17
+ s.has_rdoc = true
18
+ s.homepage = %q{http://ambitioussphinx.rubyforge.org/}
19
+ s.require_paths = ["lib"]
20
+ s.rubyforge_project = %q{ambitioussphinx}
21
+ s.rubygems_version = %q{1.0.0}
22
+ s.summary = %q{An ambitious adapter for sphinx}
23
+ s.test_files = ["test/select_test.rb", "test/slice_test.rb", "test/sort_test.rb"]
24
+
25
+ s.add_dependency(%q<ultrasphinx>, [">= 1.7"])
26
+ s.add_dependency(%q<ambition>, [">= 0.5.0"])
27
+ end
28
+
29
+
30
+ # # Original Rakefile source (requires the Echoe gem):
31
+ #
32
+ # require 'rake'
33
+ #
34
+ # begin
35
+ # require 'rubygems'
36
+ # gem 'echoe', '>=2.7'
37
+ # ENV['RUBY_FLAGS'] = ""
38
+ # require 'echoe'
39
+ #
40
+ # Echoe.new('ambitious-sphinx') do |p|
41
+ # p.dependencies << 'ultrasphinx >=1.7'
42
+ # p.summary = 'An ambitious adapter for sphinx'
43
+ # p.author = 'Josh Nichols'
44
+ # p.email = 'josh@technicalpickles.com'
45
+ #
46
+ # p.project = 'ambitioussphinx'
47
+ # p.url = 'http://ambitioussphinx.rubyforge.org/'
48
+ # p.test_pattern = 'test/*_test.rb'
49
+ # p.version = '0.1.0'
50
+ # p.dependencies << 'ambition >=0.5.0'
51
+ # end
52
+ #
53
+ # rescue LoadError
54
+ # puts "Not doing any of the Echoe gemmy stuff, because you don't have the specified gem versions"
55
+ # end
56
+ #
57
+ # desc 'Install as a gem'
58
+ # task :install_gem do
59
+ # puts `rake manifest package && gem install pkg/ambitious-sphinx-#{Version}.gem`
60
+ # end
@@ -0,0 +1,77 @@
1
+
2
+ #
3
+ # Sphinx/Ultrasphinx user-configurable options.
4
+ #
5
+ # Copy this file to RAILS_ROOT/config/ultrasphinx. You can use individual
6
+ # namespaces if you want (e.g. development.base, production.base,
7
+ # test.base).
8
+ #
9
+ # This file should not be handed directly to Sphinx. Use the rake task
10
+ #
11
+ # rake ultrasphinx::configure
12
+ #
13
+ # to generate a parallel default.conf file. This is the file that Sphinx itself will
14
+ # use. The Ultrasphinx rake tasks automatically pass the correct file to
15
+ # to Sphinx.
16
+ #
17
+ # It is safe to edit .base files by hand. It is not safe to edit the generated
18
+ # .conf files. Do not symlink the .conf file to the .base file! I don't know why
19
+ # people think they need to do that. It's wrong.
20
+ #
21
+
22
+ indexer
23
+ {
24
+ # Indexer running options
25
+ mem_limit = 256M
26
+ }
27
+
28
+ searchd
29
+ {
30
+ # Daemon options
31
+ # What interface the search daemon should listen on and where to store its logs
32
+ address = 0.0.0.0
33
+ port = 3312
34
+ seamless_rotate = 1
35
+ log = /tmp/sphinx/log/searchd.log
36
+ query_log = /tmp/sphinx/log/query.log
37
+ read_timeout = 5
38
+ max_children = 300
39
+ pid_file = /tmp/sphinx/log/searchd.pid
40
+ max_matches = 100000
41
+ }
42
+
43
+ client
44
+ {
45
+ # Client options
46
+ # Name of the Aspell dictionary (two letters max)
47
+ dictionary_name = ap
48
+ # How your application connects to the search daemon (not necessarily the same as above)
49
+ server_host = localhost
50
+ server_port = 3312
51
+ }
52
+
53
+ source
54
+ {
55
+ # Individual SQL source options
56
+ sql_range_step = 5000
57
+ strip_html = 0
58
+ index_html_attrs =
59
+ sql_query_post =
60
+ }
61
+
62
+ index
63
+ {
64
+ # Index building options
65
+ path = db/sphinx
66
+ docinfo = extern # just leave this alone
67
+ morphology = stem_en
68
+ stopwords = # /path/to/stopwords.txt
69
+ min_word_len = 1
70
+
71
+ # Enable these if you need wildcard searching. They will slow down indexing significantly.
72
+ # min_infix_len = 1
73
+ # enable_star = 1
74
+
75
+ charset_type = utf-8 # or sbcs (Single Byte Character Set)
76
+ charset_table = 0..9, A..Z->a..z, -, _, ., &, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F,U+C5->U+E5, U+E5, U+C4->U+E4, U+E4, U+D6->U+F6, U+F6, U+16B, U+0c1->a, U+0c4->a, U+0c9->e, U+0cd->i, U+0d3->o, U+0d4->o, U+0da->u, U+0dd->y, U+0e1->a, U+0e4->a, U+0e9->e, U+0ed->i, U+0f3->o, U+0f4->o, U+0fa->u, U+0fd->y, U+104->U+105, U+105, U+106->U+107, U+10c->c, U+10d->c, U+10e->d, U+10f->d, U+116->U+117, U+117, U+118->U+119, U+11a->e, U+11b->e, U+12E->U+12F, U+12F, U+139->l, U+13a->l, U+13d->l, U+13e->l, U+141->U+142, U+142, U+143->U+144, U+144,U+147->n, U+148->n, U+154->r, U+155->r, U+158->r, U+159->r, U+15A->U+15B, U+15B, U+160->s, U+160->U+161, U+161->s, U+164->t, U+165->t, U+16A->U+16B, U+16B, U+16e->u, U+16f->u, U+172->U+173, U+173, U+179->U+17A, U+17A, U+17B->U+17C, U+17C, U+17d->z, U+17e->z,
77
+ }
@@ -0,0 +1,62 @@
1
+
2
+ # Auto-generated at Tue Jan 15 21:29:08 -0500 2008.
3
+ # Hand modifications will be overwritten.
4
+ # /Users/nichoj/Projects/ambitious_sphinx/config/ultrasphinx/default.base
5
+ indexer {
6
+ mem_limit = 256M
7
+ }
8
+ searchd {
9
+ read_timeout = 5
10
+ max_children = 300
11
+ log = /tmp/sphinx/log/searchd.log
12
+ port = 3312
13
+ max_matches = 100000
14
+ query_log = /tmp/sphinx/log/query.log
15
+ seamless_rotate = 1
16
+ pid_file = /tmp/sphinx/log/searchd.pid
17
+ address = 0.0.0.0
18
+ }
19
+
20
+ # Source configuration
21
+
22
+ source tweets
23
+ {
24
+ strip_html = 0
25
+ sql_range_step = 5000
26
+ index_html_attrs =
27
+ sql_query_post =
28
+
29
+ type = mysql
30
+ sql_query_pre = SET SESSION group_concat_max_len = 65535
31
+ sql_query_pre = SET NAMES utf8
32
+
33
+ sql_db = ambitious_sphinx_development
34
+ sql_host = localhost
35
+ sql_pass =
36
+ sql_sock = /tmp/mysql.sock
37
+ sql_user = root
38
+ sql_query_range = SELECT MIN(id) , MAX(id) FROM tweets
39
+ sql_query = SELECT (tweets.id * 1 + 0) AS id, tweets.body AS body, 'Tweet' AS class, 0 AS class_id, UNIX_TIMESTAMP(tweets.created_at) AS created_at, tweets.user_name AS user_name FROM tweets WHERE tweets.id >= $start AND tweets.id <= $end GROUP BY tweets.id
40
+
41
+ sql_group_column = class_id
42
+ sql_date_column = created_at
43
+ sql_query_info = SELECT * FROM tweets WHERE tweets.id = (($id - 0) / 1)
44
+ }
45
+
46
+
47
+ # Index configuration
48
+
49
+ index complete
50
+ {
51
+ source = tweets
52
+ charset_type = utf-8
53
+ charset_table = 0..9, A..Z->a..z, -, _, ., &, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F,U+C5->U+E5, U+E5, U+C4->U+E4, U+E4, U+D6->U+F6, U+F6, U+16B, U+0c1->a, U+0c4->a, U+0c9->e, U+0cd->i, U+0d3->o, U+0d4->o, U+0da->u, U+0dd->y, U+0e1->a, U+0e4->a, U+0e9->e, U+0ed->i, U+0f3->o, U+0f4->o, U+0fa->u, U+0fd->y, U+104->U+105, U+105, U+106->U+107, U+10c->c, U+10d->c, U+10e->d, U+10f->d, U+116->U+117, U+117, U+118->U+119, U+11a->e, U+11b->e, U+12E->U+12F, U+12F, U+139->l, U+13a->l, U+13d->l, U+13e->l, U+141->U+142, U+142, U+143->U+144, U+144,U+147->n, U+148->n, U+154->r, U+155->r, U+158->r, U+159->r, U+15A->U+15B, U+15B, U+160->s, U+160->U+161, U+161->s, U+164->t, U+165->t, U+16A->U+16B, U+16B, U+16e->u, U+16f->u, U+172->U+173, U+173, U+179->U+17A, U+17A, U+17B->U+17C, U+17C, U+17d->z, U+17e->z,
54
+ min_word_len = 1
55
+ # enable_star = 1
56
+ stopwords =
57
+ path = db/sphinx//sphinx_index_complete
58
+ docinfo = extern
59
+ morphology = stem_en
60
+ # min_infix_len = 1
61
+ }
62
+
@@ -0,0 +1,15 @@
1
+ require 'ambition'
2
+
3
+ # stub out rails stuff enough so that ultrasphinx will be happy
4
+ RAILS_ROOT = './' unless defined? RAILS_ROOT
5
+ RAILS_ENV = 'development' unless defined? RAILS_ENV
6
+
7
+ require 'active_record'
8
+ require 'ultrasphinx'
9
+
10
+ %w(base page query select sort slice).each do |f|
11
+ require "ambition/adapters/ambitious_sphinx/#{f}"
12
+ end
13
+
14
+ ActiveRecord::Base.extend Ambition::API
15
+ ActiveRecord::Base.ambition_adapter = Ambition::Adapters::AmbitiousSphinx
@@ -0,0 +1,33 @@
1
+ module Ambition # :nodoc:
2
+ module Adapters # :nodoc:
3
+ module AmbitiousSphinx # :nodoc:
4
+ # Helper for the other
5
+ class Base
6
+ # Does the string have an Ultrasphinx field?
7
+ def has_field? str
8
+ str =~ /:/
9
+ end
10
+
11
+ # Does the string have any Ultrasphinx operators?
12
+ def has_operator? str
13
+ str =~ /(AND|OR|NOT)/
14
+ end
15
+
16
+ # Should this string be quotified? It needs to happen if the string doesn't
17
+ # have an operator or a field.
18
+ def needs_quoting? str
19
+ not (has_operator?(str) or has_field?(str))
20
+ end
21
+
22
+ # Quote the string if it needs it.
23
+ def quotify str
24
+ if needs_quoting?(str)
25
+ %Q("#{str}")
26
+ else
27
+ str
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,52 @@
1
+ module Ambition
2
+ module Adapters
3
+ module AmbitiousSphinx
4
+ # Responsible for taking the clauses that Ambition has generated, and ultimately doing a
5
+ # Ultrasphinx::Search based on them
6
+ class Query < Base
7
+ def kick
8
+ Ultrasphinx::Search.new(to_hash).results
9
+ end
10
+
11
+ # Some magic to add pagination. This gets called if you were to do:
12
+ #
13
+ # Meal.select {'bacon'}.page(5)
14
+ #
15
+ # When +page+ is invoked, it's actually being invoked on +Ambition::Context+.
16
+ # It has +method_missing+? voodoo which will try to pass the method onto
17
+ # the +Query+. That's this class.
18
+ def page(number)
19
+ stash[:page] = number
20
+ context
21
+ end
22
+
23
+ # Not entirely sure when this is used, so unimplemented so far.
24
+ def size
25
+ raise "Not implemented yet."
26
+ end
27
+
28
+ # Builds a hash of options for Ultrasphinx::Search based on the clauses Ambition has generated.
29
+ def to_hash
30
+ hash = {}
31
+
32
+ unless (query = clauses[:select]).blank?
33
+ query_s = query.join(' ').squeeze(' ').strip
34
+ hash[:query] = quotify(query_s)
35
+ end
36
+
37
+ unless (page = stash[:page]).blank?
38
+ hash[:page] = page
39
+ end
40
+
41
+ hash
42
+ end
43
+
44
+ # Prints out the query that would be executed.
45
+ def to_s
46
+ hash = to_hash
47
+ hash[:query]
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,108 @@
1
+ module Ambition
2
+ module Adapters
3
+ module AmbitiousSphinx
4
+ # Select is responsible for taking pure Ruby, and mangling it until it resembles
5
+ # the syntax that Ultrasphinx[http://blog.evanweaver.com/files/doc/fauna/ultrasphinx/files/README.html] uses.
6
+ class Select < Base
7
+ # Handles method calls, like
8
+ #
9
+ # u.name
10
+ def call(method)
11
+ "#{method.to_s}:"
12
+ end
13
+
14
+ # Should we be supporting chained calls like:
15
+ #
16
+ # u.name.downcase
17
+ #
18
+ # ?
19
+ #
20
+ # I don't think Sphinx would be able to handle this.
21
+ def chained_call(*methods)
22
+ raise "Not implemented yet."
23
+ end
24
+
25
+ # Handles generating an Ultrasphinx query for code like:
26
+ #
27
+ # 'foo' && 'bar'
28
+ def both(left, right)
29
+ "#{quotify left} AND #{quotify right}"
30
+ end
31
+
32
+ # Handles generating an Ultrasphinx query for code like:
33
+ #
34
+ # 'foo' || 'bar'
35
+ def either(left, right)
36
+ "#{quotify left} OR #{quotify right}"
37
+ end
38
+
39
+ # Sphinx doesn't support equality.
40
+ def ==(left, right)
41
+ raise "Not applicable to sphinx."
42
+ end
43
+
44
+ # Sphinx doesn't support inequality.
45
+ def not_equal(left, right)
46
+ raise "Not applicable to sphinx."
47
+ end
48
+
49
+ # Handles generating an Ultrasphinx query for code like:
50
+ #
51
+ # u.name =~ 'bob'
52
+ #
53
+ # Some cavaets:
54
+ # * left hand side _must_ be a field, like u.name
55
+ # * right hand side _must not_ be a regular expression. Pattern matching is generally not
56
+ # supported by full text search engines
57
+ def =~(left, right)
58
+ raise if right.is_a? Regexp
59
+ "#{left}#{quotify right}"
60
+ end
61
+
62
+ # Handles generating an Ultrasphinx query for code like:
63
+ #
64
+ # u.name !~ 'bob'
65
+ #
66
+ # Some cavaets:
67
+ # * left hand side _must_ be a field, like u.name
68
+ # * right hand side _must not_ be a regular expression. Pattern matching is generally not
69
+ # supported by full text search engines
70
+ def not_regexp(left, right)
71
+ # could be DRYer, but this is more readable than: "NOT #{self.=~(left,right)}"
72
+ raise if right.is_a? Regexp
73
+ "NOT #{left}#{quotify right}"
74
+ end
75
+
76
+ # Not supported by Sphinx. If you need this kind of comparison, you probably should be
77
+ # using ambitious-activerecord.
78
+ def <(left, right)
79
+ raise "Not applicable to sphinx."
80
+ end
81
+
82
+ # Not supported by Sphinx. If you need this kind of comparison, you probably should be
83
+ # using ambitious-activerecord.
84
+ def >(left, right)
85
+ raise "Not applicable to sphinx."
86
+ end
87
+
88
+ # Not supported by Sphinx. If you need this kind of comparison, you probably should be
89
+ # using ambitious-activerecord.
90
+ def >=(left, right)
91
+ raise "Not applicable to sphinx."
92
+ end
93
+
94
+ # Not supported by Sphinx. If you need this kind of comparison, you probably should be
95
+ # using ambitious-activerecord.
96
+ def <=(left, right)
97
+ raise "Not applicable to sphinx."
98
+ end
99
+
100
+ # Not supported by Sphinx. If you need this kind of comparison, you probably should be
101
+ # using ambitious-activerecord.
102
+ def include?(left, right)
103
+ raise "Not applicable to sphinx."
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,13 @@
1
+ module Ambition
2
+ module Adapters
3
+ module AmbitiousSphinx
4
+ # Slice would normally handle slicing, but we don't support it yet.
5
+ class Slice < Base
6
+ # Not implemented
7
+ def slice(start, length)
8
+ raise "Not implemented."
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,38 @@
1
+ module Ambition
2
+ module Adapters
3
+ module AmbitiousSphinx
4
+ # +Sort+ would normally handle sorting, but we don't support it yet.
5
+ class Sort < Base
6
+ # Not implemented
7
+ def sort_by(method)
8
+ raise "Not implemented."
9
+ end
10
+
11
+ # Not implemented
12
+ def reverse_sort_by(method)
13
+ raise "Not implemented."
14
+ end
15
+
16
+ # Not implemented
17
+ def chained_sort_by(receiver, method)
18
+ raise "Not implemented."
19
+ end
20
+
21
+ # Not implemented
22
+ def chained_reverse_sort_by(receiver, method)
23
+ raise "Not implemented."
24
+ end
25
+
26
+ # Not implemented
27
+ def to_proc(symbol)
28
+ raise "Not implemented."
29
+ end
30
+
31
+ # Not implemented
32
+ def rand
33
+ raise "Not implemented."
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,9 @@
1
+ %w( rubygems test/spec mocha redgreen English ).each { |f| require f }
2
+
3
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
4
+ require 'ambition/adapters/ambitious_sphinx'
5
+
6
+ class User < ActiveRecord::Base
7
+ attr_reader :name
8
+ attr_reader :age
9
+ end
@@ -0,0 +1,80 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context 'AmbitiousSphinx Adapter :: Select' do
4
+
5
+ specify 'Ruby attributes become Sphinx fields prefixed with @' do
6
+ query = User.select {|m| m.name}.to_hash[:query]
7
+ query.should == "name:"
8
+ end
9
+
10
+ specify 'Ruby string becomes Sphinx string' do
11
+ query = User.select {'jon'}.to_hash[:query]
12
+ query.should == %Q("jon")
13
+ end
14
+
15
+ specify 'Ruby string becomes Sphinx phrase search' do
16
+ query = User.select {'jon doe'}.to_hash[:query]
17
+ query.should == "\"jon doe\""
18
+ end
19
+
20
+ specify 'Ruby == should not be supported' do
21
+ should.raise do User.select {|m| m.name == 'jon'} end
22
+ end
23
+
24
+ specify 'Ruby != becomes Sphinx NOT operator' do
25
+ should.raise do User.select {|m| m.name != 'jon'} end
26
+ end
27
+
28
+ specify 'Ruby && becomes Sphinx AND operator' do
29
+ query = User.select {'jon' && 'blarg'}.to_hash[:query]
30
+ query.should == %Q("jon" AND "blarg")
31
+ end
32
+
33
+ specify 'Ruby || becomes Sphinx OR operator' do
34
+ query = User.select { 'jon' || 'chris'}.to_hash[:query]
35
+ query.should == %Q("jon" OR "chris")
36
+ end
37
+
38
+ specify 'Ruby =~ with string' do
39
+ query = User.select {|m| m.name =~ 'chris'}.to_hash[:query]
40
+ query.should == %Q(name:"chris")
41
+ end
42
+
43
+ specify 'Ruby =~ with string' do
44
+ query = User.select {|m| m.name =~ 'chris' && m.name =~ 'jon'}.to_hash[:query]
45
+ query.should == %Q(name:"chris" AND name:"jon")
46
+ end
47
+
48
+ specify 'Ruby =~ with Regexp' do
49
+ should.raise do User.select {|m| m.name =~ /chris/} end
50
+ end
51
+
52
+ specify 'Ruby !~ with string' do
53
+ query = User.select {|m| m.name =~ 'chris' && m.name !~ 'jon'}.to_hash[:query]
54
+ query.should == %Q(name:"chris" AND NOT name:"jon")
55
+ end
56
+
57
+ specify 'Ruby !~ with Regexp is not supported' do
58
+ should.raise do User.select {|m| m.name !~ /chris/} end
59
+ end
60
+
61
+ specify 'Ruby > should not be supported' do
62
+ should.raise do User.select {|m| m.age > 21} end
63
+ end
64
+
65
+ specify 'Ruby >= should not be supported' do
66
+ should.raise do User.select {|m| m.age >= 21} end
67
+ end
68
+
69
+ specify 'Ruby < should not be supported' do
70
+ should.raise do User.select {|m| m.age < 21} end
71
+ end
72
+
73
+ specify 'Ruby <= should not be supported' do
74
+ should.raise do User.select {|m| m.age <= 21} end
75
+ end
76
+
77
+ xspecify 'inspect' do
78
+ User.select { |u| u.name }.inspect.should.match %r(call #to_s or #to_hash)
79
+ end
80
+ end
@@ -0,0 +1,12 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "AmbitiousSphinx Adapter :: Slice" do
4
+ setup do
5
+ @klass = User
6
+ @block = @klass.select { |m| m.name =~ 'jon' }
7
+ end
8
+
9
+ specify "not supported" do
10
+ should.raise {@block.first}
11
+ end
12
+ end
data/test/sort_test.rb ADDED
@@ -0,0 +1,26 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "AmbitiousSphinx Adapter :: Sort" do
4
+ setup do
5
+ @klass = User
6
+ @block = @klass.select { |m| m.name =~ 'jon' }
7
+ end
8
+
9
+ specify "order" do
10
+ should.raise do
11
+ @block.sort_by {|m| m.name}
12
+ end
13
+ end
14
+
15
+ specify "reverse order with -" do
16
+ should.raise do
17
+ @block.sort_by { |m| -m.age }
18
+ end
19
+ end
20
+
21
+ specify "random order" do
22
+ should.raise do
23
+ @block.sort_by { rand }
24
+ end
25
+ end
26
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ambitious-sphinx
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Josh Nichols
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-02-29 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ultrasphinx
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "1.7"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: ambition
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 0.5.0
32
+ version:
33
+ description: An ambitious adapter for sphinx
34
+ email: josh@technicalpickles.com
35
+ executables: []
36
+
37
+ extensions: []
38
+
39
+ extra_rdoc_files: []
40
+
41
+ files:
42
+ - ambitious-sphinx.gemspec
43
+ - config/ultrasphinx/default.base
44
+ - config/ultrasphinx/development.conf
45
+ - lib/ambition/adapters/ambitious_sphinx/base.rb
46
+ - lib/ambition/adapters/ambitious_sphinx/query.rb
47
+ - lib/ambition/adapters/ambitious_sphinx/select.rb
48
+ - lib/ambition/adapters/ambitious_sphinx/slice.rb
49
+ - lib/ambition/adapters/ambitious_sphinx/sort.rb
50
+ - lib/ambition/adapters/ambitious_sphinx.rb
51
+ - LICENSE
52
+ - Manifest
53
+ - README
54
+ - test/helper.rb
55
+ - test/select_test.rb
56
+ - test/slice_test.rb
57
+ - test/sort_test.rb
58
+ has_rdoc: true
59
+ homepage: http://ambitioussphinx.rubyforge.org/
60
+ post_install_message:
61
+ rdoc_options: []
62
+
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ requirements: []
78
+
79
+ rubyforge_project: ambitioussphinx
80
+ rubygems_version: 1.0.0
81
+ signing_key:
82
+ specification_version: 2
83
+ summary: An ambitious adapter for sphinx
84
+ test_files:
85
+ - test/select_test.rb
86
+ - test/slice_test.rb
87
+ - test/sort_test.rb