# frozen_string_literal: true module ThinkingSphinx module ActiveRecord class Attribute; end end end require 'thinking_sphinx/errors' require 'thinking_sphinx/active_record/attribute/type' describe ThinkingSphinx::ActiveRecord::Attribute::Type do let(:type) { ThinkingSphinx::ActiveRecord::Attribute::Type.new attribute, model } let(:attribute) { double('attribute', :columns => [column], :options => {}) } let(:model) { double('model', :columns => [db_column]) } let(:column) { double('column', :__name => :created_at, :string? => false, :__stack => []) } let(:db_column) { double('column', :name => 'created_at', :type => :integer) } describe '#multi?' do let(:association) { double('association', :klass => double) } before :each do column.__stack << :foo allow(model).to receive(:reflect_on_association).and_return(association) end it "returns true if there are has_many associations" do allow(association).to receive(:macro).and_return(:has_many) expect(type).to be_multi end it "returns true if there are has_and_belongs_to_many associations" do allow(association).to receive(:macro).and_return(:has_and_belongs_to_many) expect(type).to be_multi end it "returns false if there are no associations" do column.__stack.clear expect(type).not_to be_multi end it "returns false if there are only belongs_to associations" do allow(association).to receive(:macro).and_return(:belongs_to) expect(type).not_to be_multi end it "returns false if there are only has_one associations" do allow(association).to receive(:macro).and_return(:has_one) expect(type).not_to be_multi end it "returns true if deeper associations have many" do column.__stack << :bar deep_association = double(:klass => double, :macro => :has_many) allow(association).to receive(:macro).and_return(:belongs_to) allow(association).to receive(:klass).and_return( double(:reflect_on_association => deep_association) ) expect(type).to be_multi end it "respects the provided setting" do attribute.options[:multi] = true expect(type).to be_multi end end describe '#type' do it "returns the type option provided" do attribute.options[:type] = :datetime expect(type.type).to eq(:datetime) end it "detects integer types from the database" do allow(db_column).to receive_messages(:type => :integer, :sql_type => 'integer(11)') expect(type.type).to eq(:integer) end it "detects boolean types from the database" do allow(db_column).to receive_messages(:type => :boolean) expect(type.type).to eq(:boolean) end it "detects datetime types from the database as timestamps" do allow(db_column).to receive_messages(:type => :datetime) expect(type.type).to eq(:timestamp) end it "detects date types from the database as timestamps" do allow(db_column).to receive_messages(:type => :date) expect(type.type).to eq(:timestamp) end it "detects string types from the database" do allow(db_column).to receive_messages(:type => :string) expect(type.type).to eq(:string) end it "detects text types from the database as strings" do allow(db_column).to receive_messages(:type => :text) expect(type.type).to eq(:string) end it "detects float types from the database" do allow(db_column).to receive_messages(:type => :float) expect(type.type).to eq(:float) end it "detects decimal types from the database as floats" do allow(db_column).to receive_messages(:type => :decimal) expect(type.type).to eq(:float) end it "detects big ints as big ints" do allow(db_column).to receive_messages :type => :bigint expect(type.type).to eq(:bigint) end it "detects large integers as big ints" do allow(db_column).to receive_messages :type => :integer, :sql_type => 'bigint(20)' expect(type.type).to eq(:bigint) end it "detects JSON" do allow(db_column).to receive_messages :type => :json expect(type.type).to eq(:json) end it "respects provided type setting" do attribute.options[:type] = :timestamp expect(type.type).to eq(:timestamp) end it 'raises an error if the database column does not exist' do model.columns.clear expect { type.type }.to raise_error(ThinkingSphinx::MissingColumnError) end end end