thinking-sphinx 2.0.6 → 2.0.7
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/HISTORY +157 -0
- data/lib/cucumber/thinking_sphinx/external_world.rb +12 -0
- data/lib/cucumber/thinking_sphinx/internal_world.rb +127 -0
- data/lib/cucumber/thinking_sphinx/sql_logger.rb +20 -0
- data/lib/thinking-sphinx.rb +1 -0
- data/lib/thinking_sphinx/action_controller.rb +31 -0
- data/lib/thinking_sphinx/active_record/attribute_updates.rb +53 -0
- data/lib/thinking_sphinx/active_record/collection_proxy.rb +40 -0
- data/lib/thinking_sphinx/active_record/collection_proxy_with_scopes.rb +27 -0
- data/lib/thinking_sphinx/active_record/delta.rb +65 -0
- data/lib/thinking_sphinx/active_record/has_many_association.rb +37 -0
- data/lib/thinking_sphinx/active_record/has_many_association_with_scopes.rb +21 -0
- data/lib/thinking_sphinx/active_record/log_subscriber.rb +61 -0
- data/lib/thinking_sphinx/active_record/scopes.rb +110 -0
- data/lib/thinking_sphinx/active_record.rb +383 -0
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +87 -0
- data/lib/thinking_sphinx/adapters/mysql_adapter.rb +62 -0
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +171 -0
- data/lib/thinking_sphinx/association.rb +229 -0
- data/lib/thinking_sphinx/attribute.rb +407 -0
- data/lib/thinking_sphinx/auto_version.rb +38 -0
- data/lib/thinking_sphinx/bundled_search.rb +44 -0
- data/lib/thinking_sphinx/class_facet.rb +20 -0
- data/lib/thinking_sphinx/configuration.rb +335 -0
- data/lib/thinking_sphinx/context.rb +77 -0
- data/lib/thinking_sphinx/core/string.rb +15 -0
- data/lib/thinking_sphinx/deltas/default_delta.rb +62 -0
- data/lib/thinking_sphinx/deltas.rb +28 -0
- data/lib/thinking_sphinx/deploy/capistrano.rb +99 -0
- data/lib/thinking_sphinx/excerpter.rb +23 -0
- data/lib/thinking_sphinx/facet.rb +128 -0
- data/lib/thinking_sphinx/facet_search.rb +170 -0
- data/lib/thinking_sphinx/field.rb +98 -0
- data/lib/thinking_sphinx/index/builder.rb +312 -0
- data/lib/thinking_sphinx/index/faux_column.rb +118 -0
- data/lib/thinking_sphinx/index.rb +157 -0
- data/lib/thinking_sphinx/join.rb +37 -0
- data/lib/thinking_sphinx/property.rb +185 -0
- data/lib/thinking_sphinx/railtie.rb +46 -0
- data/lib/thinking_sphinx/search.rb +995 -0
- data/lib/thinking_sphinx/search_methods.rb +439 -0
- data/lib/thinking_sphinx/sinatra.rb +7 -0
- data/lib/thinking_sphinx/source/internal_properties.rb +51 -0
- data/lib/thinking_sphinx/source/sql.rb +157 -0
- data/lib/thinking_sphinx/source.rb +194 -0
- data/lib/thinking_sphinx/tasks.rb +132 -0
- data/lib/thinking_sphinx/test.rb +55 -0
- data/lib/thinking_sphinx/version.rb +3 -0
- data/lib/thinking_sphinx.rb +296 -0
- metadata +53 -4
@@ -0,0 +1,118 @@
|
|
1
|
+
module ThinkingSphinx
|
2
|
+
class Index
|
3
|
+
# Instances of this class represent database columns and the stack of
|
4
|
+
# associations that lead from the base model to them.
|
5
|
+
#
|
6
|
+
# The name and stack are accessible through methods starting with __ to
|
7
|
+
# avoid conflicting with the method_missing calls that build the stack.
|
8
|
+
#
|
9
|
+
class FauxColumn
|
10
|
+
# Create a new column with a pre-defined stack. The top element in the
|
11
|
+
# stack will get shifted to be the name value.
|
12
|
+
#
|
13
|
+
def initialize(*stack)
|
14
|
+
@name = stack.pop
|
15
|
+
@stack = stack
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.coerce(columns)
|
19
|
+
case columns
|
20
|
+
when Symbol, String
|
21
|
+
FauxColumn.new(columns)
|
22
|
+
when Array
|
23
|
+
columns.collect { |col| FauxColumn.coerce(col) }
|
24
|
+
when FauxColumn
|
25
|
+
columns
|
26
|
+
else
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Can't use normal method name, as that could be an association or
|
32
|
+
# column name.
|
33
|
+
#
|
34
|
+
def __name
|
35
|
+
@name
|
36
|
+
end
|
37
|
+
|
38
|
+
# Can't use normal method name, as that could be an association or
|
39
|
+
# column name.
|
40
|
+
#
|
41
|
+
def __stack
|
42
|
+
@stack
|
43
|
+
end
|
44
|
+
|
45
|
+
def __path
|
46
|
+
@stack + [@name]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns true if the stack is empty *and* if the name is a string -
|
50
|
+
# which is an indication that of raw SQL, as opposed to a value from a
|
51
|
+
# table's column.
|
52
|
+
#
|
53
|
+
def is_string?
|
54
|
+
@name.is_a?(String) && @stack.empty?
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_ary
|
58
|
+
[self]
|
59
|
+
end
|
60
|
+
|
61
|
+
# This handles any 'invalid' method calls and sets them as the name,
|
62
|
+
# and pushing the previous name into the stack. The object returns
|
63
|
+
# itself.
|
64
|
+
#
|
65
|
+
# If there's a single argument, it becomes the name, and the method
|
66
|
+
# symbol goes into the stack as well. Multiple arguments means new
|
67
|
+
# columns with the original stack and new names (from each argument) gets
|
68
|
+
# returned.
|
69
|
+
#
|
70
|
+
# Easier to explain with examples:
|
71
|
+
#
|
72
|
+
# col = FauxColumn.new :a, :b, :c
|
73
|
+
# col.__name #=> :c
|
74
|
+
# col.__stack #=> [:a, :b]
|
75
|
+
#
|
76
|
+
# col.whatever #=> col
|
77
|
+
# col.__name #=> :whatever
|
78
|
+
# col.__stack #=> [:a, :b, :c]
|
79
|
+
#
|
80
|
+
# col.something(:id) #=> col
|
81
|
+
# col.__name #=> :id
|
82
|
+
# col.__stack #=> [:a, :b, :c, :whatever, :something]
|
83
|
+
#
|
84
|
+
# cols = col.short(:x, :y, :z)
|
85
|
+
# cols[0].__name #=> :x
|
86
|
+
# cols[0].__stack #=> [:a, :b, :c, :whatever, :something, :short]
|
87
|
+
# cols[1].__name #=> :y
|
88
|
+
# cols[1].__stack #=> [:a, :b, :c, :whatever, :something, :short]
|
89
|
+
# cols[2].__name #=> :z
|
90
|
+
# cols[2].__stack #=> [:a, :b, :c, :whatever, :something, :short]
|
91
|
+
#
|
92
|
+
# Also, this allows method chaining to build up a relevant stack:
|
93
|
+
#
|
94
|
+
# col = FauxColumn.new :a, :b
|
95
|
+
# col.__name #=> :b
|
96
|
+
# col.__stack #=> [:a]
|
97
|
+
#
|
98
|
+
# col.one.two.three #=> col
|
99
|
+
# col.__name #=> :three
|
100
|
+
# col.__stack #=> [:a, :b, :one, :two]
|
101
|
+
#
|
102
|
+
def method_missing(method, *args)
|
103
|
+
@stack << @name
|
104
|
+
@name = method
|
105
|
+
|
106
|
+
if (args.empty?)
|
107
|
+
self
|
108
|
+
elsif (args.length == 1)
|
109
|
+
method_missing(args.first)
|
110
|
+
else
|
111
|
+
args.collect { |arg|
|
112
|
+
FauxColumn.new(@stack + [@name, arg])
|
113
|
+
}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'thinking_sphinx/index/builder'
|
2
|
+
require 'thinking_sphinx/index/faux_column'
|
3
|
+
|
4
|
+
module ThinkingSphinx
|
5
|
+
class Index
|
6
|
+
attr_accessor :name, :model, :sources, :delta_object
|
7
|
+
|
8
|
+
# Create a new index instance by passing in the model it is tied to, and
|
9
|
+
# a block to build it with (optional but recommended). For documentation
|
10
|
+
# on the syntax for inside the block, the Builder class is what you want.
|
11
|
+
#
|
12
|
+
# Quick Example:
|
13
|
+
#
|
14
|
+
# Index.new(User) do
|
15
|
+
# indexes login, email
|
16
|
+
#
|
17
|
+
# has created_at
|
18
|
+
#
|
19
|
+
# set_property :delta => true
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
def initialize(model, &block)
|
23
|
+
@name = self.class.name_for model
|
24
|
+
@model = model
|
25
|
+
@sources = []
|
26
|
+
@options = {}
|
27
|
+
@delta_object = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def fields
|
31
|
+
@sources.collect { |source| source.fields }.flatten
|
32
|
+
end
|
33
|
+
|
34
|
+
def attributes
|
35
|
+
@sources.collect { |source| source.attributes }.flatten
|
36
|
+
end
|
37
|
+
|
38
|
+
def core_name
|
39
|
+
"#{name}_core"
|
40
|
+
end
|
41
|
+
|
42
|
+
def delta_name
|
43
|
+
"#{name}_delta"
|
44
|
+
end
|
45
|
+
|
46
|
+
def all_names
|
47
|
+
names = [core_name]
|
48
|
+
names << delta_name if delta?
|
49
|
+
|
50
|
+
names
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.name_for(model)
|
54
|
+
model.name.underscore.tr(':/\\', '_')
|
55
|
+
end
|
56
|
+
|
57
|
+
def prefix_fields
|
58
|
+
fields.select { |field| field.prefixes }
|
59
|
+
end
|
60
|
+
|
61
|
+
def infix_fields
|
62
|
+
fields.select { |field| field.infixes }
|
63
|
+
end
|
64
|
+
|
65
|
+
def local_options
|
66
|
+
@options
|
67
|
+
end
|
68
|
+
|
69
|
+
def options
|
70
|
+
all_index_options = config.index_options.clone
|
71
|
+
@options.keys.select { |key|
|
72
|
+
ThinkingSphinx::Configuration::IndexOptions.include?(key.to_s) ||
|
73
|
+
ThinkingSphinx::Configuration::CustomOptions.include?(key.to_s)
|
74
|
+
}.each { |key| all_index_options[key.to_sym] = @options[key] }
|
75
|
+
all_index_options
|
76
|
+
end
|
77
|
+
|
78
|
+
def delta?
|
79
|
+
!@delta_object.nil?
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_riddle(offset)
|
83
|
+
indexes = [to_riddle_for_core(offset)]
|
84
|
+
indexes << to_riddle_for_delta(offset) if delta?
|
85
|
+
indexes << to_riddle_for_distributed
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def adapter
|
91
|
+
@adapter ||= @model.sphinx_database_adapter
|
92
|
+
end
|
93
|
+
|
94
|
+
def utf8?
|
95
|
+
options[:charset_type] == "utf-8"
|
96
|
+
end
|
97
|
+
|
98
|
+
def sql_query_pre_for_delta
|
99
|
+
[""]
|
100
|
+
end
|
101
|
+
|
102
|
+
def config
|
103
|
+
@config ||= ThinkingSphinx::Configuration.instance
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_riddle_for_core(offset)
|
107
|
+
index = Riddle::Configuration::Index.new core_name
|
108
|
+
index.path = File.join config.searchd_file_path, index.name
|
109
|
+
|
110
|
+
set_configuration_options_for_indexes index
|
111
|
+
set_field_settings_for_indexes index
|
112
|
+
|
113
|
+
sources.each_with_index do |source, i|
|
114
|
+
index.sources << source.to_riddle_for_core(offset, i)
|
115
|
+
end
|
116
|
+
|
117
|
+
index
|
118
|
+
end
|
119
|
+
|
120
|
+
def to_riddle_for_delta(offset)
|
121
|
+
index = Riddle::Configuration::Index.new delta_name
|
122
|
+
index.parent = core_name
|
123
|
+
index.path = File.join config.searchd_file_path, index.name
|
124
|
+
|
125
|
+
sources.each_with_index do |source, i|
|
126
|
+
index.sources << source.to_riddle_for_delta(offset, i)
|
127
|
+
end
|
128
|
+
|
129
|
+
index
|
130
|
+
end
|
131
|
+
|
132
|
+
def to_riddle_for_distributed
|
133
|
+
index = Riddle::Configuration::DistributedIndex.new name
|
134
|
+
index.local_indexes << core_name
|
135
|
+
index.local_indexes.unshift delta_name if delta?
|
136
|
+
index
|
137
|
+
end
|
138
|
+
|
139
|
+
def set_configuration_options_for_indexes(index)
|
140
|
+
config.index_options.each do |key, value|
|
141
|
+
method = "#{key}=".to_sym
|
142
|
+
index.send(method, value) if index.respond_to?(method)
|
143
|
+
end
|
144
|
+
|
145
|
+
options.each do |key, value|
|
146
|
+
index.send("#{key}=".to_sym, value) if ThinkingSphinx::Configuration::IndexOptions.include?(key.to_s) && !value.nil?
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def set_field_settings_for_indexes(index)
|
151
|
+
field_names = lambda { |field| field.unique_name.to_s }
|
152
|
+
|
153
|
+
index.prefix_field_names += prefix_fields.collect(&field_names)
|
154
|
+
index.infix_field_names += infix_fields.collect(&field_names)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ThinkingSphinx
|
2
|
+
class Join
|
3
|
+
attr_accessor :source, :column, :associations
|
4
|
+
|
5
|
+
def initialize(source, column)
|
6
|
+
@source = source
|
7
|
+
@column = column
|
8
|
+
|
9
|
+
@associations = association_stack(column.__path.clone).each { |assoc|
|
10
|
+
assoc.join_to(source.base)
|
11
|
+
}
|
12
|
+
|
13
|
+
source.joins << self
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Gets a stack of associations for a specific path.
|
19
|
+
#
|
20
|
+
def association_stack(path, parent = nil)
|
21
|
+
assocs = []
|
22
|
+
|
23
|
+
if parent.nil?
|
24
|
+
assocs = @source.association(path.shift)
|
25
|
+
else
|
26
|
+
assocs = parent.children(path.shift)
|
27
|
+
end
|
28
|
+
|
29
|
+
until path.empty?
|
30
|
+
point = path.shift
|
31
|
+
assocs = assocs.collect { |assoc| assoc.children(point) }.flatten
|
32
|
+
end
|
33
|
+
|
34
|
+
assocs
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
module ThinkingSphinx
|
2
|
+
class Property
|
3
|
+
attr_accessor :alias, :columns, :associations, :model, :faceted, :admin
|
4
|
+
|
5
|
+
def initialize(source, columns, options = {})
|
6
|
+
@source = source
|
7
|
+
@model = source.model
|
8
|
+
@columns = Array(columns)
|
9
|
+
@associations = {}
|
10
|
+
|
11
|
+
raise "Cannot define a field or attribute in #{source.model.name} 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) }
|
12
|
+
|
13
|
+
@alias = options[:as]
|
14
|
+
@faceted = options[:facet]
|
15
|
+
@admin = options[:admin]
|
16
|
+
@sortable = options[:sortable] || false
|
17
|
+
@value_source = options[:value]
|
18
|
+
|
19
|
+
@alias = @alias.to_sym unless @alias.blank?
|
20
|
+
|
21
|
+
@columns.each { |col|
|
22
|
+
@associations[col] = association_stack(col.__stack.clone).each { |assoc|
|
23
|
+
assoc.join_to(source.base)
|
24
|
+
}
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the unique name of the attribute - which is either the alias of
|
29
|
+
# the attribute, or the name of the only column - if there is only one. If
|
30
|
+
# there isn't, there should be an alias. Else things probably won't work.
|
31
|
+
# Consider yourself warned.
|
32
|
+
#
|
33
|
+
def unique_name
|
34
|
+
if @columns.length == 1
|
35
|
+
@alias || @columns.first.__name
|
36
|
+
else
|
37
|
+
@alias
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_facet
|
42
|
+
return nil unless @faceted
|
43
|
+
|
44
|
+
ThinkingSphinx::Facet.new(self, @value_source)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Get the part of the GROUP BY clause related to this attribute - if one is
|
48
|
+
# needed. If not, all you'll get back is nil. The latter will happen if
|
49
|
+
# there isn't actually a real column to get data from, or if there's
|
50
|
+
# multiple data values (read: a has_many or has_and_belongs_to_many
|
51
|
+
# association).
|
52
|
+
#
|
53
|
+
def to_group_sql
|
54
|
+
case
|
55
|
+
when is_many?, is_string?, ThinkingSphinx.use_group_by_shortcut?
|
56
|
+
nil
|
57
|
+
else
|
58
|
+
@columns.collect { |column|
|
59
|
+
column_with_prefix(column)
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def changed?(instance)
|
65
|
+
return true if is_string? || @columns.any? { |col| !col.__stack.empty? }
|
66
|
+
|
67
|
+
@columns.any? { |col|
|
68
|
+
instance.send("#{col.__name.to_s}_changed?")
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def admin?
|
73
|
+
admin
|
74
|
+
end
|
75
|
+
|
76
|
+
def public?
|
77
|
+
!admin
|
78
|
+
end
|
79
|
+
|
80
|
+
def available?
|
81
|
+
columns.any? { |column| column_available?(column) }
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
# Could there be more than one value related to the parent record? If so,
|
87
|
+
# then this will return true. If not, false. It's that simple.
|
88
|
+
#
|
89
|
+
def is_many?
|
90
|
+
associations.values.flatten.any? { |assoc| assoc.is_many? }
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns true if any of the columns are string values, instead of database
|
94
|
+
# column references.
|
95
|
+
def is_string?
|
96
|
+
columns.all? { |col| col.is_string? }
|
97
|
+
end
|
98
|
+
|
99
|
+
def adapter
|
100
|
+
@adapter ||= @model.sphinx_database_adapter
|
101
|
+
end
|
102
|
+
|
103
|
+
def quote_with_table(table, column)
|
104
|
+
"#{quote_table_name(table)}.#{quote_column(column)}"
|
105
|
+
end
|
106
|
+
|
107
|
+
def quote_column(column)
|
108
|
+
@model.connection.quote_column_name(column)
|
109
|
+
end
|
110
|
+
|
111
|
+
def quote_table_name(table_name)
|
112
|
+
@model.connection.quote_table_name(table_name)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Indication of whether the columns should be concatenated with a space
|
116
|
+
# between each value. True if there's either multiple sources or multiple
|
117
|
+
# associations.
|
118
|
+
#
|
119
|
+
def concat_ws?
|
120
|
+
multiple_associations? || @columns.length > 1
|
121
|
+
end
|
122
|
+
|
123
|
+
# Checks whether any column requires multiple associations (which only
|
124
|
+
# happens for polymorphic situations).
|
125
|
+
#
|
126
|
+
def multiple_associations?
|
127
|
+
associations.any? { |col,assocs| assocs.length > 1 }
|
128
|
+
end
|
129
|
+
|
130
|
+
# Builds a column reference tied to the appropriate associations. This
|
131
|
+
# dives into the associations hash and their corresponding joins to
|
132
|
+
# figure out how to correctly reference a column in SQL.
|
133
|
+
#
|
134
|
+
def column_with_prefix(column)
|
135
|
+
return nil unless column_available?(column)
|
136
|
+
|
137
|
+
if column.is_string?
|
138
|
+
column.__name
|
139
|
+
elsif column.__stack.empty?
|
140
|
+
"#{@model.quoted_table_name}.#{quote_column(column.__name)}"
|
141
|
+
else
|
142
|
+
associations[column].collect { |assoc|
|
143
|
+
assoc.has_column?(column.__name) ?
|
144
|
+
"#{quote_with_table(assoc.join.aliased_table_name, column.__name)}" :
|
145
|
+
nil
|
146
|
+
}.compact
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def columns_with_prefixes
|
151
|
+
@columns.collect { |column|
|
152
|
+
column_with_prefix column
|
153
|
+
}.flatten.compact
|
154
|
+
end
|
155
|
+
|
156
|
+
def column_available?(column)
|
157
|
+
if column.is_string?
|
158
|
+
true
|
159
|
+
elsif column.__stack.empty?
|
160
|
+
@model.column_names.include?(column.__name.to_s)
|
161
|
+
else
|
162
|
+
associations[column].any? { |assoc| assoc.has_column?(column.__name) }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Gets a stack of associations for a specific path.
|
167
|
+
#
|
168
|
+
def association_stack(path, parent = nil)
|
169
|
+
assocs = []
|
170
|
+
|
171
|
+
if parent.nil?
|
172
|
+
assocs = @source.association(path.shift)
|
173
|
+
else
|
174
|
+
assocs = parent.children(path.shift)
|
175
|
+
end
|
176
|
+
|
177
|
+
until path.empty?
|
178
|
+
point = path.shift
|
179
|
+
assocs = assocs.collect { |assoc| assoc.children(point) }.flatten
|
180
|
+
end
|
181
|
+
|
182
|
+
assocs
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'thinking_sphinx'
|
2
|
+
require 'rails'
|
3
|
+
|
4
|
+
module ThinkingSphinx
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
|
7
|
+
initializer 'thinking_sphinx.sphinx' do
|
8
|
+
ThinkingSphinx::AutoVersion.detect
|
9
|
+
end
|
10
|
+
|
11
|
+
initializer "thinking_sphinx.active_record" do
|
12
|
+
ActiveSupport.on_load :active_record do
|
13
|
+
include ThinkingSphinx::ActiveRecord
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
initializer "thinking_sphinx.action_controller" do
|
18
|
+
ActiveSupport.on_load :action_controller do
|
19
|
+
require 'thinking_sphinx/action_controller'
|
20
|
+
include ThinkingSphinx::ActionController
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
initializer "thinking_sphinx.set_app_root" do |app|
|
25
|
+
ThinkingSphinx::Configuration.instance.reset # Rails has setup app now
|
26
|
+
end
|
27
|
+
|
28
|
+
config.to_prepare do
|
29
|
+
I18n.backend.reload!
|
30
|
+
I18n.backend.available_locales
|
31
|
+
|
32
|
+
# ActiveRecord::Base.to_crc32s is dependant on the subclasses being loaded
|
33
|
+
# consistently. When the environment is reset, subclasses/descendants will
|
34
|
+
# be lost but our context will not reload them for us.
|
35
|
+
#
|
36
|
+
# We reset the context which causes the subclasses/descendants to be
|
37
|
+
# reloaded next time the context is called.
|
38
|
+
#
|
39
|
+
ThinkingSphinx.reset_context!
|
40
|
+
end
|
41
|
+
|
42
|
+
rake_tasks do
|
43
|
+
load File.expand_path('../tasks.rb', __FILE__)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|