I am writing tests for my models and came across an error I can't seem to resolve. I'm using rspec and Fabricator. Things work fine when being tested in isolation but when I try to test for associations I get an ActiveModel::MissingAttributeError.
models/user.rb
class User < ApplicationRecord
...
validates :email, uniqueness: true, presence: true
belongs_to :company, required: false
end
models/company.rb
class Company < ApplicationRecord
validates :organisation_number, uniqueness: true, presence: true
has_many :users, dependent: :destroy
end
schema
create_table "companies", force: :cascade do |t|
t.string "organisation_number"
...
end
create_table "users", id: :serial, force: :cascade do |t|
t.string "email", default: "", null: false
...
t.bigint "company_id"
t.index ["company_id"], name: "index_users_on_company_id"
...
end
fabricators/user_fabricator.rb
Fabricator :user do
email { Faker::Internet.email }
password '123456'
confirmed_at Time.now
end
fabricators/company_fabricator.rb
Fabricator :company do
organisation_number { Faker::Company.swedish_organisation_number }
end
spec/user_spec.rb (first test passes, the second fails)
describe User do
context '#create' do
it 'Creates a user when correct email and password provided' do
user = Fabricate(:user)
expect(user).to be_valid
end
it 'Lets assign a company to user' do
company = Fabricate(:company)
expect(Fabricate.build :user, company: company).to be_valid
end
end
end
I also tried adding a company straight to the User fabricator, like so (which seems to me like a correct implementation of the documentation ):
Fabricator :user do
email { Faker::Internet.email }
password '123456'
confirmed_at Time.now
company
end
and the other way around, adding users to the Company fabricator, like so:
Fabricator :company do
organisation_number { Faker::Company.swedish_organisation_number }
users(count: 3) { Fabricate(:user) }
end
but both approaches left me with the same error:
User#create Lets assign a company to user Failure/Error: company = Fabricate(:company)
ActiveModel::MissingAttributeError: can't write unknown attribute 'company_id'
Any suggestions on what I'm doing wrong?
I would write up my own answer but I am not sure that I could describe it better than RSpec
already has so this is taken directly from Here :
Rails 4.x
ActiveRecord::Migration
pending migration checksIf you are not using
ActiveRecord
you do not need to worry about these settings.Users of Rails 4.x can now take advantage of improved schema migration and sync abilities. Prior to RSpec 3, users were required to manually run migrations in both the development and test environments. Additionally, the behavior differed depending on if the specs were run via
rake
or via the standalonerspec
command.With the release of Rails 4, new APIs have been exposed on
ActiveRecord::Migration
. This allows RSpec to take advantage of these new standard migration checks, mirroring behavior across the board.
Rails 4.0.x
Add the following to the top of the
rails_helper
file after Rails has been required:ActiveRecord::Migration.check_pending!
This will raise an exception if there are any pending schema changes. Users will still be required to manually keep the development and test environments in sync.
Rails 4.1+
With this release there was an exciting new feature. Users no longer need to keep the development and test environments in sync. To take advantage of this add the following to the top of the
rails_helper
file after Rails has been required:ActiveRecord::Migration.maintain_test_schema!
What this does is that rather than just raising when the test schema has pending migrations, Rails will try to load the schema. An exception will now only be raised if there are pending migrations afterwards the schema has been loaded.
There are a few caveates to be aware of when using this:
Migrations still need to be run manually; although now this only has to be done in the 'development' environment
An exception will be raised If the schema has not been initialized. The exception will provide instructions stating
rake db:migrate
needs to be run.It is possible to opt-out of checking for pending migrations. Since this is actually a feature of Rails, the change needs to be done as part of the Rails configuration. To do this, add the following to your
config/environments/test.rb
file:config.active_record.maintain_test_schema = false
New RSpec projects don't need to worry about these commands as the
rails generate rspec:install
will add them automatically.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.