module Symbolize::ActiveRecord::ClassMethods
Symbolize
ActiveRecord
attributes. Add
symbolize :attr_name
to your model class, to make an attribute return symbols instead of string values. Setting such an attribute will accept symbols as well as strings. In the database, the symbolized attribute should have the column-type :string.
Example:
class User < ActiveRecord::Base symbolize :gender, :in => [:female, :male] symbolize :so, :in => { :linux => "Linux", :mac => "Mac OS X" } symbolize :gui, , :in => [:gnome, :kde, :xfce], :allow_blank => true symbolize :browser, :in => [:firefox, :opera], :i18n => false end
It will automattically lookup for i18n:
activerecord:
symbolizes: user: gender: female: Girl male: Boy
You can skip i18n lookup with :i18n => false
symbolize :gender, :in => [:female, :male], :i18n => false
Its possible to use boolean fields also.
symbolize :switch, :in => [true, false] ... switch: "true": On "false": Off "nil": Unknown
Public Instance Methods
i18n_translation_for(attr_name, attr_value)
click to toggle source
# File lib/symbolize/active_record.rb, line 190 def i18n_translation_for(attr_name, attr_value) I18n.translate("activerecord.symbolizes.#{model_name.to_s.underscore}.#{attr_name}.#{attr_value}") end
initialize_attributes(*args)
click to toggle source
Hook used by Rails to do extra stuff to attributes when they are initialized.
Calls superclass method
# File lib/symbolize/active_record.rb, line 169 def initialize_attributes(*args) super.tap do |attributes| # Make sure any default values read from the database are symbolized symbolized_attributes.each do |attr_name| attributes[attr_name] = symbolize_attribute(attributes[attr_name]) end end end
symbolize(*attr_names)
click to toggle source
Specifies that values of the given attributes should be returned as symbols. The table column should be created of type string.
# File lib/symbolize/active_record.rb, line 57 def symbolize(*attr_names) configuration = attr_names.extract_options! configuration.assert_valid_keys(:in, :within, :i18n, :scopes, :methods, :capitalize, :validate, :default, :allow_blank, :allow_nil) enum = configuration[:in] || configuration[:within] i18n = configuration[:i18n] i18n = enum && !enum.is_a?(Hash) if i18n.nil? scopes = configuration[:scopes] methods = configuration[:methods] capitalize = configuration[:capitalize] validation = configuration[:validate] != false default_option = configuration[:default] attr_names.each do |attr_name| attr_name_str = attr_name.to_s if enum enum_hash = \ if enum.is_a?(Hash) enum else enum.each_with_object({}) do |e, a| a.store(e.respond_to?(:to_sym) ? e.to_sym : e, capitalize ? e.to_s.capitalize : e.to_s) end end values_name = attr_name_str + '_values' values_const_name = values_name.upcase # Get the values of :in const_set values_const_name, enum_hash unless const_defined? values_const_name [ 'get_' + values_name, attr_name_str + '_enum', ].each do |enum_method_name| define_singleton_method(enum_method_name) do if i18n enum_hash.each_key.map do |symbol| [i18n_translation_for(attr_name_str, symbol), symbol] end else enum_hash.map(&:reverse) end end end if methods enum_hash.each_key do |key| # It's a good idea to test for name collisions here and raise exceptions. # However, the existing software with this kind of errors will start crashing, # so I'd postpone this improvement until the next major version # this way it will not affect those people who use ~> in their Gemfiles # raise ArgumentError, "re-defined #{key}? method of #{self.name} class due to 'symbolize'" if method_defined?("#{key}?") define_method("#{key}?") do send(attr_name_str) == key.to_sym end end end if scopes if scopes == :shallow enum_hash.each_key do |name| next unless name.respond_to?(:to_sym) scope name, -> { where(attr_name_str => name) } # Figure out if this as another option, or default... # scope "not_#{name}", -> { where.not(attr_name_str => name) end else scope attr_name_str, ->(val) { where(attr_name_str => val) } end end if validation validates(*attr_names, configuration.slice(:allow_nil, :allow_blank).merge(:inclusion => { :in => enum_hash.keys })) end end define_method(attr_name_str) { read_and_symbolize_attribute(attr_name_str) || default_option } define_method(attr_name_str + '=') { |value| write_symbolized_attribute(attr_name_str, value) } if default_option before_save { self[attr_name_str] ||= default_option } else define_method(attr_name_str) { read_and_symbolize_attribute(attr_name_str) } end define_method(attr_name_str + '_text') do if i18n read_i18n_attribute(attr_name_str) else attr_value = send(attr_name_str) if enum enum_hash[attr_value] else attr_value.to_s end end end end # merge new symbolized attribute and create a new array to ensure that each class in inheritance hierarchy # has its own array of symbolized attributes self.symbolized_attributes += attr_names.map(&:to_s) end
symbolize_attribute(value)
click to toggle source
String becomes symbol, booleans string and nil nil.
# File lib/symbolize/active_record.rb, line 179 def symbolize_attribute(value) case value when String value.presence.try(:to_sym) when Symbol, TrueClass, FalseClass, Numeric value else nil end end