Sorry, I don't quit understand the part about first_or_build method, so I will just talk about the examples there.
First of all, we know that parent.childs.where(name: "child #{i}") and parent.childs are in different class
parent.children.where(name: "child").class
#=> Child::ActiveRecord_AssociationRelation
parent.children.class
#=> Child::ActiveRecord_Associations_CollectionProxy
so it's clear why their :build method are different, the doc are here
ActiveRecord_Associations_CollectionProxy
ActiveRecord_AssociationRelation
I will try to express my view here.
When you use ActiveRecord_AssociationRelation to build a new child, it will initialize a new Child object, and set its parent_id, but it is just an Child object. In this time, when you execute parent.children, the result is empty.
parent.children.where(name: "child1").build({age: 1})
#=> <Child id: nil, name: "child1", age: 1, parent_id: 1, created_at: nil, updated_at: nil>
parent.children
#=> <ActiveRecord::Associations::CollectionProxy []>
parent.save #=> true
parent.children.reload
#=> <ActiveRecord::Associations::CollectionProxy []>
But when you use ActiveRecord_Associations_CollectionProxy, it will initialize a new Child object, and it will also attach itself to parent, so then when you execute parent.children, the result is not empty.
parent.children.build({name: "child2", age: 2})
#=> <Child id: nil, name: "child2", age: 2, parent_id: 1, created_at: nil, updated_at: nil
parent.children
#=> <ActiveRecord::Associations::CollectionProxy [#<Child id: nil, name: "child2", age: 2, parent_id: 1, created_at: nil, updated_at: nil>]>
parent.save #=> true
parent.children.reload
#=> <ActiveRecord::Associations::CollectionProxy [#<Child id: 3, name: "child2", age: 2, parent_id: 1, created_at: "2015-05-28 17:02:39", updated_at: "2015-05-28 17:02:39">]>
In the second way, parent know it has children, so when it save, it will save its children.I think this is it.