module EnumeratedField::ClassMethods
Public Instance Methods
enum_field(field_name, values_array, options = {})
click to toggle source
ex. enum_field
(:league, [['National Football League', :nfl], ['Major League Baseball', :mlb]]) field_name typically corresponds to the database column name values_array is a double array (not a hash to preserve order for when order matters.. ie select options)
# File lib/enumerated_field.rb, line 15 def enum_field(field_name, values_array, options = {}) values_hash = ActiveSupport::HashWithIndifferentAccess.new values_array.each { |value, key| values_hash[key] = value } default_options = { :validate => true, :allow_nil => false, :allow_blank => false, } options = default_options.merge(options) # returns the values_array for this field, useful for providing to # options_for_select when constructing forms enumerated_class = class << self; self; end enumerated_class.class_eval do define_method("#{field_name}_values") do |*options| options = options.first || {} if options[:first_option] [[options[:first_option], '']] + values_array else values_array end end define_method("#{field_name}_for_json") do values_array.map do |value, key| {:display => value, :value => key} end end end class_eval do unless options[:validate] == false valid_values = values_hash.keys values_hash.keys.map do |key| if key.is_a?(String) and not key.blank? valid_values << key.to_sym else valid_values << key.to_s end end validates field_name, :inclusion => valid_values, :allow_nil => options[:allow_nil], :allow_blank => options[:allow_blank] end values_array.each do |value, key| const_name = "#{field_name}_#{key}".upcase.gsub(/[^\w_]/, "_").to_sym const_set(const_name, key) end define_method("#{field_name}_values") do |*options| self.class.send("#{field_name}_values", *options) end # returns display value for the current value of the field define_method("#{field_name}_display") do values_hash[send(field_name)] end # returns display value for the given value of the field define_method("#{field_name}_display_for") do |key| values_hash[key] end define_method("#{field_name}_value_for") do |key| values_hash.invert[key] end # defines question methods for each possible value of the field # ex. object.league_nfl? which returns true if the objects league # field is currently set to nfl otherwise false values_hash.keys.each do |key| define_method("#{field_name}_#{key}?") { send(field_name).to_s == key.to_s } end if defined? ActiveRecord::Base and ancestors.include? ActiveRecord::Base values_hash.keys.each do |key| scope "#{field_name}_#{key}", ->() { where(field_name => key) } scope "#{field_name}_not_#{key}", ->() { where("#{quoted_table_name}.#{connection.quote_column_name(field_name)} != ?", key) } end end end end