19

我想要一个Customer带有普通主键和另一列来存储自定义“客户编号”的“”模型。此外,我希望数据库处理默认客户编号。我认为,定义一个序列是最好的方法。我使用 PostgreSQL。看看我的迁移:

class CreateAccountsCustomers < ActiveRecord::Migration
  def up

    say "Creating sequenze for customer number starting at 1002"
    execute 'CREATE SEQUENCE customer_no_seq START 1002;'

    create_table :accounts_customers do |t|
      t.string :type
      t.integer :customer_no, :unique => true
      t.integer :salutation, :limit => 1
      t.string :cp_name_1
      t.string :cp_name_2
      t.string :cp_name_3
      t.string :cp_name_4
      t.string :name_first, :limit => 55
      t.string :name_last, :limit => 55
      t.timestamps
    end

    say "Adding NEXTVAL('customer_no_seq') to column cust_id"
    execute "ALTER TABLE accounts_customers ALTER COLUMN customer_no SET DEFAULT NEXTVAL('customer_no_seq');"

  end

  def down
    drop_table :accounts_customers
    execute 'DROP SEQUENCE IF EXISTS customer_no_seq;'
  end

end

如果您知道添加序列的更好的“类似rails”的方法,让我知道会很棒。

现在,如果我做类似的事情

cust = Accounts::Customer.new
cust.save

该字段customer_no未预先填充序列的下一个值(应为 1002)。

你知道整合序列的好方法吗?或者有什么好的插件吗?为所有答案干杯!

4

4 回答 4

13

对于处理自定义序列的更“rails 方式”,我没有任何建议,但我可以告诉你为什么 customer_no 字段在保存后似乎没有被填充。

当 ActiveRecord 保存一条新记录时,SQL 语句将只返回新记录的 ID,而不是它的所有字段,您可以在此处查看当前 rails 源中发生这种情况的位置https://github.com/rails/rails/ blob/cf013a62686b5156336d57d57cb12e9e17b5d462/activerecord/lib/active_record/persistence.rb#L313

为了查看值,您需要重新加载对象...

cust = Accounts::Customer.new
cust.save
cust.reload

如果您总是想这样做,请考虑在您的模型类中添加一个 after_create 钩子......

class Accounts::Customer < ActiveRecord::Base
  after_create :reload
end
于 2011-09-30T07:30:02.297 回答
3

我相信 roboles 的答案是不正确的。

我试图在我的应用程序上实现这一点(完全相同的环境:RoR+PostgreSQL),我发现当save在 RoR 上发出具有空属性的对象时,它会尝试在数据库上执行 INSERT,提到所有 VALUES 应设置为 NULL。问题在于 PostgreSQL 处理 NULL 的方式:在这种情况下,将创建新行但所有值都为空,即 DEFAULT 将被忽略。如果save只写在 RoR 上填充的 INSERT 语句属性,这将正常工作。

换句话说,只关注上面提到的typeandcustomer_no属性,这是 PostgreSQL 的行为方式:

情况1:

INSERT INTO accounts_customers (type, customer_no) VALUES (NULL, NULL);

(这就是 Rails 的save工作方式)

结果:一个新的空行type和空行customer_no

情况2:

INSERT INTO accounts_customers (type) VALUES (NULL);

结果:一个空的新行typecustomer_no用序列的 NEXTVAL 填充

我有一个关于这个的线程,请查看:

Ruby on Rails+PostgreSQL:自定义序列的使用

于 2011-10-19T15:46:18.157 回答
2

我遇到了类似的问题,但我也提出:null => false了字段跳跃,它将自动填充 nextval。

好吧,在我的情况下,如果请求中没有提供任何属性,AR 仍在尝试插入NULL,这导致了违反非空约束的异常。

这是我的解决方法。@attributes我刚刚从and中删除了这个属性键@changed_attributes,在这种情况下,postgres 正确地放置了预期的序列 nextval。

我把它放在模型中:

before_save do
  if (@attributes["customer_no"].nil? || @attributes["customer_no"].to_i == 0)
    @attributes.delete("customer_no")
    @changed_attributes.delete("customer_no")
  end
end

导轨 3.2 / Postgres 9.1

于 2012-05-24T13:56:39.300 回答
2

如果您使用的是 PostgreSQL,请查看我编写的 gem,pg_sequencer:

https://github.com/code42/pg_sequencer

它提供了一个 DSL,用于在 ActiveRecord 迁移中创建、删除和更改序列。

于 2012-08-03T15:54:01.677 回答