Rails 枚举
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 枚举的更多相关文章
- rails enum用于存储数据
http://api.rubyonrails.org/classes/ActiveRecord/Enum.html 新的项目中有一个字段是展示类型,可以用下拉框去做,用string存储具体的类型字段. ...
- rails 常用的验证方法 validates (转)
Agile Web Development with Rails 17.4 validation validate 在save的时候激活validate_on_create ...
- 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 ...
- HDU 4277 USACO ORZ(暴力+双向枚举)
USACO ORZ Time Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- Swift enum(枚举)使用范例
//: Playground - noun: a place where people can play import UIKit var str = "Hello, playground& ...
- 编写高质量代码:改善Java程序的151个建议(第6章:枚举和注解___建议88~92)
建议88:用枚举实现工厂方法模式更简洁 工厂方法模式(Factory Method Pattern)是" 创建对象的接口,让子类决定实例化哪一个类,并使一个类的实例化延迟到其它子类" ...
- Objective-C枚举的几种定义方式与使用
假设我们需要表示网络连接状态,可以用下列枚举表示: enum CSConnectionState { CSConnectionStateDisconnected, CSConnectionStateC ...
- Help Hanzo (素数筛+区间枚举)
Help Hanzo 题意:求a~b间素数个数(1 ≤ a ≤ b < 231, b - a ≤ 100000). (全题在文末) 题解: a~b枚举必定TLE,普通打表MLE,真是头疼 ...
- 枚举:enum
枚举 所谓枚举就是指定好取值范围,所有内容只能从指定范围取得. 例如,想定义一个color类,他只能有RED,GREEN,BLUE三种植. 使用简单类完成颜色固定取值问题. 1,就是说,一个类只能完成 ...
随机推荐
- python多线程编程(6): 队列同步
原文请看:http://www.cnblogs.com/holbrook/archive/2012/03/15/2398060.html 前面介绍了互斥锁和条件变量解决线程间的同步问题,并使用条件变量 ...
- [THINKPHP] 温故知新之getFieldBy
1.getFieldBy id name 1 Mike 需求1:想要获取Mike M('table')->getFieldById('1','name'); 需求2:想要获取id的值1 M('t ...
- Java工具类-设置字符编码
package common; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.Filter ...
- msysgit: Unicode font warning
Warning:your console font probably does not support unicode , if you experience strange characters ...
- 洛谷——P2708 硬币翻转
P2708 硬币翻转 题目背景 难度系数:☆☆☆☆☆(如果你看懂了) 题目描述 从前有很多个硬币摆在一行,有正面朝上的,也有背面朝上的.正面朝上的用1表示,背面朝上的用0表示.现在要求从这行的第一个硬 ...
- 第4天:Ansible模块
Ansible对远程服务器的实际操作实际是通过模块完成的,其工作原理如下: 1)将模块拷贝到远程服务器 2)执行模块定义的操做,完成对服务器的修改 3)在远程服务器中删除模块 需要说明的是,Ansib ...
- NGUI的异步场景加载进度条
1.直接创建三个场景,其中第二个场景是用来显示进度条加载的界面,进度条用UISlider,不会的看我前面的博文就可以了. 2.这里提供两种方法,建议使用第一种,加载比较平缓 方法一: using Sy ...
- BZOJ 2809 [Apio2012]dispatching(斜堆+树形DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2809 [题目大意] 给出一棵树,求出每个点有个权值,和一个乘算值,请选取一棵子树, 并 ...
- Gym 101128F Sheldon Numbers(网络流)
[题目链接] http://codeforces.com/gym/101128/attachments [题目大意] 给出一张地图,分为高地和低地,高低地的交界线上划有红线, 现在要开小车跨过每条红线 ...
- 【贪心】【multiset】Tinkoff Challenge - Final Round (Codeforces Round #414, rated, Div. 1 + Div. 2) C. Naming Company
考虑两个人,先把各自的集合排个序,丢掉一半,因为比较劣的那一半一定用不到. 然后贪心地放,只有两种决策,要么把一个最优的放在开头,要么把一个最劣的放在结尾. 如果我的最优的比对方所有的都劣(或等于), ...