@@ -1076,6 +1076,322 @@ class D
10761076 expect ( criteria ) . to eq ( [ person ] )
10771077 end
10781078 end
1079+
1080+ context "when including nested referenced associations" do
1081+
1082+ context "when using a has_one association" do
1083+ before ( :all ) do
1084+ class A
1085+ include Mongoid ::Document
1086+ has_one :b
1087+ end
1088+
1089+ class B
1090+ include Mongoid ::Document
1091+ belongs_to :a
1092+ has_one :c
1093+ end
1094+
1095+ class C
1096+ include Mongoid ::Document
1097+ belongs_to :b
1098+ has_one :d
1099+ end
1100+
1101+ class D
1102+ include Mongoid ::Document
1103+ belongs_to :c
1104+ end
1105+ end
1106+
1107+ after ( :all ) do
1108+ Object . send ( :remove_const , :A )
1109+ Object . send ( :remove_const , :B )
1110+ Object . send ( :remove_const , :C )
1111+ Object . send ( :remove_const , :D )
1112+ end
1113+
1114+ let! ( :a ) do
1115+ A . create!
1116+ end
1117+
1118+ let! ( :b ) do
1119+ B . create!
1120+ end
1121+
1122+ let! ( :c ) do
1123+ C . create!
1124+ end
1125+
1126+ let! ( :d ) do
1127+ D . create!
1128+ end
1129+
1130+ before do
1131+ c . d = d
1132+ b . c = c
1133+ a . b = b
1134+ end
1135+
1136+ context "when including the belongs_to assocation" do
1137+ let! ( :result ) do
1138+ C . includes ( b : :a ) . first
1139+ end
1140+
1141+ it "finds the right document" do
1142+ expect ( result ) . to eq ( c )
1143+ expect ( result . b ) . to eq ( c . b )
1144+ expect ( result . b . a ) . to eq ( c . b . a )
1145+ end
1146+
1147+ it "does not execute a query" do
1148+ expect_no_queries do
1149+ result . b . a
1150+ end
1151+ end
1152+ end
1153+
1154+ context "when including a doubly-nested belongs_to assocation" do
1155+ let! ( :result ) do
1156+ D . includes ( c : { b : :a } ) . first
1157+ end
1158+
1159+ it "finds the right document" do
1160+ expect ( result ) . to eq ( d )
1161+ expect ( result . c ) . to eq ( d . c )
1162+ expect ( result . c . b ) . to eq ( d . c . b )
1163+ expect ( result . c . b . a ) . to eq ( d . c . b . a )
1164+ end
1165+
1166+ it "does not execute a query" do
1167+ expect_no_queries do
1168+ result . c . b . a
1169+ end
1170+ end
1171+ end
1172+
1173+ context "when including the has_many assocation" do
1174+ let! ( :result ) do
1175+ A . includes ( b : :c ) . first
1176+ end
1177+
1178+ it "finds the right document" do
1179+ expect ( result ) . to eq ( a )
1180+ expect ( result . b ) . to eq ( a . b )
1181+ expect ( result . b . c ) . to eq ( a . b . c )
1182+ end
1183+
1184+ it "does not executes a query" do
1185+ expect_no_queries do
1186+ result . b . c
1187+ end
1188+ end
1189+ end
1190+
1191+ context "when including a doubly-nested has_many assocation" do
1192+ let! ( :result ) do
1193+ A . includes ( b : { c : :d } ) . first
1194+ end
1195+
1196+ it "finds the right document" do
1197+ expect ( result ) . to eq ( a )
1198+ expect ( result . b ) . to eq ( a . b )
1199+ expect ( result . b . c ) . to eq ( a . b . c )
1200+ expect ( result . b . c . d ) . to eq ( a . b . c . d )
1201+ end
1202+
1203+ it "does not execute a query" do
1204+ expect_no_queries do
1205+ result . b . c . d
1206+ end
1207+ end
1208+ end
1209+
1210+ context "when there are multiple documents" do
1211+ let! ( :as ) do
1212+ res = 9 . times . map do |i |
1213+ A . create! . tap do |a |
1214+ a . b = B . create! . tap do |b |
1215+ b . c = C . create!
1216+ end
1217+ end
1218+ end
1219+ [ a , *res ]
1220+ end
1221+
1222+ let! ( :results ) do
1223+ A . includes ( b : :c ) . entries . sort
1224+ end
1225+
1226+ it "finds the right document" do
1227+ as . length . times do |i |
1228+ expect ( as [ i ] ) . to eq ( results [ i ] )
1229+ expect ( as [ i ] . b ) . to eq ( results [ i ] . b )
1230+ expect ( as [ i ] . b . c ) . to eq ( results [ i ] . b . c )
1231+ end
1232+ end
1233+
1234+ it "does not execute a query" do
1235+ expect_no_queries do
1236+ results . each do |a |
1237+ a . b . c
1238+ end
1239+ end
1240+ end
1241+ end
1242+
1243+ context "when there are multiple associations" do
1244+ before ( :all ) do
1245+ class A
1246+ has_one :c
1247+ end
1248+
1249+ class C
1250+ belongs_to :a
1251+ end
1252+ end
1253+
1254+ let ( :c2 ) { C . create! }
1255+ let ( :d2 ) { D . create! }
1256+
1257+ before do
1258+ a . c = c2
1259+ a . c . d = d2
1260+ end
1261+
1262+ let! ( :results ) do
1263+ A . includes ( b : { c : :d } , c : :d ) . first
1264+ end
1265+
1266+ it "finds the right document" do
1267+ expect ( results ) . to eq ( a )
1268+ expect ( results . b ) . to eq ( a . b )
1269+ expect ( results . b . c ) . to eq ( a . b . c )
1270+ expect ( results . b . c . d ) . to eq ( a . b . c . d )
1271+ expect ( results . c ) . to eq ( a . c )
1272+ expect ( results . c . d ) . to eq ( a . c . d )
1273+ end
1274+
1275+ it "does not execute a query" do
1276+ expect_no_queries do
1277+ results . c . d
1278+ results . b . c . d
1279+ end
1280+ end
1281+ end
1282+ end
1283+ end
1284+
1285+ context "when using a has_many association" do
1286+ before ( :all ) do
1287+ class IncUser
1288+ include Mongoid ::Document
1289+ has_many :posts , class_name : 'IncPost'
1290+ has_many :comments , class_name : 'IncComment'
1291+ end
1292+
1293+ class IncPost
1294+ include Mongoid ::Document
1295+ belongs_to :user , class_name : 'IncUser'
1296+ has_many :comments , class_name : 'IncComment'
1297+ end
1298+
1299+ class IncComment
1300+ include Mongoid ::Document
1301+ belongs_to :posts , class_name : 'IncPost'
1302+ belongs_to :user , class_name : 'IncUser'
1303+ belongs_to :thread , class_name : 'IncThread'
1304+ end
1305+
1306+ class IncThread
1307+ include Mongoid ::Document
1308+ has_many :comments , class_name : 'IncComment'
1309+ end
1310+ end
1311+
1312+ after ( :all ) do
1313+ Object . send ( :remove_const , :IncUser )
1314+ Object . send ( :remove_const , :IncPost )
1315+ Object . send ( :remove_const , :IncComment )
1316+ Object . send ( :remove_const , :IncThread )
1317+ end
1318+
1319+ let! ( :user ) do
1320+ IncUser . create! ( posts : posts , comments : user_comments )
1321+ end
1322+
1323+ let! ( :posts ) do
1324+ [ IncPost . create! ( comments : post_comments ) ]
1325+ end
1326+
1327+ let! ( :user_comments ) do
1328+ 2 . times . map { IncComment . create! }
1329+ end
1330+
1331+ let! ( :post_comments ) do
1332+ 2 . times . map { IncComment . create! }
1333+ end
1334+
1335+ context "when including the same class twice" do
1336+ let! ( :results ) do
1337+ IncPost . includes ( { user : :comments } , :comments ) . entries . sort
1338+ end
1339+
1340+ it "finds the right documents" do
1341+ posts . length . times do |i |
1342+ expect ( posts [ i ] ) . to eq ( results [ i ] )
1343+ expect ( posts [ i ] . user ) . to eq ( results [ i ] . user )
1344+ expect ( posts [ i ] . user . comments ) . to eq ( results [ i ] . user . comments )
1345+ expect ( posts [ i ] . comments ) . to eq ( results [ i ] . comments )
1346+ end
1347+ end
1348+
1349+ it "does not execute a query" do
1350+ expect_no_queries do
1351+ results . each do |res |
1352+ res . user
1353+ res . user . comments . to_a
1354+ res . comments . to_a
1355+ end
1356+ end
1357+ end
1358+ end
1359+
1360+ context "when the association chain has a class name twice" do
1361+ let! ( :thread ) { IncThread . create! ( comments : user_comments ) }
1362+
1363+ let! ( :result ) do
1364+ IncThread . includes ( comments : { user : { posts : :comments } } ) . first
1365+ end
1366+
1367+ it "finds the right document" do
1368+ expect ( result ) . to eq ( thread )
1369+ result . comments . length . times do |i |
1370+ c1 = result . comments [ i ]
1371+ c2 = thread . comments [ i ]
1372+ expect ( c1 ) . to eq ( c2 )
1373+ expect ( c1 . user ) . to eq ( c2 . user )
1374+ c1 . user . posts . length . times do |i |
1375+ p1 = c1 . user . posts [ i ]
1376+ p2 = c2 . user . posts [ i ]
1377+
1378+ expect ( p1 ) . to eq ( p2 )
1379+ expect ( p1 . comments ) . to eq ( p2 . comments )
1380+ end
1381+ end
1382+ end
1383+
1384+ it "does not execute a query" do
1385+ expect_no_queries do
1386+ result . comments . each do |comment |
1387+ comment . user . posts . each do |post |
1388+ post . comments . to_a
1389+ end
1390+ end
1391+ end
1392+ end
1393+ end
1394+ end
10791395 end
10801396
10811397 describe "#inclusions" do
0 commit comments