require 'spec_helper' describe "ManyPolymorphicProxy" do before do Room.collection.drop Message.collection.drop end it "should default reader to empty array" do Room.new.messages.should == [] end it "should add type key to polymorphic class base" do Message.keys.keys.should include('_type') end it "should allow adding to assiciation like it was an array" do room = Room.new room.messages << Enter.new room.messages.push Exit.new room.messages.concat Exit.new room.messages.size.should == 3 end it "should be able to replace the association" do room = Room.create(:name => 'Lounge') lambda { room.messages = [ Enter.new(:body => 'John entered room', :position => 1), Chat.new(:body => 'Heyyyoooo!', :position => 2), Exit.new(:body => 'John exited room', :position => 3) ] }.should change { Message.count }.by(3) room = room.reload messages = room.messages.all :order => "position" messages.size.should == 3 messages[0].body.should == 'John entered room' messages[1].body.should == 'Heyyyoooo!' messages[2].body.should == 'John exited room' end it "should correctly store type when using <<, push and concat" do room = Room.new room.messages << Enter.new(:body => 'John entered the room', :position => 1) room.messages.push Exit.new(:body => 'John entered the room', :position => 2) room.messages.concat Chat.new(:body => 'Holla!' , :position => 3) room = room.reload messages = room.messages.all :order => "position" messages[0]._type.should == 'Enter' messages[1]._type.should == 'Exit' messages[2]._type.should == 'Chat' end context "build" do it "should assign foreign key" do room = Room.create message = room.messages.build message.room_id.should == room._id end it "should assign _type" do room = Room.create message = room.messages.build message._type.should == 'Message' end it "should allow assigning attributes" do room = Room.create message = room.messages.build(:body => 'Foo!') message.body.should == 'Foo!' end end context "create" do it "should assign foreign key" do room = Room.create message = room.messages.create message.room_id.should == room._id end it "should assign _type" do room = Room.create message = room.messages.create message._type.should == 'Message' end it "should save record" do room = Room.create lambda { room.messages.create }.should change { Message.count } end it "should allow passing attributes" do room = Room.create message = room.messages.create(:body => 'Foo!') message.body.should == 'Foo!' end end context "count" do it "should work scoped to association" do room = Room.create 3.times { room.messages.create } other_room = Room.create 2.times { other_room.messages.create } room.messages.count.should == 3 other_room.messages.count.should == 2 end it "should work with conditions" do room = Room.create room.messages.create(:body => 'Foo') room.messages.create(:body => 'Other 1') room.messages.create(:body => 'Other 2') room.messages.count(:body => 'Foo').should == 1 end end context "Finding scoped to association" do before do @lounge = Room.create(:name => 'Lounge') @lm1 = Message.create(:body => 'Loungin!', :position => 1) @lm2 = Message.create(:body => 'I love loungin!', :position => 2) @lounge.messages = [@lm1, @lm2] @lounge.save @hall = Room.create(:name => 'Hall') @hm1 = Message.create(:body => 'Do not fall in the hall', :position => 1) @hm3 = Message.create(:body => 'Loungin!', :position => 3) @hm2 = Message.create(:body => 'Hall the king!', :position => 2) @hall.messages = [@hm1, @hm2, @hm3] @hall.save @hall.reload end context "dynamic finders" do it "should work with single key" do @lounge.messages.find_by_position(1).should == @lm1 @hall.messages.find_by_position(2).should == @hm2 end it "should work with multiple keys" do @lounge.messages.find_by_body_and_position('Loungin!', 1).should == @lm1 @lounge.messages.find_by_body_and_position('Loungin!', 2).should be_nil end it "should raise error when using !" do lambda { @lounge.messages.find_by_position!(222) }.should raise_error(MongoMapper::DocumentNotFound) end context "find_or_create_by" do it "should not create document if found" do lambda { message = @lounge.messages.find_or_create_by_body('Loungin!') message.room.should == @lounge message.should == @lm1 }.should_not change { Message.count } end it "should create document if not found" do lambda { message = @lounge.messages.find_or_create_by_body('Yo dawg!') message.room.should == @lounge message._type.should == 'Message' }.should change { Message.count }.by(1) end end end context "with #all" do it "should work" do @lounge.messages.all(:order => "position").should == [@lm1, @lm2] end it "should work with conditions" do messages = @lounge.messages.all(:body => 'Loungin!', :order => "position") messages.should == [@lm1] end it "should work with order" do messages = @lounge.messages.all(:order => 'position desc') messages.should == [@lm2, @lm1] end end context "with #first" do it "should work" do @lounge.messages.first(:order => "position asc").should == @lm1 end it "should work with conditions" do message = @lounge.messages.first(:body => 'I love loungin!', :order => "position asc") message.should == @lm2 end end context "with #last" do it "should work" do @lounge.messages.last(:order => "position asc").should == @lm2 end it "should work with conditions" do message = @lounge.messages.last(:body => 'Loungin!', :order => "position asc") message.should == @lm1 end end context "with one id" do it "should work for id in association" do @lounge.messages.find(@lm2._id).should == @lm2 end it "should not work for id not in association" do lambda { @lounge.messages.find!(@hm2._id) }.should raise_error(MongoMapper::DocumentNotFound) end end context "with query options/criteria" do it "should work with order on association" do @lounge.messages.should == [@lm1, @lm2] end it "should allow overriding the order provided to the association" do @lounge.messages.all(:order => 'position').should == [@lm1, @lm2] end it "should allow using conditions on association" do @hall.latest_messages.should == [@hm3, @hm2] end end context "with multiple ids" do it "should work for ids in association" do messages = @lounge.messages.find(@lm1._id, @lm2._id) messages.should == [@lm1, @lm2] end it "should not work for ids not in association" do lambda { @lounge.messages.find!(@lm1._id, @lm2._id, @hm2._id) }.should raise_error(MongoMapper::DocumentNotFound) end end context "with #paginate" do before do @messages = @hall.messages.paginate(:per_page => 2, :page => 1, :order => 'position asc') end it "should return total pages" do @messages.total_pages.should == 2 end it "should return total entries" do @messages.total_entries.should == 3 end it "should return the subject" do @messages.should == [@hm1, @hm2] end end end context "extending the association" do it "should work using a block passed to many" do room = Room.new(:name => "Amazing Room") messages = room.messages = [ Enter.new(:body => 'John entered room', :position => 3), Chat.new(:body => 'Heyyyoooo!', :position => 4), Exit.new(:body => 'John exited room', :position => 5), Enter.new(:body => 'Steve entered room', :position => 6), Chat.new(:body => 'Anyone there?', :position => 7), Exit.new(:body => 'Steve exited room', :position => 8) ] room.save room.messages.older.should == messages[3..5] end it "should work using many's :extend option" do room = Room.new(:name => "Amazing Room") accounts = room.accounts = [ Bot.new(:last_logged_in => 3.weeks.ago), AccountUser.new(:last_logged_in => nil), Bot.new(:last_logged_in => 1.week.ago) ] room.save room.accounts.inactive.should == [accounts[1]] end end end