Rails Model中使用枚举有两种方案,一种是rails内置的enum,一种使用enumerize这个gem,不管哪种都能达到相同的目的。

首先介绍第一种:

一. enum

  基本使用方法,以一个案列来说明:

  给已经存在的 Company 增加一个 size 属性, 属性包括 large, medium, small 三个选项。

  从 Rails4.1 开始,可以通过 ActiveRecord::Enum 来快速实现这样的功能:

class Company < ActiveRecord::Base
enum size: [:large, :medium, :small]
end

  这样定义之后,rails会为Company添加一些帮助方法:

Company.sizes
# => {"large"=>0, "medium"=>1, "small"=>2} # Scope methods
Company.large
Company.medium
Company.small # Query methods
company.large?
company.medium? # Action methods
company.large!
company.small!

  迁移写法:

  enum 的实现是基于该字段是一个 integer 类型的。所以添加这个新的字段我们需要下面的 migration:

class AddSizeToCompanies < ActiveRecord::Migration
def change
add_column :companies, :size, :integer, null: false, default: 0
add_index :companies, :size
end
end

  赋值操作:

  通过上面 Company.sizes 方法,我们看到 Rails 默认是从0开始对应的。所以上面的 migration 中默认值是0。当新建一个Company时,默认 company 的 size 是 large

company = Company.new
company.size # => "large" # 多种赋值操作
company.size = :medium
company.medium? # => true company.size = 2
company.small? # => true company.large = 'large'
company.large? # => true

  此外,enum 会自动添加一些验证,如果给 size 属性赋错误的值,Rails会抛出异常: 

company.size = 5
# => ArgumentError: 5 is not a valid billing_category
company.size = :bala
# => ArgumentError: 'bala' is not a valid billing_category

  在Form下拉菜单中怎么使用呢?

f.input :size, collection: Company.sizes.keys.map {|s| [s.titleize, s]}, prompt: "Select a size"

  注意点:

  由于存到数据库的仍然是 number,所以如果有别的应用也使用同样的数据库,那么该应用需要知道对应关系。

  Rails4.1 及之后的版本中,由于 enum 会自动产生一些方法,所以要特别注意选项的命名问题,尽量用明确的命名。

  另外如果你还需要不同的属性,拥有相同的选项,那么你可以考虑这个 gem activerecord-enum-without-methods

  同时在 Rails5 中,就可以使用_prefix_postfix选项来避免相应的问题。·

  更好的Migration方法:

  上面的migration方法对于产品环境已经有数据的情况下,可能会产生问题。

  对于Mysql 数据库,新加字段的时候对于已有的记录,mysql 会自动设置 NOT NULL 的已有记录为 default 但是对于 postgreSQL 就会出现下面的错误:

PG::NotNullViolation: ERROR: column “size” contains null values

  这时可以先add_column添加字段,不要加 NOT NULL 的限制,然后更新已有数据,然后再通过change_column_null来添加 NOT NULL 限制。

二. enumerize

  enumerize是一个gem,使用方法和enum大致相似,就不详细说了,细节可参考项目的github地址:

  https://github.com/brainspec/enumerize

Rails 枚举的更多相关文章

  1. rails enum用于存储数据

    http://api.rubyonrails.org/classes/ActiveRecord/Enum.html 新的项目中有一个字段是展示类型,可以用下拉框去做,用string存储具体的类型字段. ...

  2. rails 常用的验证方法 validates (转)

    Agile Web Development with Rails 17.4 validation validate              在save的时候激活validate_on_create  ...

  3. usaco training 4.1.2 Fence Rails 题解

    Fence Rails题解 Burch, Kolstad, and Schrijvers Farmer John is trying to erect a fence around part of h ...

  4. HDU 4277 USACO ORZ(暴力+双向枚举)

    USACO ORZ Time Limit: 5000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  5. Swift enum(枚举)使用范例

    //: Playground - noun: a place where people can play import UIKit var str = "Hello, playground& ...

  6. 编写高质量代码:改善Java程序的151个建议(第6章:枚举和注解___建议88~92)

    建议88:用枚举实现工厂方法模式更简洁 工厂方法模式(Factory Method Pattern)是" 创建对象的接口,让子类决定实例化哪一个类,并使一个类的实例化延迟到其它子类" ...

  7. Objective-C枚举的几种定义方式与使用

    假设我们需要表示网络连接状态,可以用下列枚举表示: enum CSConnectionState { CSConnectionStateDisconnected, CSConnectionStateC ...

  8. Help Hanzo (素数筛+区间枚举)

    Help Hanzo 题意:求a~b间素数个数(1 ≤ a ≤ b < 231, b - a ≤ 100000).     (全题在文末) 题解: a~b枚举必定TLE,普通打表MLE,真是头疼 ...

  9. 枚举:enum

    枚举 所谓枚举就是指定好取值范围,所有内容只能从指定范围取得. 例如,想定义一个color类,他只能有RED,GREEN,BLUE三种植. 使用简单类完成颜色固定取值问题. 1,就是说,一个类只能完成 ...

随机推荐

  1. Optional int parameter 'id' is present but cannot be translated into a null value due to being decla

    这个错误可以将参数由int改为Integer

  2. shell脚本学习(五)

    流程控制 先说几个注意的地方 1)注意你是在unix下编程,注意文件的编码如果你发现报错请用notepad++打开,编辑->文档格式转换->点unix,然后再上传运行即可 2)sh的流程控 ...

  3. 封装boto3 api用于服务器端与AWS S3交互

    由于使用AWS的时候,需要S3来存储重要的数据. 使用Python的boto3时候,很多重要的参数设置有点繁琐. 重新写了一个类来封装操作S3的api.分享一下: https://github.com ...

  4. AspNet5 Changes to [Activate] in beta-5

    最近在看AspNet Core相关的文章,其中有个TagHelper,看上善若水的博客“关于TagHelper的那些事”,其中有一句 下面来自上善若水的博客原文: 我们知道ASP.NET 5实现了依赖 ...

  5. poj 2773欧几里德

    Happy 2006 Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 5957   Accepted: 1833 Descri ...

  6. 开发Android逆向工具

    韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha  313134555@qq.com 源代码及演示程序,请点击这里下载 下载地址: [北方网通]    [电信网通] [下载说明] ...

  7. About 分块

    分块的的复杂度是带根号的.... 然后,它是一种暴力算法 简单来说就是优化过的暴力 分块算法会对一个序列(长度为N)进行划分,每一块最多有K个元素,这样就会分为N/K块: 一般K取sqrt(N),那么 ...

  8. JZYZOJ1383 [usaco2003feb]impster 位运算 最短路

    http://172.20.6.3/Problem_Show.asp?id=1383  找能到达某个状态的最小操作数,然后把所有状态扫一遍即可,要额外判定一下起始就有的状态(如果起始里没有0那么这些状 ...

  9. [BZOJ 1500] 维护序列

    Link: BZOJ 1500 传送门 Solution: 可能平衡树维护序列的所有操作都在这了吧…… 对序列的维护$fhq treap$和$Splay$都能做 有几个注意点: 1.维护序列时始终记得 ...

  10. BZOJ 1588 [HNOI2002]营业额统计(双向链表)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1588 [题目大意] 给出一个数列,对于每个数,选择其前面的某个数作差取绝对值, 使得所 ...