How do i specify and validate an enum in rails?

前端 未结 8 1700
南笙
南笙 2020-12-30 20:15

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}

1)

相关标签:
8条回答
  • 2020-12-30 20:40

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

    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.maybe for each a checker method to see if certain status is set (ie: #yes?, #no?, #maybe?), along with attribute setter methods (ie: #yes!, #no!, #maybe!).

    Rails Docs on enums

    0 讨论(0)
  • 2020-12-30 20:42

    To define dynamic behavior you can use in: :method_name notation:

    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
    
    0 讨论(0)
  • 2020-12-30 20:45

    For enums in ActiveModels you can use this gem Enumerize

    0 讨论(0)
  • 2020-12-30 20:45

    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.

    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.

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

    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
    

    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

    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
    
    0 讨论(0)
  • 2020-12-30 20:51

    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

    0 讨论(0)
  • 2020-12-30 20:55

    You could use a string column for the status and then the :inclusion option for validates to make sure you only get what you're expecting:

    class Attend < ActiveRecord::Base
        validates :size, :inclusion => { :in => %w{yes no maybe} }
        #...
    end
    
    0 讨论(0)
提交回复
热议问题