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. 阿里云Maven仓库配置,Maven镜像配置

    Jenkins通过maven对java代码打包编译时,速度太慢,所以修改为阿里的Maven仓库 修改如下: [root@7mini-node2 conf]# vim /software/apache- ...

  2. bootstrap插件学习-bootstrap.tab.js(读码)

    先看bootstrap-tab.js的结构 var Tab = function ( element ) {} //构造器 Tab.prototype ={} //构造器的原型 $.fn.tab = ...

  3. gdbserver静态编译

    redhat9 编译gdb server(静态编译)下载gdb-6.2a.tar:http://download.chinaunix.net/download.php?id=6680&Reso ...

  4. 离线情报分析工具CaseFile

    离线情报分析工具CaseFile   CaseFile是Maltego的姊妹工具,功能非常类似于Maltego.CaseFile主要针对数据进行离线分析,缺少Maltego的数据采集功能.它可以导入各 ...

  5. [Codeforces-div.1 494B]Obsessive String

    [CF-div.1 B]Obsessive String 题目大意 两个字符串\(S,T\),求划分方案数使得一个集合中两两划分不相交且划分都包含字符串\(T\) 试题分析 kmp先求出那个位置匹配. ...

  6. 【构造】CDOJ1607 大学生足球联赛

    请自行百度逆时针轮转法 //单循环赛 逆时针轮转法 #include<cstdio> using namespace std; int n,a[70]; int main(){ scanf ...

  7. nginx和php-fpm的用户权限

    启动php-fpm sudo php-fpm -c /etc/php.ini [17-Sep-2018 00:36:59] ERROR: [pool www] please specify user ...

  8. Token-Pasting Operator (##) and Stringizing Operator (#)

    Token-Pasting Operator (##)The double-number-sign or “token-pasting” operator (##), which is sometim ...

  9. 基于 Dapper 的一个 DbUtils

    /// <summary> /// v1.0 /// </summary> public partial class DbUtils { string ConnectionSt ...

  10. rust安装

    http://blog.csdn.net/teamlet/article/details/50838996