如何在rails中指定和验证枚举?

时间:2011-11-16 05:02:46

标签: ruby-on-rails validation activerecord

我目前有一个模型Attend会有一个状态列,而这个状态列只有几个值。 STATUS_OPTIONS = {:yes,:no,:maybe}

1)我不确定在用户插入Attend之前我如何验证这一点?基本上是java中的枚举,但我怎么能在rails中做到这一点?

8 个答案:

答案 0 :(得分:64)

现在Rails 4.1包含枚举,您可以执行以下操作:

class Attend < ActiveRecord::Base
    enum size: [:yes, :no, :maybe]
    # also can use the %i() syntax for an array of symbols:
    # %i(yes no maybe)
    validates :size, inclusion: { in: sizes.keys }
end

然后为每个检查器方法提供一个范围(例如:Attend.yesAttend.noAttend.maybe,以查看是否设置了某个状态(即:#yes?#no?#maybe?),以及属性设定方法(即:#yes!#no!#maybe!)。

Rails Docs on enums

答案 1 :(得分:36)

创建所需选项的全局可访问数组,然后验证状态列的值:

class Attend < ActiveRecord::Base

  STATUS_OPTIONS = %w(yes no maybe)

  validates :status, :inclusion => {:in => STATUS_OPTIONS}

end

然后,您可以通过Attend::STATUS_OPTIONS

访问可能的状态

答案 2 :(得分:11)

这是我在Rails 4项目中实现的方式。

class Attend < ActiveRecord::Base
    enum size: [:yes, :no, :maybe]
    validates :size, inclusion: { in: Attend.sizes.keys }
end

Attend.sizes为您提供映射。

Attend.sizes # {"yes" => 0, "no" => 1, "maybe" => 2}

See more in Rails doc

答案 3 :(得分:5)

您可以使用字符串列作为状态,然后使用:inclusion option for validates以确保只获得您期望的内容:

class Attend < ActiveRecord::Base
    validates :size, :inclusion => { :in => %w{yes no maybe} }
    #...
end

答案 4 :(得分:3)

我们开始做的是在数组中定义枚举项,然后使用该数组指定枚举,验证和使用应用程序中的值。

STATUS_OPTIONS = [:yes, :no, :maybe]
enum status_option: STATUS_OPTIONS
validates :status_option, inclusion: { in: STATUS_OPTIONS.map {|t| t.to_s } }

这样您也可以稍后使用STATUS_OPTIONS,就像创建下拉列表一样。如果您想将值公开给用户,您可以像这样映射:

STATUS_OPTIONS.map {|s| s.to_s.titleize }

答案 5 :(得分:1)

对于ActiveModels中的枚举,您可以使用此gem Enumerize

答案 6 :(得分:0)

经过一番观察后,我找不到模型中的单线来帮助它发生。到目前为止,Rails提供了枚举,但不是验证无效值的综合方法。

因此,我选择了一个复合解决方案:在设置strong_params之前在控制器中添加验证,然后检查模型。

因此,在模型中,我将创建一个属性和一个自定义验证:

<强> attend.rb

enum :status => { your set of values }
attr_accessor :invalid_status

validate :valid_status
#...
private
    def valid_status
        if self.invalid_status == true
            errors.add(:status, "is not valid")
        end
    end

另外,我将检查无效输入的参数并将结果(如有必要)发送到模型,因此会将错误添加到对象中,从而使其无效

<强> attends_controller.rb

private
    def attend_params
        #modify strong_params to include the additional check
        if params[:attend][:status].in?(Attend.statuses.keys << nil) # to also allow nil input
            # Leave this as it was before the check
            params.require(:attend).permit(....) 
        else
            params[:attend][:invalid_status] = true
            # remove the 'status' attribute to avoid the exception and
            # inject the attribute to the params to force invalid instance
            params.require(:attend).permit(...., :invalid_status)
       end
    end

答案 7 :(得分:0)

要定义动态行为,可以使用In [32]: tst = pd.DataFrame({"label" : [1, 2, None, 3, None], "value" : ["A", "B", None, "C", None]}) Out[39]: label value 0 1.0 A 1 2.0 B 2 NaN None 3 3.0 C 4 NaN None In [51]: type(tst.value[2]) Out[51]: NoneType In [52]: type(tst.label[2]) Out[52]: numpy.float64 表示法:

in: :method_name