Search code examples
ruby-on-railsrspecfactory-bot

Unidirectional Relation failing with Factory Girl `can't write unknown attribute`


I have a model Event

class Event < ActiveRecord::Base
  belongs_to :approved_by, class_name: 'User', foreign_key: 'approved_by'
end

And a model User which does not care about the reverse relation

class User < ActiveRecord::Base
  include Authenticatable
end

With a Event factory like so:

FactoryGirl.define do
  factory :event do
    title "MyString"
    description "...snip..."
    start_time "2017-06-26 15:31:55"
    end_time "2017-06-26 15:31:55"
    venue "MyPlace"
    status :active
    approved_by { build :user }

    trait :pending do
      status :pending
      approved_by nil
    end

    trait :active do
      #no-op
    end
  end
end

When I try to assert that they factory works as intended, like so...

RSpec.describe Event, type: :model do
  describe 'sanity checks' do
    it { expect(build :event).to be_valid }
    it { expect(create :event).to be_persisted }
  end
end

I get the following errors:

``` drew$ rspec -b spec/models/event_spec.rb FF

Failures:

1) Event sanity checks Failure/Error: it { expect(build :event).to be_valid }

 ActiveModel::MissingAttributeError:
   can't write unknown attribute `approved_by`
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/attribute.rb:138:in `with_value_from_database'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/attribute_set.rb:39:in `write_from_user'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/attribute_methods/write.rb:74:in `write_attribute_with_type_cast'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/attribute_methods/write.rb:56:in `write_attribute'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/attribute_methods/dirty.rb:96:in `write_attribute'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/attribute_methods.rb:373:in `[]='
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/associations/belongs_to_association.rb:83:in `replace_keys'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/associations/belongs_to_association.rb:14:in `replace'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/associations/singular_association.rb:17:in `writer'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/associations/builder/association.rb:123:in `approved_by='
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:16:in `public_send'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:16:in `block (2 levels) in object'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:15:in `each'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:15:in `block in object'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:14:in `tap'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:14:in `object'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/evaluation.rb:12:in `object'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/strategy/build.rb:9:in `result'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/factory.rb:42:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/factory_runner.rb:29:in `block in run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activesupport-4.2.5/lib/active_support/notifications.rb:166:in `instrument'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/factory_runner.rb:28:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
 # ./spec/models/event_spec.rb:5:in `block (3 levels) in <top (required)>'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:254:in `instance_exec'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:254:in `block in run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:496:in `block in with_around_and_singleton_context_hooks'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:453:in `block in with_around_example_hooks'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:464:in `block in run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:604:in `block in run_around_example_hooks_for'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-rails-3.5.2/lib/rspec/rails/adapters.rb:127:in `block (2 levels) in <module:MinitestLifecycleAdapter>'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:375:in `execute_with'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:606:in `block (2 levels) in run_around_example_hooks_for'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:607:in `run_around_example_hooks_for'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:464:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:453:in `with_around_example_hooks'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:496:in `with_around_and_singleton_context_hooks'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:251:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:627:in `block in run_examples'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:623:in `map'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:623:in `run_examples'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:589:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `block in run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `map'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `block (3 levels) in run_specs'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `map'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `block (2 levels) in run_specs'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/configuration.rb:1835:in `with_suite_hooks'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:112:in `block in run_specs'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/reporter.rb:77:in `report'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:111:in `run_specs'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:87:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:71:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:45:in `invoke'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/exe/rspec:4:in `<top (required)>'
 # /Users/drew/.rvm/gems/ruby-2.2.6/bin/rspec:23:in `load'
 # /Users/drew/.rvm/gems/ruby-2.2.6/bin/rspec:23:in `<main>'
 # /Users/drew/.rvm/gems/ruby-2.2.6/bin/ruby_executable_hooks:15:in `eval'
 # /Users/drew/.rvm/gems/ruby-2.2.6/bin/ruby_executable_hooks:15:in `<main>'

2) Event sanity checks Failure/Error: it { expect(create :event).to be_persisted }

 ActiveModel::MissingAttributeError:
   can't write unknown attribute `approved_by`
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/attribute.rb:138:in `with_value_from_database'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/attribute_set.rb:39:in `write_from_user'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/attribute_methods/write.rb:74:in `write_attribute_with_type_cast'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/attribute_methods/write.rb:56:in `write_attribute'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/attribute_methods/dirty.rb:96:in `write_attribute'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/attribute_methods.rb:373:in `[]='
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/associations/belongs_to_association.rb:83:in `replace_keys'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/associations/belongs_to_association.rb:14:in `replace'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/associations/singular_association.rb:17:in `writer'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activerecord-4.2.5/lib/active_record/associations/builder/association.rb:123:in `approved_by='
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:16:in `public_send'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:16:in `block (2 levels) in object'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:15:in `each'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:15:in `block in object'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:14:in `tap'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:14:in `object'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/evaluation.rb:12:in `object'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:9:in `result'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/factory.rb:42:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/factory_runner.rb:29:in `block in run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/activesupport-4.2.5/lib/active_support/notifications.rb:166:in `instrument'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/factory_runner.rb:28:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/factory_girl-4.8.0/lib/factory_girl/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
 # ./spec/models/event_spec.rb:6:in `block (3 levels) in <top (required)>'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:254:in `instance_exec'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:254:in `block in run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:496:in `block in with_around_and_singleton_context_hooks'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:453:in `block in with_around_example_hooks'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:464:in `block in run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:604:in `block in run_around_example_hooks_for'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-rails-3.5.2/lib/rspec/rails/adapters.rb:127:in `block (2 levels) in <module:MinitestLifecycleAdapter>'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:375:in `execute_with'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:606:in `block (2 levels) in run_around_example_hooks_for'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:607:in `run_around_example_hooks_for'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:464:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:453:in `with_around_example_hooks'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:496:in `with_around_and_singleton_context_hooks'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:251:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:627:in `block in run_examples'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:623:in `map'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:623:in `run_examples'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:589:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `block in run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `map'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `block (3 levels) in run_specs'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `map'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `block (2 levels) in run_specs'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/configuration.rb:1835:in `with_suite_hooks'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:112:in `block in run_specs'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/reporter.rb:77:in `report'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:111:in `run_specs'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:87:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:71:in `run'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:45:in `invoke'
 # /Users/drew/.rvm/gems/ruby-2.2.6/gems/rspec-core-3.5.4/exe/rspec:4:in `<top (required)>'
 # /Users/drew/.rvm/gems/ruby-2.2.6/bin/rspec:23:in `load'
 # /Users/drew/.rvm/gems/ruby-2.2.6/bin/rspec:23:in `<main>'
 # /Users/drew/.rvm/gems/ruby-2.2.6/bin/ruby_executable_hooks:15:in `eval'
 # /Users/drew/.rvm/gems/ruby-2.2.6/bin/ruby_executable_hooks:15:in `<main>'

Finished in 0.75142 seconds (files took 2.6 seconds to load) 2 examples, 2 failures

Failed examples:

rspec ./spec/models/event_spec.rb:5 # Event sanity checks rspec ./spec/models/event_spec.rb:6 # Event sanity checks ```

However when I try this via console it works fine...

[4] pry(main)> e = FactoryGirl.build(:event)
=> #<Event:0x007fe5ef1643d8
 id: nil,
 title: "MyString",
 description:
  "..snip..",
 start_time: Mon, 26 Jun 2017 15:31:55 UTC +00:00,
 end_time: Mon, 26 Jun 2017 15:31:55 UTC +00:00,
 venue: "MyPlace",
 main_image_cloudinary_id: nil,
 status: 1,
 approved_by: nil,
 created_at: nil,
 updated_at: nil>
[5] pry(main)> e.approved_by
=> #<User:0x007fe5ef157340
 id: nil,
 name: "Luther Johnston",
 email: "guadalupe@brakus.com",
 password_hash: "...snip...",
 authentication_token: "...snip...",
 activation_token: nil,
 activation_date: Tue, 27 Jun 2017 00:00:00 UTC +00:00,
 reset_password_token: nil,
 created_at: nil,
 updated_at: nil>

Solution

  • Since I rubber ducked myself about 2 seconds after hitting the post button, I'll go ahead and answer it.

    My test database and development database were out of sync.

    Running rake db:test:prepare solved the issue.