Module: Symbolize::ActiveRecord::ClassMethods
- Defined in:
- lib/symbolize/active_record.rb
Overview
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
Instance Method Summary collapse
-
#symbolize(*attr_names) ⇒ Object
Specifies that values of the given attributes should be returned as symbols.
Instance Method Details
#symbolize(*attr_names) ⇒ Object
Specifies that values of the given attributes should be returned as symbols. The table column should be created of type string.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/symbolize/active_record.rb', line 52 def symbolize *attr_names configuration = {} configuration.update(attr_names.) enum = configuration[:in] || configuration[:within] i18n = configuration.delete(:i18n) || (!enum.instance_of?(Hash) && enum) scopes = configuration.delete :scopes methods = configuration.delete :methods capitalize = configuration.delete :capitalize validation = configuration.delete(:validate) != false default_option = configuration.delete :default unless enum.nil? attr_names.each do |attr_name| attr_name = attr_name.to_s const = "#{attr_name}_values" if enum.is_a?(Hash) values = enum else values = ActiveSupport::OrderedHash.new enum.map do |val| key = val.respond_to?(:to_sym) ? val.to_sym : val values[key] = capitalize ? val.to_s.capitalize : val.to_s end end # Get the values of :in const_set const.upcase, values unless const_defined? const.upcase ev = if i18n # This one is a dropdown helper code = "#{const.upcase}.map { |k,v| [I18n.translate(\"activerecord.symbolizes.\#{ActiveSupport::Inflector.underscore(self.model_name)}.#{attr_name}.\#{k}\"), k] }" #.to_sym rescue nila "def self.get_#{const}; #{code}; end;" else "def self.get_#{const}; #{const.upcase}.map(&:reverse); end" end class_eval(ev) class_eval "def self.#{attr_name}_enum; self.get_#{const}; end" if methods values.each do |value| key = value[0] # 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 self.send(attr_name) == key.to_sym end end end if scopes if scopes == :shallow values.each do |value| name = value[0] if name.respond_to?(:to_sym) scope name.to_sym, -> { where(attr_name => name.to_s) } # Figure out if this as another option, or default... # scope_comm.call "not_#{attr_name}".to_sym, :conditions => { attr_name != name } end end else scope attr_name, ->(enum) { where(attr_name => enum) } end end if validation validation = "validates :#{attr_names.join(', :')}" validation += ", :inclusion => { :in => #{values.keys.inspect} }" validation += ", :allow_nil => true" if configuration[:allow_nil] validation += ", :allow_blank => true" if configuration[:allow_blank] class_eval validation end end end attr_names.each do |attr_name| if default_option class_eval("def #{attr_name}; read_and_symbolize_attribute('#{attr_name}') || :#{default_option}; end") class_eval("def #{attr_name}= (value); write_symbolized_attribute('#{attr_name}', value); end") class_eval("def set_default_for_attr_#{attr_name}; self[:#{attr_name}] ||= :#{default_option}; end") class_eval("before_save :set_default_for_attr_#{attr_name}") else class_eval("def #{attr_name}; read_and_symbolize_attribute('#{attr_name}'); end") class_eval("def #{attr_name}= (value); write_symbolized_attribute('#{attr_name}', value); end") end if i18n class_eval("def #{attr_name}_text; read_i18n_attribute('#{attr_name}'); end") elsif enum class_eval("def #{attr_name}_text; #{attr_name.to_s.upcase}_VALUES[#{attr_name}]; end") else class_eval("def #{attr_name}_text; #{attr_name}.to_s; end") end end end |