Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Allow fields across belongs_to relationships to be included in the in…

…dex data.

Switch from klass to sphincter_klass and use the actual class name.

[git-p4: depot-paths = "//src/Sphincter/dev/": change = 3356]
  • Loading branch information...
commit b75fd3f06bcea4d2956667a48db1185e3f44c4d8 1 parent c6f809a
@drbrain drbrain authored
View
5 History.txt
@@ -1,3 +1,8 @@
+== 1.1.0 / ??
+
+* N major enhancements
+ * Fields across belongs_to relationships may be included via add_index.
+
== 1.0.0 / 2007-07-26
* 1 major enhancement
View
65 lib/sphincter/configure.rb
@@ -171,6 +171,8 @@ def self.get_conf_from(file)
def self.get_sources
load_models
+ index_defaults = { :conditions => [], :fields => [], :include => [] }
+
indexes = Sphincter::Search.indexes
index_count # HACK necessary to set options[:index_id] per-index
@@ -178,33 +180,54 @@ def self.get_sources
indexes.each do |klass, model_indexes|
model_indexes.each do |options|
+ source_conf = {}
+ fields = []
+ where = []
+
+ options = index_defaults.merge options
conn = klass.connection
table = klass.table_name
+ tables = [table]
pk = conn.quote_column_name klass.primary_key
index_id = options[:index_id]
- source_conf = {}
source_conf['sql_date_column'] = []
source_conf['sql_group_column'] = %w[sphincter_index_id]
- fields = []
fields << "(#{table}.#{pk} * #{index_count} + #{index_id}) AS #{pk}"
fields << "#{index_id} AS sphincter_index_id"
- fields << "#{conn.quote table} AS klass"
+ fields << "'#{klass.name}' AS sphincter_klass"
options[:fields].each do |field|
fields << get_sources_field(source_conf, klass, field)
end
+ options[:include].each do |as_include|
+ as_name, as_field = as_include.split '.', 2
+
+ as_assoc = klass.reflect_on_all_associations.find do |assoc|
+ assoc.name == as_name.intern
+ end
+
+ as_klass = as_assoc.class_name.constantize
+ as_table = as_klass.table_name
+ as_pkey = conn.quote_column_name as_assoc.primary_key_name.to_s
+ as_fkey = conn.quote_column_name as_klass.primary_key.to_s
+
+ tables << as_table
+ fields << get_sources_field(source_conf, as_klass, as_field, as_table)
+ where << "#{table}.#{as_pkey} = #{as_table}.#{as_fkey}"
+ end
+
fields = fields.join ', '
- where = []
- where << "#{table}.#{pk} >= $start AND #{table}.#{pk} <= $end"
- where << options[:conditions]
+ where << "#{table}.#{pk} >= $start"
+ where << "#{table}.#{pk} <= $end"
+ where.push(*options[:conditions])
where = where.compact.join ' AND '
source_conf['sql_query'] =
- "SELECT #{fields} FROM #{table} WHERE #{where}"
+ "SELECT #{fields} FROM #{tables.join ', '} WHERE #{where}"
source_conf['sql_query_info'] =
"SELECT * FROM #{table} " \
"WHERE #{table}.#{pk} = (($id - #{index_id}) / #{index_count})"
@@ -226,21 +249,27 @@ def self.get_sources
# get_sources_field only understands :datetime, :boolean, :integer, :string
# and :text column types.
- def self.get_sources_field(source_conf, klass, field)
+ def self.get_sources_field(source_conf, klass, field, as_table = nil)
conn = klass.connection
table = klass.table_name
quoted_field = conn.quote_column_name field
- case klass.columns_hash[field].type
- when :date, :datetime, :time, :timestamp then
- source_conf['sql_date_column'] << field
- "UNIX_TIMESTAMP(#{table}.#{quoted_field}) AS #{quoted_field}"
- when :boolean, :integer then
- source_conf['sql_group_column'] << field
- "#{table}.#{quoted_field} AS #{quoted_field}"
- when :string, :text then
- "#{table}.#{quoted_field} AS #{quoted_field}"
- end
+
+ type = case klass.columns_hash[field].type
+ when :date, :datetime, :time, :timestamp then
+ source_conf['sql_date_column'] << field
+ "UNIX_TIMESTAMP(#{table}.#{quoted_field})"
+ when :boolean, :integer then
+ source_conf['sql_group_column'] << field
+ "#{table}.#{quoted_field}"
+ when :string, :text then
+ "#{table}.#{quoted_field}"
+ end
+
+ as_name = [as_table, field].compact.join '_'
+ as_name = conn.quote_column_name as_name
+
+ "#{type} AS #{as_name}"
end
##
View
20 lib/sphincter/search.rb
@@ -44,10 +44,22 @@ def self.indexes
# Options are:
#
# :name:: Name of index. Defaults to ActiveRecord::Base::table_name.
- # :fields:: Fields to index. Columns from belongs_to associations are
- # automatically added.
- # :conditions:: Hash of SQL conditions that predicate inclusion in the
- # search index.
+ # :fields:: Array of fields to index. Foreign key columns for belongs_to
+ # associations are automatically added.
+ # :include:: Array of columns from belongs_to associations to include in the
+ # index.
+ # :conditions:: Array of SQL conditions that will be ANDed together to
+ # predicate inclusion in the search index.
+ #
+ # Example:
+ #
+ # class Post < ActiveRecord::Base
+ # belongs_to :user
+ # belongs_to :blog
+ #
+ # add_index :fields => %w[title body], :include => %w[user.name],
+ # :conditions => ['published = 1']
+ # end
def add_index(options = {})
options[:fields] ||= []
View
12 test/sphincter_test_case.rb
@@ -87,22 +87,22 @@ def initialize(type)
end
class Connection
- def quote(name) "`#{name}`" end
+ def quote(name) "'#{name}'" end
def quote_column_name(name) "`#{name}`" end
end
class Reflection
attr_accessor :klass
- attr_reader :macro, :options
+ attr_reader :macro, :options, :name
def initialize(macro, name)
@klass = Model
@macro = macro
- @name = name
+ @name = name.intern
@options = {}
end
- def class_name() "SphincterTestCase::#{@name.capitalize}" end
+ def class_name() @name.to_s.capitalize end
def primary_key_name() "#{@name}_id" end
end
@@ -130,6 +130,8 @@ def self.columns_hash
def self.find(ids) ids end
+ def self.name() 'Model' end
+
def self.primary_key() 'id' end
def self.reflect_on_all_associations
@@ -144,6 +146,8 @@ class Other < Model
@reflections = [Reflection.new(:belongs_to, 'model'),
Reflection.new(:has_many, 'model')]
+ def self.table_name() 'others' end
+
def id() 42 end
end
View
33 test/test_sphincter_configure.rb
@@ -6,7 +6,6 @@ class TestSphincterConfigure < SphincterTestCase
DEFAULT_GET_CONF_EXPECTED = {
"mysql" => {
"sql_query_pre" => [
- "SET SESSION group_concat_max_len = 65535",
"SET NAMES utf8",
]
},
@@ -142,7 +141,7 @@ def test_self_get_sources
"sql_query" =>
"SELECT (models.`id` * 1 + 0) AS `id`, " \
"0 AS sphincter_index_id, " \
- "`models` AS klass, "\
+ "'Model' AS sphincter_klass, "\
"models.`text` AS `text` " \
"FROM models WHERE models.`id` >= $start AND " \
"models.`id` <= $end"
@@ -152,6 +151,36 @@ def test_self_get_sources
assert_equal expected, Sphincter::Configure.get_sources
end
+ def test_self_get_sources_include
+ Sphincter::Search.indexes[Model] << {
+ :fields => %w[text],
+ :include => %w[other.string]
+ }
+
+ expected = {
+ "models" => {
+ "strip_html" => 0,
+ "sql_group_column" => ["sphincter_index_id"],
+ "sql_query_range" => "SELECT MIN(`id`), MAX(`id`) FROM models",
+ "sql_query_info" =>
+ "SELECT * FROM models WHERE models.`id` = (($id - 0) / 1)",
+ "sql_date_column" => [],
+ "sql_query" =>
+ "SELECT (models.`id` * 1 + 0) AS `id`, " \
+ "0 AS sphincter_index_id, " \
+ "'Model' AS sphincter_klass, " \
+ "models.`text` AS `text`, " \
+ "others.`string` AS `others_string` " \
+ "FROM models, others " \
+ "WHERE models.`other_id` = others.`id` AND "\
+ "models.`id` >= $start AND " \
+ "models.`id` <= $end"
+ }
+ }
+
+ assert_equal expected, Sphincter::Configure.get_sources
+ end
+
def test_self_get_sources_field
source_conf = { 'sql_group_column' => [], 'sql_date_column' => [] }
klass = Model
Please sign in to comment.
Something went wrong with that request. Please try again.