将伪枚举模型重构为枚举
Posted
技术标签:
【中文标题】将伪枚举模型重构为枚举【英文标题】:Refactoring pseudo-enum models to enums 【发布时间】:2022-01-16 15:48:32 【问题描述】:我有一个名为article_status
的模型,它只是为文章提供状态。我想删除这个article_status
表并直接在article
模型中使用enum
。
所以,我创建了一个新的迁移,但我的问题是如何编写 SQL 来更新列。
class AddStatusToArticles < ActiveRecord::Migration[6.1]
def change
add_column :articles, :status, :integer
add_index :articles, :status
execute <<~SQL
# Write SQL here
SQL
change_column :articles, :status, :integer, null: false
end
end
对于 SQL 部分,我想要相当于:
Article.all.each do |article|
article.update_columns(status: article.article_status.name.parameterize.underscore)
end
在我的article
模型中:
enum status: draft: 0, in_review: 1, reviewed: 2, published: 3, deleted: 4 , _default: :draft
我像这样添加了enum
。
PS:我使用 Postgres 作为我的数据库。
【问题讨论】:
表中有多少条记录?将逻辑转换为纯 SQL 真的值得吗?旧表中是否只有五个不同的值,还是 SQL 也需要能够处理其他值? @spickermann 我有belongs_to
关联和一些我想删除的验证。如果我删除它并像上面那样编写特定于 ruby 的代码,它会引发一个错误,提示未定义方法 article_status_id
。它的记录很少,但由于这个错误,我选择了 SQL。它只有五个不同的值。
如果你已经删除了article_status_id
,你怎么知道什么状态属于什么文章?那如何在 SQL 中解决呢?
我没有删除article_status_id
列,也没有删除article_status
表。我刚刚删除了特定于 Rails 的代码。 belongs_to :article_status
。通过这样做并编写 Rails 逻辑而不是 SQL,我得到了第一条评论中提到的错误。
【参考方案1】:
我会这样做:
statuses = ArticleStatus
.pluck(:id, :name)
.map |(id, name)| [id, name..parameterize.underscore]
.to_h
Article.find_each do |article|
article.update_columns(status: statuses[article. article_status_id])
end
【讨论】:
以上是关于将伪枚举模型重构为枚举的主要内容,如果未能解决你的问题,请参考以下文章
Python - 将枚举转换为 Django 模型。CharField 选择元组 [重复]