译:使用ActiveRecord Enums创建简单易读的属性

Creating Easy, Readable Attributes With ActiveRecord Enums

设想一个问题的状态可能为“暂停”,“通过”或“标注”。或者一个电话号码可能是“家庭号码”,“办公号码”,“手机号码”或者“传真号码”(1982年的话)
有些模块需要这种类型的数据:只对应少许值的属性,并且这些值几乎永远不会改变。
如果使用纯Ruby的话,可以通过使用symbol来解决这个问题。
可以创建PhoneNumberType或者QuestionStatus模块,并通过定义belongs_to关系来关联这些值,但是这么简单的需求似乎并不值得这么做,因为仅仅将这些值放在yaml文件中一样可以满足需求。
现在我们来看一个解决这类需求的真正利器:在Rails4.1中引入的 ActiveRecord enums

Model中的少量值

ActiveRecord enums用法很简单,你可以为model创建一个整数类型的列:

bin/rails g model phone number:string phone_number_type:integer

列出这个属性可能的值

class Phone < ActiveRecord::Base
  enum phone_number_type: [:home, :office, :mobile, :fax]
end

现在你可以直接操作字符串而不是数字了。
从前:

irb(main):001:0> Phone.first.phone_number_type
=> 3

采用ActiveRecord enums后:

irb(main):002:0> Phone.first.phone_number_type
=> "fax"

通过字符串或者数字都可以改变属性的值

irb(main):003:0> phone.phone_number_type = 1; phone.phone_number_type
=> "office"
irb(main):004:0> phone.phone_number_type = "mobile"; phone.phone_number_type
=> "mobile"

甚至是通过感叹方法

irb(main):005:0> phone.office!
=> true
irb(main):006:0> phone.phone_number_type
=> "office"

查看属性是否支持某些值:

irb(main):007:0> phone.office?
=> true

查询满足属性值的所有对象:

irb(main):008:0> Phone.office
  Phone Load (0.3ms)  SELECT "phones".* FROM "phones" WHERE "phones"."phone_number_type" = ?  [["phone_number_type", 1]]

查看属性所有可用值:

irb(main):009:0> Phone.phone_number_types
=> {"home"=>0, "office"=>1, "mobile"=>2, "fax"=>3}

在HTML表单中也可以方便使用:

<div class="field">
  <%= f.label :phone_number_type %><br>
  <%= f.select :phone_number_type, Phone.phone_number_types.keys %>
</div>
表单效果

需要注意的是

Enums并不是没有缺陷,如果不想在日后陷入麻烦的话,这里有几个问题需要注意。
定义enum时,注意顺序。假设你突然决定使用字母顺序来排列enum值:

class Phone < ActiveRecord::Base
   enum phone_number_type: [:fax, :home, :mobile, :office]
end

那么你电话号码的类型匹配就有问题咯。可以通过设定序号值来解决这个问题:

class Phone < ActiveRecord::Base
   enum phone_number_type: {fax: 3, home: 0, mobile: 2, office: 1}
end

但是讲真,最好的选择是不要改变值的顺序。
另一个更大的问题存在于Rails之外。尽管Rails将这些enum值当作字符串处理,而在数据库中它们只是一些数字。其他人看原始数据时并不知道这些数字所代表的含义,这就意味着读取这个数据库在所有应用都要有一份enum值的映射。
碰到这样需求的时候可以选择将enum映射存入数据库或yaml文件中。但这不符合DRY原则,因为现在你在两个地方定义了enum。而且随着应用规模的扩展,可能我们一开始想要避免的做法反而更好:创建另一个模型和关联,即Phone belong_to PhoneNumberType
但是如果想保持简单,enums依然是不错的选择。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,865评论 6 13
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,598评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,747评论 6 342
  • 每天拿出时间来放松一下,能保护你的身体,同时增强你的意志力储备。通过深呼吸和休息能更快恢复意志力,同时减少压力...
    铲屎官88阅读 439评论 2 2
  • 在零几年的一天周清包子铺开业了,包子铺老板老周,包子铺助手小魏。生意几年越来越好,其他几个包子铺人都很少,主要就是...
    d8e61f2c6cdf阅读 210评论 0 0