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

Ruby on rails Seeds.rb设置主键值,导致重复键错误,ruby-on-rails,postgresql,heroku,Ruby On Rails,Postgresql,Heroku,在我的Rails 4应用程序中(我在Heroku上使用该应用程序进行生产),我为初始数据集设置了一个seeds.rb文件。由于一些记录必须具有特定的主ID(例如在“活动”表中),这一点非常重要,因此我已经设置了这些ID。一切顺利 直到。直到我需要将新活动添加到活动表。添加一条新记录的失败次数与该表中的记录相同,而sequencer会跟上。(例如,如果我有三条记录,新记录创建失败三次,第四次成功) 问题:如何使Heroku postgres数据库上的主ID计数器在seeds.rb文件中设置的最高主

在我的Rails 4应用程序中(我在Heroku上使用该应用程序进行生产),我为初始数据集设置了一个seeds.rb文件。由于一些记录必须具有特定的主ID(例如在“活动”表中),这一点非常重要,因此我已经设置了这些ID。一切顺利

直到。直到我需要将新活动添加到活动表。添加一条新记录的失败次数与该表中的记录相同,而sequencer会跟上。(例如,如果我有三条记录,新记录创建失败三次,第四次成功)

问题:如何使Heroku postgres数据库上的主ID计数器在seeds.rb文件中设置的最高主ID之后启动?如果你不知道,我应该用谷歌搜索什么术语

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


提前感谢。

id列是一个自动递增列。因此,您无法控制它使用什么值——它总是使用其内部计数器中可用的下一个id。如果这是我,我会找到其他方法来识别这些记录,而不是通过:id。例如,您可以通过:name或其他特殊属性来引用这些记录?(如果您这样做,请不要忘记为您正在查找的属性编制索引!)


然后,我将使用来执行幂等播种,正如您所希望的那样。使用幂等种子设定,如果记录已经存在,则将对其进行更新(如果要执行任何更新;如果没有,则为无操作)。这样,您就不会有异常,您可以随时添加新记录或更新现有记录。

自动递增

除了
pdob
的答案之外,您还可以从以下内容中获益:当您将数据插入到具有
auto_increment
列的表中时,它只会在最后一列的末尾添加一个数字。在正常情况下,你根本不必担心它

如果您需要在特定的
id
中包含项目,例如如果您正在引用特定的记录或其他内容,我的最佳建议是更改您的系统以不处理特定的
主键

--

示例

我们在创建的
CMS
中使用
options
表,并从
options
表中引用
role\u id
(我们为其设定种子):

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

Option.create({name: "role", value: "admin"})
Option.create({name: "role", value: "moderator"})
Option.create({name: "role", value: "author"})
请注意,未提及
id

这意味着我们可以参考
角色
,如下所示:

#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
因此,我们将
角色
id
存储在
角色
列中;并使用自定义的
实例方法
访问它,该方法覆盖Rails制作的getter

所以如果我打电话

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

这意味着我们能够自动分配
id


这是因为即使删除了前面的项,
角色的
id
记录仍将保持不变。你不必担心你的
自动增量

问题最终是我在运行seeds.rb

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

$ rake db:migrate
$ rake db:seed
我可以修改生产数据库中的种子数据,而无需重置Postgres主ID计数器


另一方面,为了避免意外发生这种情况,我还创建了一个rakefile,在输入rake db:setup时会引发错误。

我在gem for rails上遇到了这个问题,因为它会抛出重复标记错误

在I
rails db:seed
之后,我运行
rails\u ENV=development rake db:reset\u pk\u 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

这似乎可以解决问题,但我还没有在生产中尝试,因为我没有使用种子数据进行生产。

我很感兴趣,但我不太明白这里的结论是什么。我不理解配置文件/选项之间的关系。。。即
外键
选项,以及这意味着能够“自动分配
id
”。我明白了。。。Profile指向一个来自选项类的角色,该选项类的作用域为
名称
“role”
。那又怎么样?是否仍有此引用中暗指的角色模型?是否有包含
%w[管理员版主作者]
之一的profiles.Role列?但是。。。什么?您仍然有一个选项对象作为您的“角色”作为配置文件,对吗?很抱歉,我忘了为您更新其余的(这是我们做的一些很酷的编码向导)亲爱的先生,谢谢,@Rich!不过,我还在想办法。所以你说“它覆盖了Rails生成的setter”——你是说getter吗?考虑到您定义的
角色
方法,
属于
的意义是什么?由于
:外键
选项具有相同的名称,
所属
是否与您的自定义
角色
方法交互?或者,
属于
只是用作设置器?最后,有没有榜样?(角色最后只是一个字符串值吗?)您写道>它总是在其内部计数器中使用下一个可用的id问题是,如何强制postgres或rails使用最高主键值之后的下一个值,而不是使用它自己的计数器?