我正在使用 Devise 构建 Rails 应用程序以进行身份验证,其默认数据库迁移设置以下列:
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
同时设置null: false
和default: ""
有什么用?
我的理解是 null: false
有效地产生了一个必需的值:即, 试图在其中保存一个带有 NULL
值的记录列将在数据库级别失败,而不依赖于对模型的任何验证。
但是 default: ""
基本上通过在保存之前将 NULL
值转换为空字符串来取消它。
我知道对于可选列,您想要拒绝 NULL
值只是为了确保该列中的所有数据都属于同一类型。但是,在这种情况下,电子邮件和密码显然不是可选用户身份验证模型的属性。我确定模型中有验证以确保您不能使用空电子邮件地址创建用户,但是为什么要首先在此处设置 default: ""
?它是否提供了一些好处或防止了一些我没有考虑过的边缘情况?
最佳答案
广义上讲:
- 要使列成为必填列,您必须对其设置
null: false
。无论您是创建新表还是更新现有表,都是如此。 - 如果您要更新现有表,数据库引擎将尝试在每一行中用
NULL
填充新列。在这种情况下,您必须使用default: ""
覆盖此行为,否则它将与null: false
冲突并且迁移将失败。
关于设计:
Devise 使用两个单独的模板来构建迁移:migration.rb
,用于创建新表,以及 migration_existing.rb
,用于更新现有表(参见 source on GitHub) .两个模板调用相同的 migration_data
method生成有问题的行(即,指定 null: false, default: ""
的行),但如上所述,default: ""
仅在后一种情况下真正相关(有关更多信息,请参见 O. Jones’ answer)。
所以对您的问题的简短回答,特别是在 Devise 迁移的情况下,是“因为生成器使用了并不总是适用的借用代码,但仍然不会破坏任何东西。”
UNIQUE
列的注意事项:
请注意,在大多数流行的 SQL 引擎中,uniquely indexed columns can still contain multiple rows of NULL
values ,只要不需要(自然)。但是创建新列的效果既需要又是唯一的(即 null: false
, default: ""
, and unique: true
) cannot be added: 数据库引擎尝试用空字符串填充新列行,它与 unique
约束冲突并导致迁移失败。
(此机制失败的唯一情况是,如果您的表中只有一行——它为新列获取一个空字符串值,这自然会通过唯一性约束,因为它是唯一的记录。)
因此,另一种看待它的方式可能是,这些选项是一种安全机制,可防止您运行不应运行的迁移(即,向已填充的表追溯添加所需的列) .
关于mysql - 为什么要在所需的数据库列上设置 `null: false, default: ""`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44904357/