【问题标题】:How do I update a sequence in Rails and get the resulting value in my object?如何更新 Rails 中的序列并在对象中获取结果值?
【发布时间】:2015-05-27 09:50:43
【问题描述】:

假设我有一个派生自 ActiveRecord 的类。它有几个字段,外加一个“id”字段。创建了“id”,因此它的默认值是序列的“nextval”,因此每次保存新记录时它都会自动递增。它是通过以下方式创建的:

CREATE SEQUENCE id_sequence;

ALTER TABLE my_table ALTER COLUMN id SET DEFAULT nextval('id_sequence');

所以,现在在 Ruby 中,我填充对象中的字段,然后“保存!”它。现在我需要对对象做更多的工作,但“id”字段仍设置为 nil。 Ruby 中没有“加载”函数可以让我从数据库中重新加载对象。不管你怎么想,“!”在 ActiveRecord 中并不意味着它修改了原始对象(如果 Rails 不遵循它们,Ruby 约定的意义何在)。您似乎无法在原始对象中执行“self.find_by”。我能想到的唯一想法是在表的某些定义消息字段上调用“find_by”(这几乎是不可能的,因为这就是 id 的用途,但我还没有它!)并创建一个新对象并从中得到 id。

一定有更简单的方法。

【问题讨论】:

  • 所以你是说调用save! 不会引发错误? save 返回什么?
  • 我从未听说过“串行”列,它看起来不像是 ActiveRecord 数据类型之一:stackoverflow.com/questions/17918117/rails-4-datatypes
  • 目前的答案似乎是在调用“保存”后使用“重新加载”。这至少比我之前做的黑客要好。

标签: sql ruby-on-rails postgresql activerecord sequence


【解决方案1】:

Rails ActiveRecord 应该在创建对象时使用其新 ID 自动更新它。当同时创建序列和列时,这通常可以正常工作,例如使用 SERIAL 类型。仅将列的默认值设置为 nextval(sequence_name) 不足以将序列“绑定”到列。

解决方案似乎是通过设置其所有权将序列与列相关联,如下所示:

ALTER SEQUENCE id_sequence OWNED BY my_table.id;

这应该允许 ActiveRecord 查询 pg 目录并找到要检索的正确序列值。

您可以通过在 alter 语句之前和之后运行 SELECT pg_get_serial_sequence('my_table', 'id') 来检查这一点。在它可能为空白之前,它应该显示序列名称(在您的示例中为 id_sequence )。这是 ActiveRecord 运行以查找适当序列的名称 (line 258 in schema_statements.rb) 的查询。

如果这仍然不起作用,我会将序列重命名为约定:tablename_columnname_seq——在你的情况下是my_table_id_seq

【讨论】:

  • 实际上我确实有一个“ALTER SEQUENCE id_sequence OWNED BY my_table.id”。当我创建对象并“保存”它时,我查看数据库,我看到“id”设置为正确的数字并且序列增加,所以我知道事情的 db 方面正在工作。但是当我查看对象时,id 设置为“nil”。如果我然后创建一个新对象并“find_by”来获取我刚刚创建的对象,则会设置 id 但这很尴尬,并且只有在我可以使用其他标识字段加载对象时才有效。
  • @Mike 创建一个带有 SERIAL 列的新表,看看是否可行。
  • 对,对不起,没看到。然后它应该可以工作,因为 AFAIK,AR 将使用 INSERT ... RETURNING id 创建新条目。除非id 可能不是 PK。
猜你喜欢
  • 1970-01-01
  • 2018-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-24
  • 2017-03-10
  • 1970-01-01
  • 2015-09-18
相关资源
最近更新 更多