require 'mongoid/enum/version' require 'mongoid/enum/validators/multiple_validator' module Mongoid # Mongoid Enum module Enum extend ActiveSupport::Concern # # Class Methods # # class Model # include Mongoid::Enum # # enum :status, in: %i( waiting approved dismissed ) # module ClassMethods # # Main class method # def enum(field_name, values, options = {}) options = default_options(values).merge(options) set_values_constant field_name, values create_field field_name, options create_i18n_helper field_name, options create_values_helper field_name, options create_validations field_name, values, options define_value_scopes_and_accessors field_name, values, options end private def default_options(values) { :multiple => false, :default => values.first, :required => true, :validate => true } end def set_values_constant(name, values) const_name = name.to_s.upcase const_set const_name, values end def create_field(field_name, options) type = options[:multiple] && Array || Symbol field field_name, :type => type, :default => options[:default] end def create_validations(field_name, values, options) if options[:multiple] && options[:validate] validates field_name, :'mongoid/enum/validators/multiple' => { :in => values, :allow_nil => !options[:required] } elsif validate validates field_name, :inclusion => { :in => values }, :allow_nil => !options[:required] end end def create_i18n_helper(field_name, options) return if options[:i18n].is_a?(FalseClass) define_method("#{field_name}_i18n") do I18n.translate("mongoid.enums.#{model_name.to_s.underscore}."\ "#{field_name}.#{self[field_name]}") end end def create_values_helper(field_name, options) return if options[:i18n].is_a?(FalseClass) define_method("#{field_name}_values") do I18n.translate("mongoid.enums.#{model_name.to_s.underscore}."\ "#{field_name}").map { |k, v| [v, k] } end end def define_value_scopes_and_accessors(field_name, values, options) values.each do |value| unless options[:scope].is_a?(FalseClass) scope value, -> { where(field_name => value) } end next if options[:accessors].is_a?(FalseClass) if options[:multiple] define_array_accessor(field_name, value) else define_string_accessor(field_name, value) end end end def define_array_accessor(field_name, value) class_eval "def #{value}?() self.#{field_name}.include?(:#{value}) end" class_eval "def #{value}!() update_attributes! :#{field_name} => (self.#{field_name} || []) + [:#{value}] end" end def define_string_accessor(field_name, value) class_eval "def #{value}?() self.#{field_name} == :#{value} end" class_eval "def #{value}!() update_attributes! :#{field_name} => :#{value} end" end end end end