• 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

  • 相关阅读:
    ERROR 000732:Output Geodatabase:Dataset Database ConnectionsConnection to localhost.sdeSDE.Dataset does not exist or is not supported
    【转】通过 INotifyPropertyChanged 实现观察者模式
    Fatal NI connect error 6413的解决办法 http://www.itpub.net/thread-107518-1-1.html
    Oracle impdp的ignore及 fromuser / touser 功能
    进度条插件使用demo
    两个div并列居中显示——当display:inline-block;时,两个div无法对齐即一高一矮
    两个div并列居中显示——当display:inline;时,div的宽高不起作用即两个div重叠显示
    轮播插件unslider.min.js使用demo
    WEB网页如何让背景图片跟随可视窗口自适应大小
    火狐浏览器不支持location.reload()(以改变页面大小时重新刷新页面为例)
  • 原文地址:https://www.cnblogs.com/gdpdroid/p/7325259.html
Copyright © 2020-2023  润新知