I wrote about using iMates a few times already, but I thought it could still be worth sharing this model as well that I'm using for a Design Automation API for Inventor sample talked about here.
I have 90cm and 180cm corner posts and mid-section posts, and 90cm and 120cm wide shelves to select from:

I have the following iMates in the models:

The corner posts have an a and b iMate at each level named (a1, b1, a2, b2, etc), the mid-section posts have an additional c and d iMates as well at each level (c1, d1, etc)
The selves have a to d iMates on the two ends (1a - 1d and 2a - 2d)
Most of the time the correct letters match up between the post and the shelf, apart from two corner posts where a is matched with c and b is matched with d.
All iMates use the same Constraint type: Insert & Opposed

The 3 parameters driving the model are: Column, Height and ShelfWidth
When the rule is run it has three main parts:
1) start
- add corner post and ground it
- add the shelves
- add the other corner post
2) middle (repeated depending on how many columns we have)
- add the two mid-section posts
- add the shelves
3) end
- add the two corner posts

Instead of the main parameter changes kicking off the iLogic rule, I added an iTrigger parameter to do it.
Sub Main()
Trace.WriteLine("Main, starting")
trigger = iTrigger0
Dim height As String = Parameter("Height") 'Height
Dim width As String = Parameter("ShelfWidth") ' ShelfWidth
Dim columns As Integer = Parameter("Columns") ' Columns
Dim rows = 4
If height = "90" Then rows = 2
Trace.TraceInformation("Main, Values: height = {0}, width = {1}, columns = {2}, rows = {3}", height, width, columns, rows)
Dim asm As AssemblyDocument
asm = ThisDoc.Document
Dim acd As AssemblyComponentDefinition
acd = asm.ComponentDefinition
Dim tg As TransientGeometry
tg = ThisServer.TransientGeometry
Dim path As String
path = ThisDoc.Path + "\"
Trace.WriteLine("Main, path = " + path)
' START
Dim post As ComponentOccurrence
Dim bottomShelf As ComponentOccurrence
' add first corner (a,b)
post = acd.Occurrences.Add(path + "corner" + height + ".ipt", tg.CreateMatrix)
post.Grounded = True
' add shelves (1a,1b)
bottomShelf = AddShelves(post, path + "shelf" + width + ".ipt", rows)
' add second corner (1c,1d) // enough to mate the first level
Call AddPost(bottomShelf, path + "corner" + height + ".ipt", "1", "c", "a", "d", "b")
' MIDDLE
Dim Column As Integer
For Column = 2 To columns
' add first mid (2a,2b) // enough to mate the first level
Call AddPost(bottomShelf, path + "mid" + height + ".ipt", "2", "a", "a", "b", "b")
' add second mid (2c,2d) // enough to mate the first level
post = AddPost(bottomShelf, path + "mid" + height + ".ipt", "2", "c", "c", "d", "d")
' add shelves ()
bottomShelf = AddShelves(post, path + "shelf" + width + ".ipt", rows)
' repeat
Next
' END
' add third corner (2a,2b) // enough to mate the first level
Call AddPost(bottomShelf, path + "corner" + height + ".ipt", "2", "a", "a", "b", "b")
' add fourth corner (2c,2d) // enough to mate the first level
Call AddPost(bottomShelf, path + "corner" + height + ".ipt", "2", "c", "a", "d", "b")
End Sub
Function GetimateDefinition(defs As iMateDefinitionsEnumerator, name As String) As iMateDefinition
Dim def As iMateDefinition
For Each def In defs
If def.Name = name Then
GetimateDefinition = def
Exit For
End If
Next
End Function
Function AddShelves(post As ComponentOccurrence, fullPath As String, rows As Integer) As ComponentOccurrence
Trace.WriteLine("AddShelves, fullPath = " + fullPath)
Dim tg As TransientGeometry
tg = ThisServer.TransientGeometry
Dim acd As AssemblyComponentDefinition
acd = post.Parent
Dim occs As ComponentOccurrences
occs = acd.Occurrences
Dim postMate As iMateDefinition
Dim shelfMate As iMateDefinition
Dim shelf As ComponentOccurrence
Dim i As Integer
For i = 1 To rows
shelf = occs.Add(fullPath, tg.CreateMatrix)
If AddShelves Is Nothing Then
AddShelves = shelf
End If
postMate = GetimateDefinition(post.iMateDefinitions, "a" + CStr(i))
shelfMate = GetimateDefinition(shelf.iMateDefinitions, "1a")
Call acd.iMateResults.AddByTwoiMates(postMate, shelfMate)
postMate = GetimateDefinition(post.iMateDefinitions, "b" + CStr(i))
shelfMate = GetimateDefinition(shelf.iMateDefinitions, "1b")
Call acd.iMateResults.AddByTwoiMates(postMate, shelfMate)
Next
End Function
Function AddPost(shelf As ComponentOccurrence, fullPath As String, shelfSide As String, shelfMate1 As String, postMate1 As String, shelfMate2 As String, postMate2 As String) As ComponentOccurrence
Trace.WriteLine("AddPost, fullPath = " + fullPath)
Dim tg As TransientGeometry
tg = ThisServer.TransientGeometry
Dim acd As AssemblyComponentDefinition
acd = shelf.Parent
Dim occs As ComponentOccurrences
occs = acd.Occurrences
Dim postMate As iMateDefinition
Dim shelfMate As iMateDefinition
AddPost = occs.Add(fullPath, tg.CreateMatrix)
postMate = GetimateDefinition(AddPost.iMateDefinitions, postMate1 + "1")
shelfMate = GetimateDefinition(shelf.iMateDefinitions, shelfSide + shelfMate1)
Call acd.iMateResults.AddByTwoiMates(postMate, shelfMate)
postMate = GetimateDefinition(AddPost.iMateDefinitions, postMate2 + "1")
shelfMate = GetimateDefinition(shelf.iMateDefinitions, shelfSide + shelfMate2)
Call acd.iMateResults.AddByTwoiMates(postMate, shelfMate)
End Function
The model can be found here: https://github.com/adamenagy/QuickerAssemblerDA/tree/master/forgesample/wwwroot/files
-Adam