require 'spec_helper' describe ThinkingSphinx::ActiveRecord::Associations do JoinDependency = ::ActiveRecord::Associations::JoinDependency let(:associations) { ThinkingSphinx::ActiveRecord::Associations.new model } let(:model) { model_double 'articles' } let(:base) { double('base', :active_record => model, :join_base => join_base) } let(:join_base) { double('join base') } let(:join) { join_double 'users' } let(:sub_join) { join_double 'posts' } def join_double(table_alias) double 'join', :join_type= => nil, :aliased_table_name => table_alias, :reflection => double('reflection') end def model_double(table_name = nil) double 'model', :quoted_table_name => table_name, :reflections => {} end before :each do JoinDependency.stub :new => base JoinDependency::JoinAssociation.stub(:new).and_return(join, sub_join) model.reflections[:user] = join.reflection join.stub :active_record => model_double join.active_record.reflections[:posts] = sub_join.reflection end describe '#add_join_to' do it "adds just one join for a stack with a single association" do JoinDependency::JoinAssociation.unstub :new JoinDependency::JoinAssociation.should_receive(:new). with(join.reflection, base, join_base).once.and_return(join) associations.add_join_to([:user]) end it "does not duplicate joins when given the same stack twice" do JoinDependency::JoinAssociation.unstub :new JoinDependency::JoinAssociation.should_receive(:new).once.and_return(join) associations.add_join_to([:user]) associations.add_join_to([:user]) end context 'multiple joins' do it "adds two joins for a stack with two associations" do JoinDependency::JoinAssociation.unstub :new JoinDependency::JoinAssociation.should_receive(:new). with(join.reflection, base, join_base).once.and_return(join) JoinDependency::JoinAssociation.should_receive(:new). with(sub_join.reflection, base, join).once.and_return(sub_join) associations.add_join_to([:user, :posts]) end it "extends upon existing joins when given stacks where parts are already mapped" do JoinDependency::JoinAssociation.unstub :new JoinDependency::JoinAssociation.should_receive(:new).twice. and_return(join, sub_join) associations.add_join_to([:user]) associations.add_join_to([:user, :posts]) end end end describe '#aggregate_for?' do it "is false when the stack is empty" do associations.aggregate_for?([]).should be_false end it "is true when a reflection is a has_many" do join.reflection.stub!(:macro => :has_many) associations.aggregate_for?([:user]).should be_true end it "is true when a reflection is a has_and_belongs_to_many" do join.reflection.stub!(:macro => :has_and_belongs_to_many) associations.aggregate_for?([:user]).should be_true end it "is false when a reflection is a belongs_to" do join.reflection.stub!(:macro => :belongs_to) associations.aggregate_for?([:user]).should be_false end it "is false when a reflection is a has_one" do join.reflection.stub!(:macro => :has_one) associations.aggregate_for?([:user]).should be_false end it "is true when one level is aggregate" do join.reflection.stub!(:macro => :belongs_to) sub_join.reflection.stub!(:macro => :has_many) associations.aggregate_for?([:user, :posts]).should be_true end it "is true when both levels are aggregates" do join.reflection.stub!(:macro => :has_many) sub_join.reflection.stub!(:macro => :has_many) associations.aggregate_for?([:user, :posts]).should be_true end it "is false when both levels are not aggregates" do join.reflection.stub!(:macro => :belongs_to) sub_join.reflection.stub!(:macro => :belongs_to) associations.aggregate_for?([:user, :posts]).should be_false end end describe '#alias_for' do it "returns the model's table name when no stack is given" do associations.alias_for([]).should == 'articles' end it "adds just one join for a stack with a single association" do JoinDependency::JoinAssociation.unstub :new JoinDependency::JoinAssociation.should_receive(:new). with(join.reflection, base, join_base).once.and_return(join) associations.alias_for([:user]) end it "returns the aliased table name for the join" do associations.alias_for([:user]).should == 'users' end it "does not duplicate joins when given the same stack twice" do JoinDependency::JoinAssociation.unstub :new JoinDependency::JoinAssociation.should_receive(:new).once.and_return(join) associations.alias_for([:user]) associations.alias_for([:user]) end context 'multiple joins' do it "adds two joins for a stack with two associations" do JoinDependency::JoinAssociation.unstub :new JoinDependency::JoinAssociation.should_receive(:new). with(join.reflection, base, join_base).once.and_return(join) JoinDependency::JoinAssociation.should_receive(:new). with(sub_join.reflection, base, join).once.and_return(sub_join) associations.alias_for([:user, :posts]) end it "returns the sub join's aliased table name" do associations.alias_for([:user, :posts]).should == 'posts' end it "extends upon existing joins when given stacks where parts are already mapped" do JoinDependency::JoinAssociation.unstub :new JoinDependency::JoinAssociation.should_receive(:new).twice. and_return(join, sub_join) associations.alias_for([:user]) associations.alias_for([:user, :posts]) end end end describe '#join_values' do it "returns all joins that have been created" do associations.alias_for([:user]) associations.alias_for([:user, :posts]) associations.join_values.should == [join, sub_join] end end end