minisphinx 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ *~
2
+ pkg
3
+ Gemfile.lock
data/.rbenv-gemsets ADDED
@@ -0,0 +1 @@
1
+ minisphinx
data/.rbenv-version ADDED
@@ -0,0 +1 @@
1
+ ree-1.8.7-2012.02
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://www.rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Justin Balthrop
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,9 @@
1
+ minisphinx
2
+ ==========
3
+
4
+ An alternative to Ultrasphinx. But nobody will use it until I write some documentation.
5
+
6
+ COPYRIGHT
7
+ =========
8
+
9
+ Copyright (c) 2009 Justin Balthrop. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'rake/testtask'
2
+ require 'bundler/gem_tasks'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs = ['lib']
6
+ t.pattern = 'test/**/*_test.rb'
7
+ t.verbose = false
8
+ end
9
+
10
+ task :default => :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,14 @@
1
+ indexer {
2
+ mem_limit = 1024M
3
+ }
4
+
5
+ searchd {
6
+ read_timeout = 5
7
+ max_children = 300
8
+ log = <%= RAILS_ROOT %>/log/searchd.log
9
+ max_matches = 100000
10
+ query_log = <%= RAILS_ROOT %>/log/query.log
11
+ seamless_rotate = 1
12
+ listen = 0.0.0.0:3313
13
+ pid_file = <%= RAILS_ROOT %>/log/searchd.pid
14
+ }
@@ -0,0 +1,40 @@
1
+ require 'deep_hash'
2
+
3
+ module Minisphinx
4
+ class Charset
5
+ attr_reader :name, :only, :except
6
+
7
+ def initialize(opts)
8
+ opts = {:name => opts} if opts.kind_of?(Symbol)
9
+ @name = opts[:name]
10
+ @only = Array(opts[:only]).to_set if opts[:only]
11
+ @except = Array(opts[:except]).to_set if opts[:except]
12
+ end
13
+
14
+ def self.charset
15
+ @charset ||= YAML.load_file(RAILS_ROOT + '/config/sphinx/charset.yml')
16
+ end
17
+
18
+ MAX_PER_LINE = 50
19
+ def to_s
20
+ chars = {}
21
+
22
+ self.class.charset[name.to_s].each do |charset|
23
+ charset.each do |group, charset|
24
+ next if except and except.include?(group.to_sym)
25
+ next if only and not only.include?(group.to_sym)
26
+ charset.split(',').each do |char|
27
+ key = char.strip.split('->').first
28
+ chars[key] ||= char
29
+ end
30
+ end
31
+ end
32
+
33
+ lines = []
34
+ chars.values.flatten.sort.each_slice(MAX_PER_LINE) do |line_chars|
35
+ lines << line_chars.join(', ')
36
+ end
37
+ lines.join(", \\\n")
38
+ end
39
+ end
40
+ end
data/lib/minisphinx.rb ADDED
@@ -0,0 +1,243 @@
1
+ module Minisphinx
2
+ def sphinx_source(name, opts)
3
+ opts[:model_class] ||= self
4
+ Minisphinx.sources << Source.new(name, opts)
5
+ end
6
+
7
+ def sphinx_index(name, opts = {})
8
+ Minisphinx.indexes << Index.new(name, opts)
9
+ end
10
+
11
+ def self.indexes; @indexes ||= []; end
12
+ def self.sources; @sources ||= []; end
13
+
14
+ def self.configure(opts)
15
+ template = ['default', RAILS_ENV].collect {|base| RAILS_ROOT + "/config/sphinx/#{base}.conf"}.detect {|file| File.exists?(file)}
16
+
17
+ File.open(opts[:path] + '/sphinx.conf', 'w') do |file|
18
+ file << "# Autogenerated by minisphinx at #{Time.now}\n"
19
+ file << ERB.new(IO.read(template)).result(binding) + "\n" if template
20
+ file << "# Sources\n\n"
21
+ sources.each do |source|
22
+ file << source.configuration(opts)
23
+ end
24
+ file << "# Indexes\n\n"
25
+ indexes.each do |index|
26
+ file << index.configuration(opts)
27
+ end
28
+ end unless opts[:write] == false
29
+ end
30
+
31
+ def self.config_block(head, lines)
32
+ "#{head}\n{\n #{lines.flatten.compact.join("\n ")}\n}\n\n"
33
+ end
34
+
35
+ class Source
36
+ attr_reader :name, :model_class, :fetch_key, :db, :fields, :joins, :config, :delta_field
37
+
38
+ def initialize(name, opts)
39
+ @name = name
40
+ @delta_field = opts.delete(:delta_field)
41
+ @delta_min = opts.delete(:delta_min)
42
+ @fetch_key = opts.delete(:fetch_key) || 'id'
43
+
44
+ @fields = initialize_fields(opts)
45
+ @joins = Array(opts.delete(:joins)) + Array(opts.delete(:join))
46
+ (opts.delete(:include) || []).each do |include_opts|
47
+ @fields.concat initialize_fields(include_opts)
48
+ @joins.concat Array(include_opts.delete(:joins)) + Array(include_opts.delete(:join))
49
+ end
50
+ raise 'at least one field required' if @fields.empty?
51
+ @fields.sort!
52
+
53
+ @model_class = opts.delete(:model_class)
54
+ @table_name = opts.delete(:table_name)
55
+ @db = opts.delete(:db) || model_class.connection.config
56
+ @db = ActiveRecord::Base.configurations["#{db}_#{RAILS_ENV}"] unless db.kind_of?(Hash)
57
+
58
+ @config = self.class.config.merge(opts)
59
+ end
60
+
61
+ def table_name
62
+ @table_name ||= model_class.table_name
63
+ end
64
+
65
+ def type
66
+ db[:adapter] == 'postgresql' ? 'pgsql' : db[:adapter]
67
+ end
68
+
69
+ def configuration(opts)
70
+ str = Minisphinx.config_block("source #{name}_base", [
71
+ "type = #{type}",
72
+ config.collect do |key, value|
73
+ "sql_#{key} = #{value}"
74
+ end,
75
+ "sql_db = #{db[:database]}",
76
+ "sql_host = #{db[:host]}",
77
+ "sql_pass = #{db[:password]}",
78
+ "sql_user = #{db[:username]}",
79
+ "sql_query_info = #{sql_query_info}",
80
+ fields.collect do |field|
81
+ "sql_attr_#{field.type} = #{field.name}" if field.type != :text
82
+ end,
83
+ ])
84
+ str << Minisphinx.config_block("source #{name} : #{name}_base", [
85
+ "sql_query_range = #{sql_query_range}",
86
+ "sql_query = #{sql_query}",
87
+ ])
88
+ if delta_field
89
+ str << Minisphinx.config_block("source #{name}_delta : #{name}_base", [
90
+ "sql_query = #{sql_query_delta(opts[:delta_min])}",
91
+ ])
92
+ end
93
+ str
94
+ end
95
+
96
+ def sql_query_range
97
+ "SELECT coalesce(MIN(#{fetch_key}),1)::bigint, coalesce(MAX(#{fetch_key}),1)::bigint FROM #{table_name}"
98
+ end
99
+
100
+ def sql_query
101
+ "SELECT #{table_name}.id AS doc_id, #{fields.join(', ')} " <<
102
+ "FROM #{table_name} #{joins.join(' ')} WHERE #{fetch_key} >= $start AND #{fetch_key} <= $end"
103
+ end
104
+
105
+ def sql_query_delta(delta_min)
106
+ delta_min = "'#{delta_min.to_s(:db)}'" if delta_min.kind_of?(Time) or delta_min.kind_of?(Date)
107
+ "SELECT #{table_name}.id AS doc_id, #{fields.join(', ')} " <<
108
+ "FROM #{table_name} #{joins.join(' ')} WHERE #{delta_field} >= #{delta_min}"
109
+ end
110
+
111
+ def sql_query_info
112
+ "SELECT * FROM #{table_name} WHERE id = $id"
113
+ end
114
+
115
+ def self.config
116
+ @config ||= {
117
+ :range_step => 5000,
118
+ :ranged_throttle => 0,
119
+ }
120
+ end
121
+
122
+ private
123
+
124
+ def initialize_fields(opts)
125
+ (opts.delete(:fields) || []).collect do |field_opts|
126
+ field_opts = {:field => field_opts} unless field_opts.kind_of?(Hash)
127
+ field_opts[:table_name] = opts[:table_name]
128
+ field_opts[:model_class] = opts[:model_class]
129
+
130
+ if field_opts[:sortable] and not [nil, :text].include?(field_opts[:type])
131
+ raise ":sortable only permitted for :text fields, #{field_opts[:field]} is of type #{field_opts[:type].inspect}"
132
+ end
133
+
134
+ [Field.new(field_opts), field_opts[:sortable] && Field.new(field_opts.merge(:type => :sortable, :suffix => 'sortable'))]
135
+ end.flatten.compact
136
+ end
137
+ end
138
+
139
+ class Field
140
+ attr_reader :model_class, :field, :name, :type
141
+
142
+ TYPE_MAP = {
143
+ :integer => :uint,
144
+ :decimal => :float,
145
+ :boolean => :bool,
146
+ :date => :timestamp,
147
+ :datetime => :timestamp,
148
+ :timestamp => :timestamp,
149
+ :string => :text,
150
+ :sortable => :string,
151
+ }
152
+
153
+ def initialize(opts)
154
+ @model_class = opts[:model_class]
155
+ @table_name = opts[:table_name]
156
+
157
+ @type = opts[:type]
158
+ @name = opts[:as] || opts[:field]
159
+ @name = "#{name}_#{opts[:suffix]}" if opts[:suffix]
160
+ @field = opts[:field]
161
+ @field = "#{table_name}.#{field}" if not field.index(/[\(.\s]/)
162
+ @field = opts[:transform] % field if opts[:transform]
163
+ @field = "UNIX_TIMESTAMP(#{field})" if type == :timestamp
164
+ end
165
+
166
+ def table_name
167
+ @table_name ||= model_class ? model_class.table_name : nil
168
+ end
169
+
170
+ def <=>(other)
171
+ # Sphinx has a bug that messes up your index unless str2ordinal fields come first.
172
+ if type != other.type
173
+ (type == :str2ordinal && -1) || (other.type == :str2ordinal && 1) || (type.to_s <=> other.type.to_s)
174
+ else
175
+ name <=> other.name
176
+ end
177
+ end
178
+
179
+ def type
180
+ if @type.nil? and model_class
181
+ column = model_class.columns_hash[name]
182
+ @type = column.sql_type == 'bigint' ? :bigint : column.type.to_sym
183
+ end
184
+ TYPE_MAP[@type] || @type || :text
185
+ end
186
+
187
+ def to_s
188
+ "#{field} AS #{name}"
189
+ end
190
+ end
191
+
192
+ class Index
193
+ attr_reader :name, :sources, :charset, :ngram, :config, :delta
194
+
195
+ def initialize(name, opts)
196
+ @name = name
197
+ @config = self.class.config.merge(opts)
198
+ @delta = config.delete(:delta)
199
+ @delta = "#{name}_delta" if @delta == true
200
+ @sources = Array(config.delete(:source)) + Array(config.delete(:sources))
201
+ @charset = Minisphinx::Charset.new(config.delete(:charset)) if config[:charset]
202
+ @ngram = Minisphinx::Charset.new(config.delete(:ngram)) if config[:ngram]
203
+ end
204
+
205
+ def configuration(opts)
206
+ path = opts[:path]
207
+ str = Minisphinx.config_block("index #{name}", [
208
+ sources.collect do |source|
209
+ "source = #{source}"
210
+ end,
211
+ "path = #{path}/#{name}",
212
+ config.collect do |key, value|
213
+ "#{key} = #{value}"
214
+ end,
215
+ charset && "charset_table = #{charset}",
216
+ ngram && "ngram_chars = #{ngram}",
217
+ ngram && "ngram_len = 1",
218
+ ])
219
+ if delta
220
+ str << Minisphinx.config_block("index #{delta} : #{name}", [
221
+ sources.collect do |source|
222
+ "source = #{source}_delta"
223
+ end,
224
+ "path = #{path}/#{delta}",
225
+ ])
226
+ end
227
+ str
228
+ end
229
+
230
+ def self.config
231
+ @config ||= {
232
+ :charset_type => 'utf-8',
233
+ :min_word_len => 1,
234
+ :html_strip => 0,
235
+ :docinfo => 'extern',
236
+ }
237
+ end
238
+ end
239
+ end
240
+
241
+ class ActiveRecord::ConnectionAdapters::AbstractAdapter
242
+ attr_reader :config
243
+ end
@@ -0,0 +1,36 @@
1
+ /* Taken from ultrasphinx */
2
+
3
+ /* http://osdir.com/ml/db.postgresql.admIN/2003-08/msg00057.html */
4
+
5
+ CREATE FUNCTION MAKE_CONCAT_WS() RETURNS text AS '
6
+ declare
7
+ v_args int := 32;
8
+ v_first text := ''CREATE FUNCTION CONCAT_WS(text,text,text) RETURNS text AS ''''SELECT CASE WHEN $1 IS NULL THEN NULL WHEN $3 IS NULL THEN $2 ELSE $2 || $1 || $3 END'''' LANGUAGE sql IMMUTABLE'';
9
+ v_part1 text := ''CREATE FUNCTION CONCAT_WS(text,text'';
10
+ v_part2 text := '') RETURNS text AS ''''SELECT CONCAT_WS($1,CONCAT_WS($1,$2'';
11
+ v_part3 text := '')'''' LANGUAGE sql IMMUTABLE'';
12
+ v_sql text;
13
+
14
+ BEGIN
15
+ EXECUTE v_first;
16
+ FOR i IN 4 .. v_args loop
17
+ v_sql := v_part1;
18
+ FOR j IN 3 .. i loop
19
+ v_sql := v_sql || '',text'';
20
+ END loop;
21
+
22
+ v_sql := v_sql || v_part2;
23
+
24
+ FOR j IN 3 .. i - 1 loop
25
+ v_sql := v_sql || '',$'' || j::text;
26
+ END loop;
27
+ v_sql := v_sql || ''),$'' || i::text;
28
+
29
+ v_sql := v_sql || v_part3;
30
+ EXECUTE v_sql;
31
+ END loop;
32
+ RETURN ''OK'';
33
+ END;
34
+ ' LANGUAGE 'plpgsql';
35
+
36
+ SELECT MAKE_CONCAT_WS();
@@ -0,0 +1,16 @@
1
+ /* Taken from ultrasphinx */
2
+
3
+ /* Fake CRC32 */
4
+
5
+ CREATE FUNCTION crc32(text)
6
+ RETURNS bigint AS $$
7
+ DECLARE
8
+ tmp bigint;
9
+ BEGIN
10
+ tmp = (hex_to_int(SUBSTRING(MD5($1) FROM 1 FOR 8))::bigint);
11
+ IF tmp < 0 THEN
12
+ tmp = 4294967296 + tmp;
13
+ END IF;
14
+ return tmp;
15
+ END
16
+ $$ IMMUTABLE STRICT LANGUAGE plpgsql;
@@ -0,0 +1,24 @@
1
+ /* Taken from ultrasphinx */
2
+
3
+ /*
4
+ mysqlcompat-1.0b3
5
+ public domain
6
+ GROUP_CONCAT()
7
+ Note: For DISTINCT and ORDER BY a subquery is required
8
+ */
9
+
10
+ CREATE FUNCTION _group_concat(text, text)
11
+ RETURNS text AS $$
12
+ SELECT CASE
13
+ WHEN $2 IS NULL THEN COALESCE($1, ' ')
14
+ WHEN $1 IS NULL THEN $2
15
+ ELSE $1 operator(pg_catalog.||) ' ' operator(pg_catalog.||) $2
16
+ END
17
+ $$ IMMUTABLE LANGUAGE SQL;
18
+
19
+ CREATE AGGREGATE group_concat (
20
+ BASETYPE = text,
21
+ SFUNC = _group_concat,
22
+ STYPE = text
23
+ );
24
+
@@ -0,0 +1,16 @@
1
+ /* Taken from ultrasphinx */
2
+
3
+ CREATE FUNCTION hex_to_int(varchar) RETURNS int4 AS '
4
+ DECLARE
5
+ h alias for $1;
6
+ exec varchar;
7
+ curs refcursor;
8
+ res int;
9
+ BEGIN
10
+ exec := ''SELECT x'''''' || h || ''''''::int4'';
11
+ OPEN curs FOR EXECUTE exec;
12
+ FETCH curs INTO res;
13
+ CLOSE curs;
14
+ return res;
15
+ END;'
16
+ LANGUAGE 'plpgsql' IMMUTABLE STRICT;
@@ -0,0 +1,13 @@
1
+ /* Taken from ultrasphinx */
2
+
3
+ /*
4
+ mysqlcompat-1.0b3
5
+ public domain
6
+ modified
7
+ UNIX_TIMESTAMP(date)
8
+ */
9
+
10
+ CREATE FUNCTION unix_timestamp(timestamp without time zone)
11
+ RETURNS bigint AS $$
12
+ SELECT EXTRACT(EPOCH FROM $1)::bigint
13
+ $$ VOLATILE LANGUAGE SQL;
@@ -0,0 +1,25 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "minisphinx"
6
+ gem.version = IO.read('VERSION')
7
+ gem.authors = ["Justin Balthrop"]
8
+ gem.email = ["git@justinbalthrop.com"]
9
+ gem.description = %q{A simple Sphinx indexing library for Ruby}
10
+ gem.summary = gem.description
11
+ gem.homepage = "https://github.com/ninjudd/minisphinx"
12
+
13
+ gem.add_development_dependency 'shoulda', '3.0.1'
14
+ gem.add_development_dependency 'mocha'
15
+ gem.add_development_dependency 'rake'
16
+ gem.add_development_dependency 'activerecord-postgresql-adapter'
17
+
18
+ gem.add_dependency 'activerecord', '~> 2.3.9'
19
+ gem.add_dependency 'deep_hash', '0.0.2'
20
+
21
+ gem.files = `git ls-files`.split($/)
22
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
23
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
24
+ gem.require_paths = ["lib"]
25
+ end
@@ -0,0 +1,60 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class MinisphinxTest < Test::Unit::TestCase
4
+ class CreateTables < ActiveRecord::Migration
5
+ def self.up
6
+ create_table :pets do |t|
7
+ t.column :name, :string
8
+ t.column :species, :string
9
+ t.column :breed, :string
10
+ t.column :color, :string
11
+ t.column :gender, :string
12
+ t.column :adopted, :boolean
13
+ end
14
+ end
15
+
16
+ def self.down
17
+ drop_table :pets
18
+ end
19
+ end
20
+
21
+ class Pet < ActiveRecord::Base
22
+ extend Minisphinx
23
+
24
+ def self.initialize_sphinx
25
+ sphinx_source :pets,
26
+ :fetch_key => 'public_id',
27
+ :delta_field => 'CASE WHEN master_profile THEN now() ELSE updated_at END',
28
+ :fields => [
29
+ {:field => 'name', :sortable => true},
30
+ {:field => 'species', :sortable => true},
31
+ {:field => 'breed', :sortable => true},
32
+ {:field => 'gender', :sortable => true},
33
+ {:field => 'adopted', :type => :boolean},
34
+ ]
35
+
36
+ Minisphinx::Index.config[:source ] = :profiles
37
+ Minisphinx::Index.config[:delta ] = true
38
+
39
+ sphinx_index :full
40
+ end
41
+ end
42
+
43
+ context 'with a db connection' do
44
+ setup do
45
+ Dir.mkdir('/tmp/minisphinx-test')
46
+ CreateTables.verbose = false
47
+ CreateTables.up
48
+ end
49
+
50
+ teardown do
51
+ CreateTables.down
52
+ end
53
+
54
+ should "write config" do
55
+ Pet.initialize_sphinx
56
+ Minisphinx.configure(:path => '/tmp/minisphinx-test')
57
+ assert File.exists('/tmp/minisphinx-test/sphinx.conf')
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha/setup'
5
+ require 'pp'
6
+
7
+ require 'active_record'
8
+ require 'minisphinx'
9
+ require 'minisphinx/charset'
10
+
11
+ class Test::Unit::TestCase
12
+ end
13
+
14
+ RAILS_ENV = 'test'
15
+ RAILS_ROOT = '/tmp/minisphinx-test'
16
+
17
+ ActiveRecord::Base.establish_connection(
18
+ :adapter => "postgresql",
19
+ :host => "localhost",
20
+ :database => "minisphinx_test"
21
+ )
22
+ ActiveRecord::Migration.verbose = false
23
+ ActiveRecord::Base.connection.client_min_messages = 'panic'
metadata ADDED
@@ -0,0 +1,176 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: minisphinx
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Justin Balthrop
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2013-06-03 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: shoulda
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - "="
28
+ - !ruby/object:Gem::Version
29
+ hash: 5
30
+ segments:
31
+ - 3
32
+ - 0
33
+ - 1
34
+ version: 3.0.1
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: mocha
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 0
48
+ version: "0"
49
+ type: :development
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: rake
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ type: :development
64
+ version_requirements: *id003
65
+ - !ruby/object:Gem::Dependency
66
+ name: activerecord-postgresql-adapter
67
+ prerelease: false
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ type: :development
78
+ version_requirements: *id004
79
+ - !ruby/object:Gem::Dependency
80
+ name: activerecord
81
+ prerelease: false
82
+ requirement: &id005 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ hash: 17
88
+ segments:
89
+ - 2
90
+ - 3
91
+ - 9
92
+ version: 2.3.9
93
+ type: :runtime
94
+ version_requirements: *id005
95
+ - !ruby/object:Gem::Dependency
96
+ name: deep_hash
97
+ prerelease: false
98
+ requirement: &id006 !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - "="
102
+ - !ruby/object:Gem::Version
103
+ hash: 27
104
+ segments:
105
+ - 0
106
+ - 0
107
+ - 2
108
+ version: 0.0.2
109
+ type: :runtime
110
+ version_requirements: *id006
111
+ description: A simple Sphinx indexing library for Ruby
112
+ email:
113
+ - git@justinbalthrop.com
114
+ executables: []
115
+
116
+ extensions: []
117
+
118
+ extra_rdoc_files: []
119
+
120
+ files:
121
+ - .gitignore
122
+ - .rbenv-gemsets
123
+ - .rbenv-version
124
+ - Gemfile
125
+ - LICENSE
126
+ - README
127
+ - Rakefile
128
+ - VERSION
129
+ - examples/default.conf
130
+ - lib/minisphinx.rb
131
+ - lib/minisphinx/charset.rb
132
+ - lib/mysqlcompat/concat_ws.sql
133
+ - lib/mysqlcompat/crc32.sql
134
+ - lib/mysqlcompat/group_concat.sql
135
+ - lib/mysqlcompat/hex_to_int.sql
136
+ - lib/mysqlcompat/unix_timestamp.sql
137
+ - minisphinx.gemspec
138
+ - test/minisphinx_test.rb
139
+ - test/test_helper.rb
140
+ has_rdoc: true
141
+ homepage: https://github.com/ninjudd/minisphinx
142
+ licenses: []
143
+
144
+ post_install_message:
145
+ rdoc_options: []
146
+
147
+ require_paths:
148
+ - lib
149
+ required_ruby_version: !ruby/object:Gem::Requirement
150
+ none: false
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ hash: 3
155
+ segments:
156
+ - 0
157
+ version: "0"
158
+ required_rubygems_version: !ruby/object:Gem::Requirement
159
+ none: false
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ hash: 3
164
+ segments:
165
+ - 0
166
+ version: "0"
167
+ requirements: []
168
+
169
+ rubyforge_project:
170
+ rubygems_version: 1.5.2
171
+ signing_key:
172
+ specification_version: 3
173
+ summary: A simple Sphinx indexing library for Ruby
174
+ test_files:
175
+ - test/minisphinx_test.rb
176
+ - test/test_helper.rb