Seeds.rb设置主键值,导致重复键错误

时间:2014-05-27 23:24:22

标签: ruby-on-rails postgresql heroku

在我使用Heroku进行制作的Rails 4应用程序中,我为初始数据集设置了一个seeds.rb文件。因为一些记录具有特定的主要ID是至关重要的,例如在'活动'表,我已经设定了那些。一切顺利。

UNTIL。直到我需要向活动表添加新活动。添加新记录将失败的次数与该表中的记录一样多,而顺控程序会赶上。 (例如,如果我有三条记录,则新记录创建失败三次,成功完成第四条记录。)

问题:如何让Heroku postgres数据库中的主ID计数器在我的seeds.rb文件中设置的最高主ID之后启动?如果您不知道,我应该使用Google搜索哪些字词?

理想情况下,这个解决方案是自动的,而不是每次我为数据库播种时都要打开psql。

提前致谢。

4 个答案:

答案 0 :(得分:3)

:id列是一个自动增量列。因此,您无法控制它使用的值 - 它只是始终使用其内部计数器中的下一个ID。如果这是我,我会找到一些其他方法来识别那些记录而不是:id。例如,也许您可​​以通过:名称或其他特殊属性来引用记录? (如果你走这条路线,别忘了索引你所找到的属性!)

然后,我会使用seed_fu gem来执行幂等种子,就像你似乎想要的那样。使用幂等种子,如果已经存在记录,那么它将被更新(如果有任何更新要执行;如果没有则那么它是无操作)。这样您就没有例外,您可以随时添加新记录或更新现有记录。

答案 1 :(得分:1)

自动增量

pdobb的答案之后,您将从阅读auto_increment中受益 - 当您将数据插入包含auto_increment列的表格时,它只会添加一个数字最后一个结束。在正常的情况下,您根本不必关心它

如果您需要包含特定ids项,例如您引用特定记录或其他内容,我最好的建议是将您的系统更改为不处理特定primary_keys

-

示例

我们使用options表和我们创建的CMS表,并引用role_id表中的options表(我们播种):

enter image description here

这是从我们的db/seeds.rb文件中填充的:

Option.create({name: "role", value: "admin"})
Option.create({name: "role", value: "moderator"})
Option.create({name: "role", value: "author"})

请注意,没有对id的引用?

这意味着我们可以按如下方式引用role

#app/models/profile.rb
belongs_to :role, -> { where(name: "role") }, class_name: "Option", foreign_key: "role"

def role
  role_name = Option.find self[:role]
  role_name.value
end

因此,我们将role id存储在role列中;并使用自定义instance method来访问它,该自定义覆盖了Rails创建的getter!

所以,如果我打电话

current_user.profile.role # -> in DB, will have id stored, but will output "value" of that

-

这意味着我们可以自动分配id

这是有效的,因为即使您删除了前面的项目,id记录的role仍将保持不变。您无需担心自己的auto_increment

答案 2 :(得分:1)

我遇到了rails的acts_as_taggable_on gem遇到这个问题,因为它会抛出重复的标记错误。

在我rails db:seed之后,我运行RAILS_ENV=development rake db:reset_pk_sequence以便重置密钥。

# lib/tasks/tag_cleaner.rake
# run using 'RAILS_ENV=development rake db:reset_pk_sequence'

namespace :db do
  desc "reset the pk sequence"
  task :reset_pk_sequence => :environment do
    ActiveRecord::Base.connection.tables.each do |t|
      ActiveRecord::Base.connection.reset_pk_sequence!(t)
    end
  end
end

这似乎解决了这个问题,但后来我没有尝试过生产,因为我没有使用种子数据进行生产。

答案 3 :(得分:0)

问题最终是我从

运行seeds.rb
$ rake db:setup

db:setup重新创建数据库,从而重置计数器。切换到:

$ rake db:migrate
$ rake db:seed

我可以在生产数据库中修改种子数据,而无需重置Postgres主ID计数器。

在旁注中,为了不会偶然发生这种情况,我还创建了一个rakefile,在输入rake db:setup时会引发错误。