ruby-on-rails - MySQL double 到 PostgreSQL double 有效,但 schema.rb 转储中不存在默认列值

标签 ruby-on-rails postgresql rails-activerecord

我在 Rails 应用程序中将 MySQL 数据库转换为 PostgreSQL,MySQL double 列在 PostgreSQL 中被转换为 double precision 列。

问题在于,即使 PostgreSQL 结构的这一列的默认值为“0::double precision”,rake db:schema:dump 也不会添加此默认值。

因此,在创建模型实例时,不会自动分配默认值,而是它的值为nil

现在,我使用的是 Rails 4.1.6,发生这种情况是因为未列出列类型 here (AFAIK)。奇怪的是(对我来说)是为什么还没有添加这个。

此处推荐的方法是什么?更改 PostgreSQL 中的列类型?

来自 psql\d payments 说:

                                       Table "public.payments"
     Column     |            Type             |                       Modifiers                       
----------------+-----------------------------+-------------------------------------------------------
 id             | integer                     | not null default nextval('payments_id_seq'::regclass)
 credit_card_id | integer                     | not null default 0
 order_id       | integer                     | not null default 0
 amount         | double precision            | not null default 0::double precision
 created_at     | timestamp without time zone | not null
 updated_at     | timestamp without time zone | not null
 authorization  | character varying(510)      | default NULL::character varying
Indexes:
    "payments_pkey" PRIMARY KEY, btree (id)
    "credit_card_id" btree (credit_card_id)
    "purchase_order_id_1" btree (order_id)

schema.rb 的相应部分说:

create_table "payments", force: true do |t|
  t.integer  "credit_card_id",             default: 0, null: false
  t.integer  "order_id",                   default: 0, null: false
  t.float    "amount",                                 null: false
  t.datetime "created_at",                             null: false
  t.datetime "updated_at",                             null: false
  t.string   "authorization",  limit: 510
end

最佳答案

我认为您对 ActiveRecord 内 extract_value_from_default 中的问题的看法是正确的; AR 倾向于忽略数据库中它不理解的任何内容,它不理解 amount 定义中的 ::double precision,因此 AR 假设存在没有默认值。

无论您使用什么工具将 MySQL 模式和数据库转换为 PostgreSQL,都存在一定的问题。不需要类型转换,PostgreSQL 可以自行将整数转换为 double ,所以只需:

amount double precision default 0

就足够了。如果你想在默认情况下提醒你正在处理 float ,那么你可以使用:

amount double precision default 0.0

AR 应该理解其中任何一个。

最简单的解决方案是修复数据库中的默认值并删除类型转换。在 AR 的背后做一个手动的 ALTER TABLE 应该就足够了。从 psql,你可以说:

alter table payments alter column amount set default 0;

或在迁移中:

def up
  connection.execute('alter table payments alter column amount set default 0')
end

之后,您的 db:schema:dump 应该包含新的默认值,并且新创建的 Payment 的金额应该为零。


顺便说一句,您可能希望在数据库中切换到 numeric 类型(AR 称其为 t.decimal)。用 float 换钱很少有好下场。

关于ruby-on-rails - MySQL double 到 PostgreSQL double 有效,但 schema.rb 转储中不存在默认列值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27634013/

相关文章:

ruby-on-rails - 来自 Rails 表单的用户数据不是采用 UTF-8 编码吗?

SQL获取整数后两位

sql - Postgres : How to set check constraint during an update?

sql - 如何在 PostgreSQL 中给每个组编号

C# ASP.NET MVC3 优于 Ruby on Rails 3、Django?

ruby-on-rails - rails : Setting a position value in before_create

ruby-on-rails - Rails 2.3.8 中的 SQLite 3 繁忙异常

Rails 5 升级后 Activerecord 存储仅返回空哈希

ruby-on-rails - Rails - 异常 I18n::InvalidLocale 在一个奇怪的地方

ruby - 营救ActiveRecord::RecordNotUnique in Rails 3.2