rake db:seed出现验证失败

5
我正在学习哈特尔的教程第12章。当我运行bundle exec rake db:seed时,出现了以下错误:
ActiveRecord::RecordInvalid: Validation failed: Email has already been taken

我尝试运行

rake db:reset
rake db:migrate
rake db:test:prepare

最后,
rake db:populate 

但是他们没有解决问题。当我运行rake db:populate时,会出现以下错误:

Don't know how to build task 'db:populate'

这是我的seeds.rb文件:
    # Users
User.create!(name:  "Example User",
             email: "example@railstutorial.org",
             password:              "foobar",
             password_confirmation: "foobar",
             admin:     true,
             activated: true,
             activated_at: Time.zone.now)

99.times do |n|
  name  = Faker::Name.name
  email = "example-#{n+1}@railstutorial.org"
  password = "password"
  User.create!(name: name,
              email: email,
              password:              password,
              password_confirmation: password,
              activated: true,
              activated_at: Time.zone.now)
end

# Microposts
users = User.order(:created_at).take(6)
50.times do
  content = Faker::Lorem.sentence(5)
  users.each { |user| user.microposts.create!(content: content) }
end

# Following relationships
users = User.all
user  = users.first
following = users[2..50]
followers = users[3..40]
following.each { |followed| user.follow(followed) }
followers.each { |follower| follower.follow(user) }

我猜问题可能出在这一行代码上:email = "example-#{n+1}@railstutorial.org"

我认为你的种子文件没有问题。你确定数据库已经正确地删除了吗?也许可以进入Rails控制台检查是否有任何持久化的内容。或者尝试捕获异常并确定哪个记录导致了问题。 - user2536065
4个回答

5
你的问题在于 rake db:reset不仅会删除并重新创建数据库,而且它还会执行迁移和种子数据。因此,基本上发生的情况是这样的:
rake db:drop
rake db:create
rake db:schema:load # (think of this as running all the migrations you've run before)
rake db:seed # (creates your 100 database users)

然后你运行:

rake db:migrate # (likely unnecessary, but it causes no harm)
rake db:test:prepare # (prepares the test database)
rake db:prepare # (runs the seeds AGAIN and causes your errors)

显然,如果你停止运行rake db:prepare命令,你的问题就会消失。但为了避免将来发生这种情况,我强烈建议在您的种子文件中加入一些逻辑。它只是Ruby,所以你可以在unless语句中包装User创建,比如:

unless User.find_by( email: "example@railstutorial.org" )
  # create all 100 users
end

这将特别有价值,如果你的生产网站仍在使用种子数据(如SiteSetting表);你需要确保数据进入生产数据库,但是如果不删除种子数据再次运行种子操作将会创建重复记录(或错误)。请参考答案中选择的这个问题,作为你问题的额外参考。希望这提供了你所需的所有信息!

谢谢你的回答...我运行了你提到的命令,但没有运行rake db:prepare,但错误仍然存在...我很困惑,真的不知道该怎么办! - Hanna
我没有运行'rake db:prepare'。 - Hanna
那么现在当错误出现时,你到底在运行什么?rake db:preparerake db:resetrake db:seedbundle exec rake db:Seed都是在运行你的种子数据。使用多个命令总会导致这个错误。 - ConnorCMcKee
1
啊,我明白了。你是正确的,没有问题。Hartl先生在那段话中只是想让你把种子放入你的数据库中,而你已经成功地做到了。 - ConnorCMcKee
你的unless语句可以简化为unless User.exists?,这将返回true如果至少有1个用户记录,或者如果没有则返回false。顺便说一下,这是ActiveRecord的一个特性。 - clairity
显示剩余4条评论

1
我正在做 Hartle 的教程第 12 章。当我运行 bundle exec rake db:seed 时,我遇到了以下错误: ActiveRecord::RecordInvalid: 验证失败:Email 已被使用。
当你运行 rake db:reset 时,它会为你填充数据库。然后再运行 rake db:seed,将会抛出异常,因为在你的 seeds.rb 文件中使用了 create!。与 create 不同,create! 在验证失败时会引发一个异常。
你可以通过运行 rake db:reset,然后使用 rails console 检查你的数据库记录来验证这一点。
有几件事情可以防止这种情况发生,但是既然你的数据已经存在,为什么要这样做呢?
当我运行 rake db:populate 时它会给出以下信息: Don't know how to build task 'db:populate'
除非您自己定义,否则没有名为db:populatetask

-1

尝试使用:

如果情况已经存在,则通过电子邮件解决它。

email = "example-#{rand(100000)}@railstutorial.org"

而且你也可以看到错误:

user = User.new(name:  "Example User",
         email: "example@railstutorial.org",
         password:              "foobar",
         password_confirmation: "foobar",
         admin:     true,
         activated: true,
         activated_at: Time.zone.now)
user.errors
user.save if user.valid

相同的错误信息:“验证失败:该电子邮件已被使用”。 - Hanna
打开控制台并查看 User.all.pluck(:email).sort 的输出,检查是否存在邮箱ID在 example-1@railstutorial.org.....example-100@railstutorial.org 之间的。 - Abdul Baig
其中一个是“example@railstutorial.org”,它是最先定义的,其他的则在“example-1@railstutorial.org”和“example-100@railstutorial.org”之间。 - Hanna
你的用户邮箱已通过验证。所以在执行 User.delete_all 后,接着执行 rake db:seed 或者 rake db:drop db:create db:migrate,再执行 rake db:seed 即可生效。 - Abdul Baig
我按照你的说法删除了所有用户,并运行了 rake db:drop、rake db:create、rake db:migrate 和 rake db:seed... 但是在此之后,当我运行 bundle exec rake db:seed 时,我又看到了这个错误:(并且在 User.all.pluck(:email).sort 中,我可以再次看到所有这些电子邮件!) rake 中止! ActiveRecord::RecordInvalid: 验证失败:电子邮件已经被占用。 - Hanna

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接