I'm trying to clean up some tests and get them to run a little faster, and I have bunch of FactoryBot generated items which are currently created and persisted to the database. Obviously this isn't good for performance, so I'm trying to change the bulk of them over to use build
rather than create
to avoid the DB bottleneck. My current problem has to do with getting the objects to have a working association. What I have currently:
class User < ApplicationRecord
has_many :transaction_items,
class_name: 'Transaction',
foreign_key: 'user_id'
end
class Transaction < ApplicationRecord
belongs_to :user, class_name: 'User'
end
And the tests use these classes like so:
@user = create(:user)
@transaction1 = create(:transaction, user: @user)
@transaction2 = create(:transaction, user: @user,)
I'm fine with the User
object being created and saved to the DB, as I need it to be available for authentication purposes. I need to change the Transaction
objects to be instantiated using build
. If I make that change the Transaction
objects are aware of their associated User
object (@transaction1.user
returns the User
instance) but the inverse is not true, i.e. @user.transaction_items
does not return the associated Transaction
objects. It does return a Transaction::ActiveRecord_Associations_CollectionProxy
object but it is an empty collection. This is causing a failure because the code under tests makes use of the #transaction_items
method and it needs to have the associated objects in it.
I'm far from an expert in FactoryBot, and while there is a ton of great information out there on FactoryBot associations for some reason I've not been able to get the association to work properly. What do I need to do here to get this kind of more complex association working in my factories?
Using Rails 5.1, FactoryBot v5.0.2
That's easy
@user = create(:user)
def build_transaction(user)
user.transaction_items.build(attributes_for(:transaction, user: user))
end
@transaction1 = build_transaction(@user)
@transaction2 = build_transaction(@user)