# frozen_string_literal: true class ThinkingSphinx::ActiveRecord::Attribute::Type UPDATEABLE_TYPES = [:integer, :timestamp, :boolean, :float] def initialize(attribute, model) @attribute, @model = attribute, model end def multi? @multi ||= attribute.options[:multi] || multi_from_associations end def timestamp? type == :timestamp end def type @type ||= attribute.options[:type] || type_from_database end def type=(value) @type = attribute.options[:type] = value end def updateable? UPDATEABLE_TYPES.include?(type) && single_column_reference? end private attr_reader :attribute, :model def associations @associations ||= begin klass = model attribute.columns.first.__stack.collect { |name| association = klass.reflect_on_association(name) klass = association.klass association } end end def big_integer? type_symbol == :integer && database_column.sql_type[/bigint/i] end def column_name attribute.columns.first.__name.to_s end def database_column @database_column ||= klass.columns.detect { |db_column| db_column.name == column_name } end def klass @klass ||= associations.any? ? associations.last.klass : model end def multi_from_associations associations.any? { |association| [:has_many, :has_and_belongs_to_many].include?(association.macro) } end def single_column_reference? attribute.columns.length == 1 && attribute.columns.first.__stack.length == 0 && !attribute.columns.first.string? end def type_from_database raise ThinkingSphinx::MissingColumnError, "Cannot determine the database type of column #{column_name}, as it does not exist" if database_column.nil? return :bigint if big_integer? case type_symbol when :datetime, :date :timestamp when :text :string when :decimal :float when :integer, :boolean, :timestamp, :float, :string, :bigint, :json type_symbol else raise ThinkingSphinx::UnknownAttributeType, <<-ERROR Unable to determine an equivalent Sphinx attribute type from #{database_column.type.class.name} for attribute #{attribute.name}. You may want to manually set the type. e.g. has my_column, :type => :integer ERROR end end def type_symbol return database_column.type if database_column.type.is_a?(Symbol) database_column.type.class.name.demodulize.downcase.to_sym end end