2

I have these two models

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  has_many :posts
end

class Post < ApplicationRecord
  belongs_to :user
end

These are my factories

FactoryGirl.define do
  factory :user do
    id 1
    first_name 'John'
    last_name 'Doe'
    sequence(:email) { |n| "tester#{n}@example.com" }
    password 'secretpassword'
  end
end

FactoryGirl.define do
  factory :post do
    user_id 1
    title 'This is a title'
    body 'This is a body'
    published_at Time.now
  end
end

When I run the following tests I get the following error:

RSpec.describe User, type: :model do
  let(:user) { build(:user) }
  it { expect(user).to have_many(:posts) }
end

RSpec.describe Post, type: :model do
  let(:post) { build(:post) }
  it { expect(post).to belong_to(:user) }
end

# Error I get:
FactoryGirl::InvalidFactoryError:
  The following factories are invalid:

  * post - Validation failed: User must exist (ActiveRecord::RecordInvalid)

How can I fix this?

This is also my db schema

  create_table "posts", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.integer  "user_id"
    t.string   "title"
    t.text     "body",         limit: 65535
    t.datetime "published_at"
    t.datetime "created_at",                 null: false
    t.datetime "updated_at",                 null: false
    t.index ["user_id"], name: "index_posts_on_user_id", using: :btree
  end

create_table "users", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
  # Whatever devise generates
end
ltdev
  • 4,037
  • 20
  • 69
  • 129

2 Answers2

3

I found the solution eventually. The key was missing was the association :user

FactoryGirl.define do
  factory :post do
    title 'This is a title'
    body 'This is a body'
    published_at Time.now
    association :user
  end
end
ltdev
  • 4,037
  • 20
  • 69
  • 129
-1

Try the following:

belongs_to :user, optional: true

4.1.2.11 :optional

If you set the :optional option to true, then the presence of the associated object won't be validated. By default, this option is set to false.

You may refer to the docs for more information.

Roshan
  • 905
  • 9
  • 21
  • I have already tried this, but I'm getting another error: `* post - Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails` – ltdev Aug 24 '17 at 21:27
  • @Lykos This occurs if child table contain some data with the foreign key that are not in parent table. In your case, `post.user_id` is foreign key of `user.id` and post table contain `user_id` that is not present in user table. – Roshan Aug 24 '17 at 21:40
  • Not sure if I understand what you're saying, but I generated this migration in order to associate posts - users `add_reference :posts, :user, foreign_key: true, after: :id` This is how I set the `post.user_id` – ltdev Aug 24 '17 at 21:44
  • Wait, does this issue occurs because I use `build` instead of `create` in my tests?? – ltdev Aug 24 '17 at 21:45
  • @Lykos The `create()` method persists the instance of the model while the the `build()` method keeps it only on memory, so that could be the reason for the orphan record. Anyway, you should clean your test db. – Roshan Aug 24 '17 at 21:51