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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8146965/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 02:21:26  来源:igfitidea点击:

How do i specify and validate an enum in rails?

ruby-on-railsvalidationactiverecord

提问by Kamilski81

I currently have a model Attend that will have a status column, and this status column will only have a few values for it. STATUS_OPTIONS = {:yes, :no, :maybe}

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

1) I am not sure how i can validate this before a user inserts an Attend? Basically an enum in java but how could i do this in rails?

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

回答by barnett

Now that Rails 4.1includes enums you can do the following:

现在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

Which then provides you with a scope (ie: Attend.yes, Attend.no, Attend.maybefor each a checker method to see if certain status is set (ie: #yes?, #no?, #maybe?), along with attribute setter methods (ie: #yes!, #no!, #maybe!).

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

Rails Docs on enums

关于枚举的 Rails 文档

回答by mnelson

Create a globally accessible array of the options you want, then validate the value of your status column:

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

class Attend < ActiveRecord::Base

  STATUS_OPTIONS = %w(yes no maybe)

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

end

You could then access the possible statuses via Attend::STATUS_OPTIONS

然后您可以通过访问可能的状态 Attend::STATUS_OPTIONS

回答by Benny

This is how I implement in my Rails 4 project.

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

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

Attend.sizes gives you the mapping.

Attend.sizes 为您提供映射。

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

See more in Rails doc

在 Rails 文档中查看更多信息

回答by mu is too short

You could use a string column for the status and then the :inclusionoption for validatesto make sure you only get what you're expecting:

您可以使用一个字符串列作为状态,然后使用:inclusion选项validates来确保您只得到您所期望的:

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

回答by Ken Stipek

What we have started doing is defining our enum items within an array and then using that array for specifying the enum, validations, and using the values within the application.

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

STATUS_OPTIONS = [:yes, :no, :maybe]
enum status_option: STATUS_OPTIONS
validates :status_option, inclusion: { in: STATUS_OPTIONS.map(&:to_s) }

This way you can also use STATUS_OPTIONS later, like for creating a drop down lists. If you want to expose your values to the user you can always map like this:

这样你以后也可以使用 STATUS_OPTIONS,比如创建下拉列表。如果您想向用户公开您的值,您可以始终像这样映射:

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

回答by Yoihito

For enums in ActiveModels you can use this gem Enumerize

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

回答by Ruby Racer

After some looking, I could not find a one-liner in model to help it happen. By now, Rails provides Enums, but not a comprehensive way to validate invalid values.

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

So, I opted for a composite solution: To add a validation in the controller, before setting the strong_params, and then by checking against the model.

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

So, in the model, I will create an attribute and a custom validation:

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

attend.rb

出席.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

Also, I will do a check against the parameters for invalid input and send the result (if necessary) to the model, so an error will be added to the object, thus making it invalid

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

attends_controller.rb

参加_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

回答by Ivan

To define dynamic behavior you can use in: :method_namenotation:

要定义动态行为,您可以使用in: :method_name符号:

class Attend < ActiveRecord::Base
  enum status: [:yes, :no, :maybe]
  validates :status, inclusion: {in: :allowed_statuses}

  private

  # restricts status to be changed from :no to :yes
  def allowed_statuses
    min_status = Attend.statuses[status_was]
    Attend.statuses.select { |_, v| v >= min_status }.keys
  end
end