Last Updated: February 25, 2016
·
970
· alexvpopov

How to define fabricators of models with polymorphic associations

Let's say you have the following models:

class Admin < ActiveRecord::Base
  has_one :login, as: :loginable
end

class User < ActiveRecord::Base
  has_one :login, as: :loginable
end

class Login < ActiveRecord::Base
  belongs_to :login, polymorphic: true

  validate :email # your validations
  validate :password # your
end

Here is how to define the fabricators.

In login_fabricator.rb:

Fabricator(:login) do
  email { FFaker::Internet.email }
  pass = FFaker::Internet.password
  password pass
  password_confirmation pass
end

Fabricator(:admin_login, from: :login) do
  loginable(fabricator: :admin)
end

Fabricator(:user_login, from: :login) do
  loginable(fabricator: :user)
end

In admin_fabricator.rb:

Fabricator(:admin) do
  ...
end

Fabricator(:admin_with_login, from: :admin) do
  login { Fabricate.build :admin_login, loginable: nil }
end

In user_fabricator.rb:

Fabricator(:user) do
  ...
end

Fabricator(:user_with_login, from: :user) do
  login { Fabricate.build :user_login, loginable: nil }
end

This will produce:

Admin

admin = Fabricate :admin
admin.login # => nil
admin_with_login = Fabricate :admin_with_login
admin_with_login.login # => <Login:0x007f70c6b75550>

User

user = Fabricate :user
user.login # => nil
user_with_login = Fabricate :user_with_login
user_with_login.login # => <Login:0x007f70c6b75550>

Login

login = Fabricate :login
login.loginable # => nil
admin_login = Fabricate :admin_login
admin_login.loginable # => <Account:0x007f70c518a8e8>
user_login = Fabricate :user_login
user_login.loginable # => <User:0x007f70c9150bd0>