class ThinkingSphinx::Property

Attributes

admin[RW]
alias[RW]
associations[RW]
columns[RW]
faceted[RW]
model[RW]

Public Class Methods

new(source, columns, options = {}) click to toggle source
# File lib/thinking_sphinx/property.rb, line 5
def initialize(source, columns, options = {})
  @source       = source
  @model        = source.model
  @columns      = Array(columns)
  @associations = {}

  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) }

  @alias        = options[:as]
  @faceted      = options[:facet]
  @admin        = options[:admin]
  @sortable     = options[:sortable] || false
  @value_source = options[:value]

  @alias    = @alias.to_sym unless @alias.blank?

  @columns.each { |col|
    @associations[col.__stack] = association_stack(col.__stack.clone).each { |assoc|
      assoc.join_to(source.base)
    }
  }
end

Public Instance Methods

admin?() click to toggle source
# File lib/thinking_sphinx/property.rb, line 72
def admin?
  admin
end
available?() click to toggle source
# File lib/thinking_sphinx/property.rb, line 80
def available?
  columns.any? { |column| column_available?(column) }
end
changed?(instance) click to toggle source
# File lib/thinking_sphinx/property.rb, line 64
def changed?(instance)
  return true if is_string? || @columns.any? { |col| !col.__stack.empty? }

  @columns.any? { |col|
    instance.send("#{col.__name.to_s}_changed?")
  }
end
public?() click to toggle source
# File lib/thinking_sphinx/property.rb, line 76
def public?
  !admin
end
to_facet() click to toggle source
# File lib/thinking_sphinx/property.rb, line 41
def to_facet
  return nil unless @faceted

  ThinkingSphinx::Facet.new(self, @value_source)
end
to_group_sql() click to toggle source

Get the part of the GROUP BY clause related to this attribute - if one is needed. If not, all you'll get back is nil. The latter will happen if there isn't actually a real column to get data from, or if there's multiple data values (read: a has_many or has_and_belongs_to_many association).

# File lib/thinking_sphinx/property.rb, line 53
def to_group_sql
  case
  when is_many?, is_string?, ThinkingSphinx.use_group_by_shortcut?
    nil
  else
    @columns.collect { |column|
      column_with_prefix(column)
    }
  end
end
unique_name() click to toggle source

Returns the unique name of the attribute - which is either the alias of the attribute, or the name of the only column - if there is only one. If there isn't, there should be an alias. Else things probably won't work. Consider yourself warned.

# File lib/thinking_sphinx/property.rb, line 33
def unique_name
  if @columns.length == 1
    @alias || @columns.first.__name
  else
    @alias
  end
end

Private Instance Methods

adapter() click to toggle source
# File lib/thinking_sphinx/property.rb, line 99
def adapter
  @adapter ||= @model.sphinx_database_adapter
end
association_stack(path, parent = nil) click to toggle source

Gets a stack of associations for a specific path.

# File lib/thinking_sphinx/property.rb, line 170
def association_stack(path, parent = nil)
  assocs = []

  if parent.nil?
    assocs = @source.association(path.shift)
  else
    assocs = parent.children(path.shift)
  end

  until path.empty?
    point  = path.shift
    assocs = assocs.collect { |assoc| assoc.children(point) }.flatten
  end

  assocs
end
column_available?(column) click to toggle source
# File lib/thinking_sphinx/property.rb, line 156
def column_available?(column)
  if column.is_string?
    true
  elsif column.__stack.empty?
    @model.column_names.include?(column.__name.to_s)
  else
    associations[column.__stack].any? { |assoc|
      assoc.has_column?(column.__name)
    }
  end
end
column_with_prefix(column) click to toggle source

Builds a column reference tied to the appropriate associations. This dives into the associations hash and their corresponding joins to figure out how to correctly reference a column in SQL.

# File lib/thinking_sphinx/property.rb, line 134
def column_with_prefix(column)
  return nil unless column_available?(column)

  if column.is_string?
    column.__name
  elsif column.__stack.empty?
    "#{@model.quoted_table_name}.#{quote_column(column.__name)}"
  else
    associations[column.__stack].collect { |assoc|
      assoc.has_column?(column.__name) ?
      "#{quote_with_table(assoc.join.aliased_table_name, column.__name)}" :
      nil
    }.compact
  end
end
columns_with_prefixes() click to toggle source
# File lib/thinking_sphinx/property.rb, line 150
def columns_with_prefixes
  @columns.collect { |column|
    column_with_prefix column
  }.flatten.compact
end
concat_ws?() click to toggle source

Indication of whether the columns should be concatenated with a space between each value. True if there's either multiple sources or multiple associations.

# File lib/thinking_sphinx/property.rb, line 119
def concat_ws?
  multiple_associations? || @columns.length > 1
end
is_many?() click to toggle source

Could there be more than one value related to the parent record? If so, then this will return true. If not, false. It's that simple.

# File lib/thinking_sphinx/property.rb, line 89
def is_many?
  associations.values.flatten.any? { |assoc| assoc.is_many? }
end
is_string?() click to toggle source

Returns true if any of the columns are string values, instead of database column references.

# File lib/thinking_sphinx/property.rb, line 95
def is_string?
  columns.all? { |col| col.is_string? }
end
multiple_associations?() click to toggle source

Checks whether any column requires multiple associations (which only happens for polymorphic situations).

# File lib/thinking_sphinx/property.rb, line 126
def multiple_associations?
  associations.values.any? { |assocs| assocs.length > 1 }
end
quote_column(column) click to toggle source
# File lib/thinking_sphinx/property.rb, line 107
def quote_column(column)
  @model.connection.quote_column_name(column)
end
quote_table_name(table_name) click to toggle source
# File lib/thinking_sphinx/property.rb, line 111
def quote_table_name(table_name)
  @model.connection.quote_table_name(table_name)
end
quote_with_table(table, column) click to toggle source
# File lib/thinking_sphinx/property.rb, line 103
def quote_with_table(table, column)
  "#{quote_table_name(table)}.#{quote_column(column)}"
end