dpickett-thinking-sphinx 1.1.4 → 1.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.textile +126 -0
- data/lib/thinking_sphinx/active_record/attribute_updates.rb +48 -0
- data/lib/thinking_sphinx/active_record/delta.rb +14 -1
- data/lib/thinking_sphinx/active_record.rb +23 -5
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +9 -1
- data/lib/thinking_sphinx/adapters/mysql_adapter.rb +3 -2
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +4 -3
- data/lib/thinking_sphinx/association.rb +17 -0
- data/lib/thinking_sphinx/attribute.rb +106 -95
- data/lib/thinking_sphinx/class_facet.rb +0 -5
- data/lib/thinking_sphinx/collection.rb +7 -1
- data/lib/thinking_sphinx/configuration.rb +9 -4
- data/lib/thinking_sphinx/core/string.rb +3 -10
- data/lib/thinking_sphinx/deltas/default_delta.rb +8 -5
- data/lib/thinking_sphinx/deltas/delayed_delta.rb +4 -2
- data/lib/thinking_sphinx/deltas.rb +7 -2
- data/lib/thinking_sphinx/deploy/capistrano.rb +80 -0
- data/lib/thinking_sphinx/facet.rb +22 -9
- data/lib/thinking_sphinx/facet_collection.rb +27 -12
- data/lib/thinking_sphinx/field.rb +4 -96
- data/lib/thinking_sphinx/index/builder.rb +46 -15
- data/lib/thinking_sphinx/index.rb +58 -66
- data/lib/thinking_sphinx/property.rb +133 -0
- data/lib/thinking_sphinx/rails_additions.rb +7 -4
- data/lib/thinking_sphinx/search.rb +181 -44
- data/lib/thinking_sphinx/tasks.rb +4 -4
- data/lib/thinking_sphinx.rb +47 -11
- data/spec/unit/thinking_sphinx/active_record/delta_spec.rb +2 -2
- data/spec/unit/thinking_sphinx/active_record_spec.rb +64 -4
- data/spec/unit/thinking_sphinx/attribute_spec.rb +16 -1
- data/spec/unit/thinking_sphinx/facet_collection_spec.rb +64 -0
- data/spec/unit/thinking_sphinx/facet_spec.rb +46 -0
- data/spec/unit/thinking_sphinx/index_spec.rb +90 -0
- data/spec/unit/thinking_sphinx/rails_additions_spec.rb +183 -0
- data/spec/unit/thinking_sphinx/search_spec.rb +44 -0
- data/spec/unit/thinking_sphinx_spec.rb +10 -6
- data/tasks/distribution.rb +1 -1
- data/tasks/testing.rb +7 -15
- data/vendor/after_commit/init.rb +3 -0
- data/vendor/after_commit/lib/after_commit/active_record.rb +27 -4
- data/vendor/after_commit/lib/after_commit/connection_adapters.rb +1 -1
- data/vendor/after_commit/lib/after_commit.rb +4 -1
- metadata +12 -3
- data/README +0 -107
@@ -31,8 +31,10 @@ module ThinkingSphinx
|
|
31
31
|
# fashion to database.yml - using the following keys: config_file,
|
32
32
|
# searchd_log_file, query_log_file, pid_file, searchd_file_path, port,
|
33
33
|
# allow_star, enable_star, min_prefix_len, min_infix_len, mem_limit,
|
34
|
-
# max_matches,
|
35
|
-
# html_strip,
|
34
|
+
# max_matches, morphology, charset_type, charset_table, ignore_chars,
|
35
|
+
# html_strip, html_remove_elements, delayed_job_priority.
|
36
|
+
#
|
37
|
+
# I think you've got the idea.
|
36
38
|
#
|
37
39
|
# Each setting in the YAML file is optional - so only put in the ones you
|
38
40
|
# want to change.
|
@@ -55,7 +57,8 @@ module ThinkingSphinx
|
|
55
57
|
|
56
58
|
attr_accessor :config_file, :searchd_log_file, :query_log_file,
|
57
59
|
:pid_file, :searchd_file_path, :address, :port, :allow_star,
|
58
|
-
:database_yml_file, :app_root, :bin_path, :model_directories
|
60
|
+
:database_yml_file, :app_root, :bin_path, :model_directories,
|
61
|
+
:delayed_job_priority
|
59
62
|
|
60
63
|
attr_accessor :source_options, :index_options
|
61
64
|
|
@@ -85,7 +88,9 @@ module ThinkingSphinx
|
|
85
88
|
self.searchd_file_path = "#{self.app_root}/db/sphinx/#{environment}"
|
86
89
|
self.allow_star = false
|
87
90
|
self.bin_path = ""
|
88
|
-
self.model_directories = ["#{app_root}/app/models/"]
|
91
|
+
self.model_directories = ["#{app_root}/app/models/"] +
|
92
|
+
Dir.glob("#{app_root}/vendor/plugins/*/app/models/")
|
93
|
+
self.delayed_job_priority = 0
|
89
94
|
|
90
95
|
self.source_options = {}
|
91
96
|
self.index_options = {
|
@@ -1,18 +1,11 @@
|
|
1
|
+
require 'zlib'
|
2
|
+
|
1
3
|
module ThinkingSphinx
|
2
4
|
module Core
|
3
5
|
module String
|
4
|
-
|
5
6
|
def to_crc32
|
6
|
-
|
7
|
-
self.each_byte do |byte|
|
8
|
-
result ^= byte
|
9
|
-
8.times do
|
10
|
-
result = (result >> 1) ^ (0xEDB88320 * (result & 1))
|
11
|
-
end
|
12
|
-
end
|
13
|
-
result ^ 0xFFFFFFFF
|
7
|
+
Zlib.crc32 self
|
14
8
|
end
|
15
|
-
|
16
9
|
end
|
17
10
|
end
|
18
11
|
end
|
@@ -11,18 +11,20 @@ module ThinkingSphinx
|
|
11
11
|
def index(model, instance = nil)
|
12
12
|
return true unless ThinkingSphinx.updates_enabled? &&
|
13
13
|
ThinkingSphinx.deltas_enabled?
|
14
|
+
return true if instance && !toggled(instance)
|
14
15
|
|
15
16
|
config = ThinkingSphinx::Configuration.instance
|
16
17
|
client = Riddle::Client.new config.address, config.port
|
18
|
+
rotate = ThinkingSphinx.sphinx_running? ? "--rotate" : ""
|
19
|
+
|
20
|
+
output = `#{config.bin_path}indexer --config #{config.config_file} #{rotate} #{delta_index_name model}`
|
21
|
+
puts(output) unless ThinkingSphinx.suppress_delta_output?
|
17
22
|
|
18
23
|
client.update(
|
19
24
|
core_index_name(model),
|
20
25
|
['sphinx_deleted'],
|
21
26
|
{instance.sphinx_document_id => [1]}
|
22
|
-
) if instance && ThinkingSphinx.sphinx_running? && instance.
|
23
|
-
|
24
|
-
output = `#{config.bin_path}indexer --config #{config.config_file} --rotate #{delta_index_name model}`
|
25
|
-
puts output unless ThinkingSphinx.suppress_delta_output?
|
27
|
+
) if instance && ThinkingSphinx.sphinx_running? && instance.in_both_indexes?
|
26
28
|
|
27
29
|
true
|
28
30
|
end
|
@@ -37,7 +39,8 @@ module ThinkingSphinx
|
|
37
39
|
|
38
40
|
def reset_query(model)
|
39
41
|
"UPDATE #{model.quoted_table_name} SET " +
|
40
|
-
"#{@index.quote_column(@column.to_s)} = #{adapter.boolean(false)}"
|
42
|
+
"#{@index.quote_column(@column.to_s)} = #{adapter.boolean(false)} " +
|
43
|
+
"WHERE #{@index.quote_column(@column.to_s)} = #{adapter.boolean(true)}"
|
41
44
|
end
|
42
45
|
|
43
46
|
def clause(model, toggled)
|
@@ -9,13 +9,15 @@ module ThinkingSphinx
|
|
9
9
|
class DelayedDelta < ThinkingSphinx::Deltas::DefaultDelta
|
10
10
|
def index(model, instance = nil)
|
11
11
|
ThinkingSphinx::Deltas::Job.enqueue(
|
12
|
-
ThinkingSphinx::Deltas::DeltaJob.new(delta_index_name(model))
|
12
|
+
ThinkingSphinx::Deltas::DeltaJob.new(delta_index_name(model)),
|
13
|
+
ThinkingSphinx::Configuration.instance.delayed_job_priority
|
13
14
|
)
|
14
15
|
|
15
16
|
Delayed::Job.enqueue(
|
16
17
|
ThinkingSphinx::Deltas::FlagAsDeletedJob.new(
|
17
18
|
core_index_name(model), instance.sphinx_document_id
|
18
|
-
)
|
19
|
+
),
|
20
|
+
ThinkingSphinx::Configuration.instance.delayed_job_priority
|
19
21
|
) if instance
|
20
22
|
|
21
23
|
true
|
@@ -5,7 +5,8 @@ require 'thinking_sphinx/deltas/datetime_delta'
|
|
5
5
|
module ThinkingSphinx
|
6
6
|
module Deltas
|
7
7
|
def self.parse(index, options)
|
8
|
-
|
8
|
+
delta_option = options.delete(:delta)
|
9
|
+
case delta_option
|
9
10
|
when TrueClass, :default
|
10
11
|
DefaultDelta.new index, options
|
11
12
|
when :delayed
|
@@ -15,7 +16,11 @@ module ThinkingSphinx
|
|
15
16
|
when FalseClass, nil
|
16
17
|
nil
|
17
18
|
else
|
18
|
-
|
19
|
+
if delta_option.ancestors.include?(ThinkingSphinx::Deltas::DefaultDelta)
|
20
|
+
delta_option.new index, options
|
21
|
+
else
|
22
|
+
raise "Unknown delta type"
|
23
|
+
end
|
19
24
|
end
|
20
25
|
end
|
21
26
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
namespace :thinking_sphinx do
|
2
|
+
namespace :install do
|
3
|
+
desc "Install Sphinx by source"
|
4
|
+
task :sphinx do
|
5
|
+
with_postgres = false
|
6
|
+
run "which pg_config" do |channel, stream, data|
|
7
|
+
with_postgres = !(data.nil? || data == "")
|
8
|
+
end
|
9
|
+
|
10
|
+
args = []
|
11
|
+
if with_postgres
|
12
|
+
run "pg_config --pkgincludedir" do |channel, stream, data|
|
13
|
+
args << "--with-pgsql=#{data}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
commands = <<-CMD
|
18
|
+
wget -q http://www.sphinxsearch.com/downloads/sphinx-0.9.8.1.tar.gz >> sphinx.log
|
19
|
+
tar xzvf sphinx-0.9.8.1.tar.gz
|
20
|
+
cd sphinx-0.9.8.1
|
21
|
+
./configure #{args.join(" ")}
|
22
|
+
make
|
23
|
+
sudo make install
|
24
|
+
rm -rf sphinx-0.9.8.1 sphinx-0.9.8.1.tar.gz
|
25
|
+
CMD
|
26
|
+
run commands.split(/\n\s+/).join(" && ")
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "Install Thinking Sphinx as a gem from GitHub"
|
30
|
+
task :ts do
|
31
|
+
sudo "gem install freelancing-god-thinking-sphinx --source http://gems.github.com"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Generate the Sphinx configuration file"
|
36
|
+
task :configure do
|
37
|
+
rake "thinking_sphinx:configure"
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "Index data"
|
41
|
+
task :index do
|
42
|
+
rake "thinking_sphinx:index"
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Start the Sphinx daemon"
|
46
|
+
task :start do
|
47
|
+
configure
|
48
|
+
rake "thinking_sphinx:start"
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Stop the Sphinx daemon"
|
52
|
+
task :stop do
|
53
|
+
configure
|
54
|
+
rake "thinking_sphinx:stop"
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "Stop and then start the Sphinx daemon"
|
58
|
+
task :restart do
|
59
|
+
stop
|
60
|
+
start
|
61
|
+
end
|
62
|
+
|
63
|
+
desc "Stop, re-index and then start the Sphinx daemon"
|
64
|
+
task :rebuild do
|
65
|
+
stop
|
66
|
+
index
|
67
|
+
start
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "Add the shared folder for sphinx files for the production environment"
|
71
|
+
task :shared_sphinx_folder, :roles => :web do
|
72
|
+
sudo "mkdir -p #{shared_path}/db/sphinx/production"
|
73
|
+
end
|
74
|
+
|
75
|
+
def rake(*tasks)
|
76
|
+
tasks.each do |t|
|
77
|
+
run "cd #{current_path} && rake #{t} RAILS_ENV=production"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -9,25 +9,38 @@ module ThinkingSphinx
|
|
9
9
|
raise "Can't translate Facets on multiple-column field or attribute"
|
10
10
|
end
|
11
11
|
end
|
12
|
+
|
13
|
+
def self.name_for(facet)
|
14
|
+
case facet
|
15
|
+
when Facet
|
16
|
+
facet.name
|
17
|
+
when String, Symbol
|
18
|
+
facet.to_s.gsub(/(_facet|_crc)$/,'').to_sym
|
19
|
+
end
|
20
|
+
end
|
12
21
|
|
13
22
|
def name
|
14
23
|
reference.unique_name
|
15
24
|
end
|
25
|
+
|
26
|
+
def self.attribute_name_for(name)
|
27
|
+
name.to_s == 'class' ? 'class_crc' : "#{name}_facet"
|
28
|
+
end
|
16
29
|
|
17
30
|
def attribute_name
|
18
|
-
@attribute_name ||= case @reference
|
19
|
-
when Attribute
|
20
|
-
|
21
|
-
when Field
|
22
|
-
|
23
|
-
end
|
31
|
+
# @attribute_name ||= case @reference
|
32
|
+
# when Attribute
|
33
|
+
# @reference.unique_name.to_s
|
34
|
+
# when Field
|
35
|
+
@attribute_name ||= @reference.unique_name.to_s + "_facet"
|
36
|
+
# end
|
24
37
|
end
|
25
38
|
|
26
39
|
def value(object, attribute_value)
|
27
40
|
return translate(object, attribute_value) if @reference.is_a?(Field)
|
28
41
|
|
29
42
|
case @reference.type
|
30
|
-
when :string
|
43
|
+
when :string
|
31
44
|
translate(object, attribute_value)
|
32
45
|
when :datetime
|
33
46
|
Time.at(attribute_value)
|
@@ -42,7 +55,7 @@ module ThinkingSphinx
|
|
42
55
|
name
|
43
56
|
end
|
44
57
|
|
45
|
-
|
58
|
+
private
|
46
59
|
|
47
60
|
def translate(object, attribute_value)
|
48
61
|
column.__stack.each { |method|
|
@@ -55,4 +68,4 @@ module ThinkingSphinx
|
|
55
68
|
@reference.columns.first
|
56
69
|
end
|
57
70
|
end
|
58
|
-
end
|
71
|
+
end
|
@@ -5,20 +5,26 @@ module ThinkingSphinx
|
|
5
5
|
def initialize(arguments)
|
6
6
|
@arguments = arguments.clone
|
7
7
|
@attribute_values = {}
|
8
|
-
@
|
8
|
+
@facet_names = []
|
9
9
|
end
|
10
10
|
|
11
11
|
def add_from_results(facet, results)
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
name = ThinkingSphinx::Facet.name_for(facet)
|
13
|
+
|
14
|
+
self[name] ||= {}
|
15
|
+
@attribute_values[name] ||= {}
|
16
|
+
@facet_names << name
|
17
|
+
|
18
|
+
return if results.empty?
|
19
|
+
|
20
|
+
facet = facet_from_object(results.first, facet) if facet.is_a?(String)
|
15
21
|
|
16
22
|
results.each_with_groupby_and_count { |result, group, count|
|
17
23
|
facet_value = facet.value(result, group)
|
18
24
|
|
19
|
-
self[
|
20
|
-
self[
|
21
|
-
@attribute_values[
|
25
|
+
self[name][facet_value] ||= 0
|
26
|
+
self[name][facet_value] += count
|
27
|
+
@attribute_values[name][facet_value] = group
|
22
28
|
}
|
23
29
|
end
|
24
30
|
|
@@ -28,8 +34,8 @@ module ThinkingSphinx
|
|
28
34
|
options[:with] ||= {}
|
29
35
|
|
30
36
|
hash.each do |key, value|
|
31
|
-
attrib =
|
32
|
-
options[:with][attrib] =
|
37
|
+
attrib = ThinkingSphinx::Facet.attribute_name_for(key)
|
38
|
+
options[:with][attrib] = underlying_value key, value
|
33
39
|
end
|
34
40
|
|
35
41
|
arguments << options
|
@@ -38,8 +44,17 @@ module ThinkingSphinx
|
|
38
44
|
|
39
45
|
private
|
40
46
|
|
41
|
-
def
|
42
|
-
|
47
|
+
def underlying_value(key, value)
|
48
|
+
case value
|
49
|
+
when Array
|
50
|
+
value.collect { |item| underlying_value(key, item) }
|
51
|
+
else
|
52
|
+
@attribute_values[key][value]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def facet_from_object(object, name)
|
57
|
+
object.sphinx_facets.detect { |facet| facet.attribute_name == name }
|
43
58
|
end
|
44
59
|
end
|
45
|
-
end
|
60
|
+
end
|
@@ -7,9 +7,8 @@ module ThinkingSphinx
|
|
7
7
|
# generate SQL statements, you'll need to set the base model, and all the
|
8
8
|
# associations. Which can get messy. Use Index.link!, it really helps.
|
9
9
|
#
|
10
|
-
class Field
|
11
|
-
attr_accessor :
|
12
|
-
:prefixes, :faceted
|
10
|
+
class Field < ThinkingSphinx::Property
|
11
|
+
attr_accessor :sortable, :infixes, :prefixes
|
13
12
|
|
14
13
|
# To create a new field, you'll need to pass in either a single Column
|
15
14
|
# or an array of them, and some (optional) options. The columns are
|
@@ -54,16 +53,11 @@ module ThinkingSphinx
|
|
54
53
|
# )
|
55
54
|
#
|
56
55
|
def initialize(columns, options = {})
|
57
|
-
|
58
|
-
@associations = {}
|
59
|
-
|
60
|
-
raise "Cannot define a field with no columns. Maybe you are trying to index a field with a reserved name (id, name). You can fix this error by using a symbol rather than a bare name (:id instead of id)." if @columns.empty? || @columns.any? { |column| !column.respond_to?(:__stack) }
|
56
|
+
super
|
61
57
|
|
62
|
-
@alias = options[:as]
|
63
58
|
@sortable = options[:sortable] || false
|
64
59
|
@infixes = options[:infixes] || false
|
65
60
|
@prefixes = options[:prefixes] || false
|
66
|
-
@faceted = options[:facet] || false
|
67
61
|
end
|
68
62
|
|
69
63
|
# Get the part of the SELECT clause related to this field. Don't forget
|
@@ -77,96 +71,10 @@ module ThinkingSphinx
|
|
77
71
|
column_with_prefix(column)
|
78
72
|
}.join(', ')
|
79
73
|
|
80
|
-
clause = adapter.concatenate(clause)
|
74
|
+
clause = adapter.concatenate(clause) if concat_ws?
|
81
75
|
clause = adapter.group_concatenate(clause) if is_many?
|
82
76
|
|
83
77
|
"#{adapter.cast_to_string clause } AS #{quote_column(unique_name)}"
|
84
78
|
end
|
85
|
-
|
86
|
-
# Get the part of the GROUP BY clause related to this field - if one is
|
87
|
-
# needed. If not, all you'll get back is nil. The latter will happen if
|
88
|
-
# there's multiple data values (read: a has_many or has_and_belongs_to_many
|
89
|
-
# association).
|
90
|
-
#
|
91
|
-
def to_group_sql
|
92
|
-
case
|
93
|
-
when is_many?, ThinkingSphinx.use_group_by_shortcut?
|
94
|
-
nil
|
95
|
-
else
|
96
|
-
@columns.collect { |column|
|
97
|
-
column_with_prefix(column)
|
98
|
-
}
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
# Returns the unique name of the field - which is either the alias of
|
103
|
-
# the field, or the name of the only column - if there is only one. If
|
104
|
-
# there isn't, there should be an alias. Else things probably won't work.
|
105
|
-
# Consider yourself warned.
|
106
|
-
#
|
107
|
-
def unique_name
|
108
|
-
if @columns.length == 1
|
109
|
-
@alias || @columns.first.__name
|
110
|
-
else
|
111
|
-
@alias
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def to_facet
|
116
|
-
return nil unless @faceted
|
117
|
-
|
118
|
-
ThinkingSphinx::Facet.new(self)
|
119
|
-
end
|
120
|
-
|
121
|
-
private
|
122
|
-
|
123
|
-
def adapter
|
124
|
-
@adapter ||= @model.sphinx_database_adapter
|
125
|
-
end
|
126
|
-
|
127
|
-
def quote_column(column)
|
128
|
-
@model.connection.quote_column_name(column)
|
129
|
-
end
|
130
|
-
|
131
|
-
# Indication of whether the columns should be concatenated with a space
|
132
|
-
# between each value. True if there's either multiple sources or multiple
|
133
|
-
# associations.
|
134
|
-
#
|
135
|
-
def concat_ws?
|
136
|
-
@columns.length > 1 || multiple_associations?
|
137
|
-
end
|
138
|
-
|
139
|
-
# Checks whether any column requires multiple associations (which only
|
140
|
-
# happens for polymorphic situations).
|
141
|
-
#
|
142
|
-
def multiple_associations?
|
143
|
-
associations.any? { |col,assocs| assocs.length > 1 }
|
144
|
-
end
|
145
|
-
|
146
|
-
# Builds a column reference tied to the appropriate associations. This
|
147
|
-
# dives into the associations hash and their corresponding joins to
|
148
|
-
# figure out how to correctly reference a column in SQL.
|
149
|
-
#
|
150
|
-
def column_with_prefix(column)
|
151
|
-
if column.is_string?
|
152
|
-
column.__name
|
153
|
-
elsif associations[column].empty?
|
154
|
-
"#{@model.quoted_table_name}.#{quote_column(column.__name)}"
|
155
|
-
else
|
156
|
-
associations[column].collect { |assoc|
|
157
|
-
assoc.has_column?(column.__name) ?
|
158
|
-
"#{@model.connection.quote_table_name(assoc.join.aliased_table_name)}" +
|
159
|
-
".#{quote_column(column.__name)}" :
|
160
|
-
nil
|
161
|
-
}.compact.join(', ')
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
# Could there be more than one value related to the parent record? If so,
|
166
|
-
# then this will return true. If not, false. It's that simple.
|
167
|
-
#
|
168
|
-
def is_many?
|
169
|
-
associations.values.flatten.any? { |assoc| assoc.is_many? }
|
170
|
-
end
|
171
79
|
end
|
172
80
|
end
|
@@ -87,22 +87,16 @@ module ThinkingSphinx
|
|
87
87
|
def indexes(*args)
|
88
88
|
options = args.extract_options!
|
89
89
|
args.each do |columns|
|
90
|
-
|
90
|
+
field = Field.new(FauxColumn.coerce(columns), options)
|
91
|
+
fields << field
|
91
92
|
|
92
|
-
if
|
93
|
-
|
94
|
-
fields.last.columns.collect { |col| col.clone },
|
95
|
-
options.merge(
|
96
|
-
:type => :string,
|
97
|
-
:as => fields.last.unique_name.to_s.concat("_sort").to_sym
|
98
|
-
).except(:facet)
|
99
|
-
)
|
100
|
-
end
|
93
|
+
add_sort_attribute field, options if field.sortable
|
94
|
+
add_facet_attribute field, options if field.faceted
|
101
95
|
end
|
102
96
|
end
|
103
97
|
alias_method :field, :indexes
|
104
98
|
alias_method :includes, :indexes
|
105
|
-
|
99
|
+
|
106
100
|
# This is the method to add attributes to your index (hence why it is
|
107
101
|
# aliased as 'attribute'). The syntax is the same as #indexes, so use
|
108
102
|
# that as starting point, but keep in mind the following points.
|
@@ -142,7 +136,10 @@ module ThinkingSphinx
|
|
142
136
|
def has(*args)
|
143
137
|
options = args.extract_options!
|
144
138
|
args.each do |columns|
|
145
|
-
|
139
|
+
attribute = Attribute.new(FauxColumn.coerce(columns), options)
|
140
|
+
attributes << attribute
|
141
|
+
|
142
|
+
add_facet_attribute attribute, options if attribute.faceted
|
146
143
|
end
|
147
144
|
end
|
148
145
|
alias_method :attribute, :has
|
@@ -152,7 +149,10 @@ module ThinkingSphinx
|
|
152
149
|
options[:facet] = true
|
153
150
|
|
154
151
|
args.each do |columns|
|
155
|
-
|
152
|
+
attribute = Attribute.new(FauxColumn.coerce(columns), options)
|
153
|
+
attributes << attribute
|
154
|
+
|
155
|
+
add_facet_attribute attribute, options
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
@@ -200,7 +200,17 @@ module ThinkingSphinx
|
|
200
200
|
#
|
201
201
|
# Please don't forget to add a boolean field named 'delta' to your
|
202
202
|
# model's database table if enabling the delta index for it.
|
203
|
+
# Valid options for the delta property are:
|
203
204
|
#
|
205
|
+
# true
|
206
|
+
# false
|
207
|
+
# :default
|
208
|
+
# :delayed
|
209
|
+
# :datetime
|
210
|
+
#
|
211
|
+
# You can also extend ThinkingSphinx::Deltas::DefaultDelta to implement
|
212
|
+
# your own handling for delta indexing.
|
213
|
+
|
204
214
|
def set_property(*args)
|
205
215
|
options = args.extract_options!
|
206
216
|
if options.empty?
|
@@ -224,8 +234,29 @@ module ThinkingSphinx
|
|
224
234
|
#
|
225
235
|
# Example: indexes assoc(:properties).column
|
226
236
|
#
|
227
|
-
def assoc(assoc)
|
228
|
-
FauxColumn.new(
|
237
|
+
def assoc(assoc, *args)
|
238
|
+
FauxColumn.new(assoc, *args)
|
239
|
+
end
|
240
|
+
|
241
|
+
private
|
242
|
+
|
243
|
+
def add_sort_attribute(field, options)
|
244
|
+
add_internal_attribute field, options, "_sort"
|
245
|
+
end
|
246
|
+
|
247
|
+
def add_facet_attribute(resource, options)
|
248
|
+
add_internal_attribute resource, options, "_facet", true
|
249
|
+
end
|
250
|
+
|
251
|
+
def add_internal_attribute(resource, options, suffix, crc = false)
|
252
|
+
@attributes << Attribute.new(
|
253
|
+
resource.columns.collect { |col| col.clone },
|
254
|
+
options.merge(
|
255
|
+
:type => resource.is_a?(Field) ? :string : options[:type],
|
256
|
+
:as => resource.unique_name.to_s.concat(suffix).to_sym,
|
257
|
+
:crc => crc
|
258
|
+
).except(:facet)
|
259
|
+
)
|
229
260
|
end
|
230
261
|
end
|
231
262
|
end
|