首页 > 解决方案 > 从字符串迁移到布尔 Rails

问题描述

我的一个表中有两列,我需要将它们从字符串转换为布尔值。对象已经将数据附加到这些列(yes、no 或 nil),因此需要将 yes 结果转换为 true 并将 no/nil 转换为 false。

我正在为 change_column 运行一个简单的迁移,但这显然不是要走的路,而且我很难找到解决方案。

我的表如下,两列分别是 inner_sleeve 和 inserts。

create_table "listings", force: :cascade do |t|
    t.string "front_cover"
    t.bigint "version_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "back_cover"
    t.string "front_label"
    t.string "back_label"
    t.integer "step", default: 0
    t.string "cover_conditions", default: [], array: true
    t.string "cover_grading"
    t.text "cover_info"
    t.boolean "original_sleeve"
    t.string "disc_grading"
    t.text "disc_info"
    t.string "inner_sleeve"
    t.string "inserts"
    t.text "inner_inserts_info"
    t.text "other_info"
    t.bigint "user_id"
    t.string "disc_conditions", default: [], array: true
    t.integer "status", default: 0
    t.date "first_active_at"
    t.boolean "order_dispatched", default: false
    t.bigint "purchaser_id"
    t.index ["purchaser_id"], name: "index_listings_on_purchaser_id"
    t.index ["user_id"], name: "index_listings_on_user_id"
    t.index ["version_id"], name: "index_listings_on_version_id"
  end

谢谢!

标签: ruby-on-railsrubypostgresqlbooleanmigration

解决方案


在这种情况下,我真的建议回退到好的 ol' SQL 来处理这类事情。举个例子,我在 PostgreSQL 中创建了一个小表:

convert_test=# select * from listings;
 id | inserts | inner_sleeve 
----+---------+--------------
  1 | yes     | no
  2 | yes     | 
  3 | no      | 
  4 |         | 
(4 rows)

然后我执行了两个原始 SQL 语句来更改列类型:

ALTER TABLE listings ALTER COLUMN inserts TYPE boolean USING CASE WHEN inserts = 'yes' THEN true ELSE false END;
ALTER TABLE listings ALTER COLUMN inner_sleeve TYPE boolean USING CASE WHEN inner_sleeve = 'yes' THEN true ELSE false END;

这应该是不言自明的,除非该USING语句正是为了转换列中的值而运行的语句。

结果如预期:

convert_test=# select * from listings; id | inserts | inner_sleeve 
----+---------+--------------
  1 | t       | f
  2 | t       | f
  3 | f       | f
  4 | f       | f
(4 rows)

推荐阅读