如何将序列添加到迁移并在模型中使用它们?
我希望拥有一个普通主键的“ Customer
”模型和另一个存储自定义“客户编号”的列。 另外,我希望db处理默认的客户编号。 我认为,定义序列是最好的方法。 我使用PostgreSQL。 看看我的迁移:
class CreateAccountsCustomers 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
如果您知道更好的“类似轨道”的方法来添加序列,那么让我知道真棒。
现在,如果我做了类似的事情
cust = Accounts::Customer.new cust.save
字段customer_no
未预先填充序列的下一个值(应为1002)。
你知道整合序列的好方法吗? 还是有一个很好的插件? 为所有答案干杯!
我没有关于处理自定义序列的更多“轨道方式”的建议,但我可以告诉您为什么在保存后不会填充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
我相信roboles的回答是不正确的。
我尝试在我的应用程序上实现这一点(完全相同的env:RoR + PostgreSQL),我发现当在具有空属性的对象的RoR上发出save
时,它会尝试对数据库执行INSERT,提到所有VALUES应设置为NULL。 问题是PostgreSQL处理NULL的方式:在这种情况下,将创建新行,但所有值都为空,即DEFAULT将被忽略。 如果save
只写在RoR上填充的INSERT语句属性上,这将正常工作。
换句话说,只关注上面提到的type
和customer_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);
结果:一个空type
的新行和customer_no
填充了序列的NEXTVAL
我有一个关于此的线索,请查看:
Ruby on Rails + PostgreSQL:自定义序列的使用
我遇到了类似的问题,但我也在字段跳转时使用:null => false
,它会自动填充nextval。
好吧,在我的情况下,如果请求中没有提供任何属性,AR仍然试图插入NULL
,这导致了非空约束违规的exception。
这是我的解决方法。 我刚刚从@attributes
和@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
Rails 3.2 / Postgres 9.1
如果你正在使用PostgreSQL,请查看我写的gem,pg_sequencer:
https://github.com/code42/pg_sequencer
它提供了一个DSL,用于在ActiveRecord迁移中创建,删除和更改序列。
- 什么是“循环参数引用”错误,使用activesupport time_zone?
- 解决Rails孤立迁移的最佳方法是什么?
- Rails 4:schema.db显示“无法转储表”事件“因为跟随NoMethodError #nunfined方法`’为nil:NilClass”
- 如何创建迁移以仅在存在时删除索引,而不是如果不存在则抛出exception?
- 模型中的更改未保存。 Rails 4.1
- heroku运行rake db:迁移错误
- 管理mongoid迁移
- Rails + Postgres迁移 – 为什么我收到错误“PG :: UndefinedFunction:ERROR:function gen_random_uuid()不存在”?
- Rails和MySQL语法错误与执行块中的多个SQL语句