FactoryGirl screws up rake db:migrate process

2020-01-30 04:34发布

问题:

I am doing TDD/BDD in Ruby on Rails 3 with Rspec (2.11.0) and FactoryGirl (4.0.0). I have a factory for a Category model:

FactoryGirl.define "Category" do
  factory :category do
    name "Foo"
  end
end

If I drop, create then migrate the database in the test enviroment I get this error:

rake aborted!
Could not find table 'categories'

This problem occurs because FactoryGirl expects the tables to already exist (for some odd reason). If I remove the spec folder from my rails app and do db:migrate, it works. Also if I mark factory-girl-rails from my Gemfile as :require => false it also works (then I have to comment that require in order to run rspec).

I found some information about this problem here: https://github.com/thoughtbot/factory_girl/issues/88

Is there something wrong that I'm doing? How can I "pass by" the FactoryGirl stage in the db:migration task?

回答1:

I think you need to have factory girl definition like that in Gemfile:

  gem 'factory_girl_rails', :require => false

And then you just require it in your spec_helper.rb like that:

  require 'factory_girl_rails'

This is the way I'm always using this gem. You don't need to require it in other places than spec_helper.rb. Your current desired approach is just wrong.



回答2:

A simple fix to this issue is to delay evaluation of any models in your factories by wrapping them in blocks. So, instead of this:

factory :cake do
  name "Delicious Cake"
  frosting Frosting.new(:flavor => 'chocolate')
  filling Filling.new(:flavor => 'red velvet')
end

Do this (notice the curly braces):

factory :cake do
  name "Delicious Cake in a box"
  frosting { Frosting.new(:flavor => 'chocolate') }
  filling { Filling.new(:flavor => 'red velvet') }
end

If you have a lot of factories this may not be feasible, but it is rather straightforward. See also here.



回答3:

Information from: http://guides.rubyonrails.org/testing.html

When you do end up destroying your testing database (and it will happen, trust me), you can rebuild it from scratch according to the specs defined in the development database. You can do this by running rake db:test:prepare.

The rake db:migrate above runs any pending migrations on the development environment and updates db/schema.rb. The rake db:test:load recreates the test database from the current db/schema.rb. On subsequent attempts, it is a good idea to first run db:test:prepare, as it first checks for pending migrations and warns you appropriately.

rake db:test:clone            Recreate the test database from the current environment’s database schema
rake db:test:clone_structure  Recreate the test database from the development structure
rake db:test:load             Recreate the test database from the current schema.rb
rake db:test:prepare          Check for pending migrations and load the test schema
rake db:test:purge            Empty the test database.


回答4:

You shouldn't need to do any of that.. I think the issue is that your argument to FactoryGirl.define..

try this.

FactoryGirl.define do
   factory :category do
       name "Foo"
   end
end

That should work fine, and does not screw up my migrations or load.. Today, I had to fix an issue where I was referencing a model constant from my factory directly and had to put it in a block to fix things.

FactoryGirl.define do
   factory :category do
       # this causes unknown table isseus
       # state Category::Active
       # this does not.
       state { Category::Active }
   end
end