Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Factory Girl / Rspec - "Trait Not Registered" Error

Following along with Ben Walker's (amazing) Let's Build Instagram With Rails, specifically the BDD version. Tutorial uses FactoryGirl. I'm getting the following error with a number of tests:

Short Version

Failure/Error: post = create( :post, user_id = user.id )<br>
ArgumentError:<br>
Trait not registered: 1

I can't get Ben to even recreate the bug with a clone of my repo, and I'm finding nothing in the Stack Overflow "trait not registered" questions.

This is my first SO question, so if I'm doing anything wrong on that front, please let me know. Thanks in advance for the help!

Code selections:

spec/factories.rb

FactoryGirl.define do
  factory :post do
    caption "nofilter"
    image Rack::Test::UploadedFile.new(Rails.root + 'spec/files/images/coffee.jpg', 'image/jpg')
    user_id 1
  end
  factory :user do
    email '[email protected]'
    user_name 'Arnie'
    password 'illbeback'
    id 1
  end
end

spec/features/viewing_posts_spec.rb

require 'spec_helper'

feature 'viewing individual posts' do
  background do
    user = create :user
    post = create( :post, user_id = user.id )

    sign_in_with user
  end

  scenario 'can click and view a post' do
    post = create(:post)

    visit '/'
    find(:xpath, "//a[contains(@href,'posts/2')]").click
    expect(page.current_path).to eq(post_path(post))
  end
end

app/models/post.rb

class Post < ActiveRecord::Base
  belongs_to :user

  validates :user_id, presence: true

   validates :image, presence: true

  has_attached_file :image, styles: { :medium => "640x" }

  validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
end

app/models/user.rb

class User < ActiveRecord::Base
  validates :user_name, presence: true, length: { minimum: 4, maximum: 16 }
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  has_many :posts, dependent: :destroy
end

app/controllers/posts_controller.rb

class PostsController < ApplicationController
  before_action :authenticate_user!

  def index
    @posts = Post.all
  end

  def new
    @post = current_user.posts.build
  end

  def create
    @post = current_user.posts.build(post_params)
    if @post.save
      flash[:success] = 'Your post has been created.'
      redirect_to posts_path
    else
      flash[:alert] = 'Halt, you fiend! You need an image to post here!'
      render :new
    end
  end

  def show
    @post = Post.find(params[:id])
  end

  def edit
    @post = Post.find(params[:id])
  end

  def update
    @post = Post.find(params[:id])
    if @post.update(post_params)
      flash[:success] = 'Post updated hombre.'
      redirect_to root_path
    else
      flash[:alert] = 'Something is wrong with your form!'
      redirect_to root_path
    end
  end

  def destroy
    @post = Post.find(params[:id])
    @post.destroy
    flash[:success] = 'Problem solved!  Post deleted.'
    redirect_to root_path
  end

  private

  def post_params
    params.require(:post).permit(:caption, :image)
  end
end

Full Error (one of many)

viewing individual posts can click and view a post
     Failure/Error: post = create( :post, user_id = user.id )
     ArgumentError:
       Trait not registered: 1
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/registry.rb:24:in `find'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/decorator.rb:10:in `method_missing'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl.rb:98:in `trait_by_name'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/definition.rb:113:in `trait_by_name'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/definition.rb:109:in `block in additional_traits'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/definition.rb:109:in `map'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/definition.rb:109:in `additional_traits'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/definition.rb:135:in `block in aggregate_from_traits_and_self'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/definition.rb:128:in `tap'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/definition.rb:128:in `aggregate_from_traits_and_self'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/definition.rb:33:in `to_create'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/definition_hierarchy.rb:16:in `build_from_definition'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/factory.rb:124:in `build_hierarchy'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/factory.rb:87:in `compile'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/factory.rb:32:in `run'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/factory_runner.rb:23:in `block in run'
     # /var/lib/gems/2.1.0/gems/activesupport-4.2.0/lib/active_support/notifications.rb:166:in `instrument'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/factory_runner.rb:22:in `run'
     # /var/lib/gems/2.1.0/gems/factory_girl-4.5.0/lib/factory_girl/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
     # ./spec/features/viewing_posts_spec.rb:6:in `block (2 levels) in <top (required)>'
like image 334
Parker Harris Emerson Avatar asked Aug 23 '15 22:08

Parker Harris Emerson


2 Answers

I got this exact same error message too, and it was because of these lines of code in my spec file.

# .spec file

let!(:user) { create(:user) }
let!(:board) { create(:board, 1, user_id: user.id) }
let!(:categories) { create_list(:category, 5, board_id: board.id) }

In my app, users have many boards, and boards have many categories. In this part of my spec, I was trying to create one user, one board, linked to that user via the id property, and a list of 5 categories, each linked to that one board via the id property on category.

The problem was I copied the arguments for the create_list function for creating categories and pasted it as the arguments for the create function intended to create one board.

The create function expects a property override as the second arg, while the create_list function expects an integer, representing how many objects to populate the list with.

The error is shown because the second argument of 1 in the create function, intended for a single category, represents a 'property override, since that's what the create function expects as the second argument. By removing the 1 as the second parameter in create, the error is gone because the correct parameters are provided.

Cheers.

like image 83
Mika Yeap Avatar answered Sep 28 '22 05:09

Mika Yeap


Modify your factories to use the association.

FactoryGirl.define do
  factory :post do
    caption "nofilter"
    image Rack::Test::UploadedFile.new(Rails.root + 'spec/files/images/coffee.jpg', 'image/jpg')
    association user
  end
  factory :user do
    email '[email protected]'
    user_name 'Arnie'
    password 'illbeback'
    sequence(:id) { |id| id }
  end
end

Then, create the user and post like this:

user = create :user
post = create(:post, user: user)

This should work.

See more about factory_girl associations.

like image 40
K M Rakibul Islam Avatar answered Sep 28 '22 05:09

K M Rakibul Islam