了解Rails 7为SQLite的二进制列增加默认值支持

52 阅读1分钟

虽然ActiveRecord是一个包含大量功能的庞然大物,但还是会时不时出现一些WTFs。其中一个WTF就是不支持SQLite中二进制列的默认值。

之前

让我们在一个使用SQLite数据库的模型中创建一个字符串列,并给它添加一个默认值。

# db/migrate/20220821142603_add_string_to_physician.rb
# class AddStringToPhysician < ActiveRecord::Migration[7.0]
#   def change
#     add_column :physicians, :signature, :string, default: "Regards"
#   end
# end

irb(main):001:0> physician = Physician.create! name: "Belle"
                 ...
irb(main):002:0> physician.signature
=> "Regards"
irb(main):003:0> physician.reload.signature
=> "Regards"

让我们对二进制列做同样的事情。

# db/migrate/20220821142330_add_greeting_to_physician.rb
# class AddGreetingToPhysician < ActiveRecord::Migration[7.0]
#   def change
#     add_column :physicians, :greeting, :binary, default: "Hello!"
#   end
# end

irb(main):001:0> physician = Physician.create! name: "Belle"
   (0.6ms)  SELECT sqlite_version(*)
  TRANSACTION (0.0ms)  begin transaction
  Physician Create (0.3ms)  INSERT INTO "physicians" ("name", "created_at", "updated_at", "greeting", "signature") VALUES (?, ?, ?, ?, ?)  [["name", "Belle"], ["created_at", "2022-08-21 15:47:44.957101"], ["updated_at", "2022-08-21 15:47:44.957101"], ["greeting", nil], ["signature", "Regards"]]
  TRANSACTION (0.4ms)  commit transaction
...
irb(main):002:0> physician.greeting
=> nil
irb(main):003:0> physician.reload.greeting
=> "Hello!"

这就造成了Sqlite与Rails行为的不一致。

之后

幸运的是,这个PR增加了对二进制列的默认值的支持,在从数据库中读取其数据之前就可以读取。

irb(main):001:0> physician = Physician.create! name: "Belle"
   (0.6ms)  SELECT sqlite_version(*)
  TRANSACTION (0.0ms)  begin transaction
  Physician Create (0.3ms)  INSERT INTO "physicians" ("name", "created_at", "updated_at", "greeting", "signature") VALUES (?, ?, ?, ?, ?)  [["name", "Belle"], ["created_at", "2022-08-21 15:47:44.957101"], ["updated_at", "2022-08-21 15:47:44.957101"], ["greeting", "<11 bytes of binary data>"], ["signature", "Regards"]]
  TRANSACTION (0.4ms)  commit transaction
...
irb(main):002:0> physician.greeting
=> "Hello!"
irb(main):003:0> physician.reload.signature
=> "Hello!"