Rails 4.2 (如果没记错)给我们带来了官方的 Enum 解决方案,目前大家都在使用它了。
比如:
class Book
enum status: %i[draft published archived]
end
然而我们在使用的时候会发现,往往我们需要将 status
字段用中文或其他的方式在界面上显示,而不是一个 draft / published / archived
。
于是很多人可能会这样:
class Book
enum status: %i[draft published archived]
def status_name
case status
when "draft" then "草稿"
when "published" then "已发布"
when "archived" then "归档"
end
end
end
然后随着项目的推进,你会发现你的 Model 里面大量有这种函数。
为了解决这个问题,我们最初在自己的项目里面实现了一个扩展,用于代替 enum
的定义,给它增加一些函数扩展,现在提取成一个 Gem,可以方便以后使用。
gem "enumize"
然后你的原来的 enum 定义不需要改变,这个 Gem 已经覆盖了那个方法。
所以,你可以认为这个 Gem 的引入不会改变 ActiveRecord::Enum 的原有使用方式,你可以无缝的集成到你的项目中!
class Book
enum status: %i[draft published archived]
end
现在你有了 status_name
, status_color
, status_value
以及 Book.status_options
这些方法:
#{attribute}_name
- 返回 name 的 I18n 信息,用于显示#{attribute}_color
- 返回从 I18n 里面读取 color 的信息(如果你项目用不到可以忽略它)#{attribute}_value
- 返回原始的数据库值,用来代替 Book.statuses[@book.status]
Book.#{attribute}_options
- 返回一个 Array,用于 select
tag,比如 <%= f.select :status, Book.status_options %>
.配置 I18n:
config/locales/en.yml
en:
activerecord:
enums:
book:
status:
draft: Drafting
published: Published
archived: Archived
status_color:
draft: "#999999"
published: "green"
archived: "red"
config/locales/zh-CN.yml
zh-CN:
activerecord:
enums:
book:
status:
draft: "草稿"
published: "已发布"
archived: "归档"
下面是使用的演示:
irb> @book = Book.new(status: :draft)
irb> @book.status
"draft"
irb> @book.draft?
true
irb> @book.published?
false
irb> @book.status_value
0
irb> @book.status_name
"草稿"
irb> @book.status_color
"#999999"
status_options
方法用在 View 里面的演示:
<% form_for(@book) do |f| %>
<%= f.text_field :name %>
<%= f.select :status, Book.status_options %>
<%= f.submit %>
<% end >