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
- #i18n_translation_for(attr_name, attr_value) ⇒ Object
-
#initialize_attributes(*args) ⇒ Object
Hook used by Rails to do extra stuff to attributes when they are initialized.
-
#symbolize(*attr_names) ⇒ Object
Specifies that values of the given attributes should be returned as symbols.
-
#symbolize_attribute(value) ⇒ Object
String becomes symbol, booleans string and nil nil.
Instance Method Details
#i18n_translation_for(attr_name, attr_value) ⇒ Object
190 191 192 |
# 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) ⇒ Object
Hook used by Rails to do extra stuff to attributes when they are initialized.
169 170 171 172 173 174 175 176 |
# 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) ⇒ Object
Specifies that values of the given attributes should be returned as symbols. The table column should be created of type string.
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 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/symbolize/active_record.rb', line 57 def symbolize(*attr_names) configuration = attr_names. 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) ⇒ Object
String becomes symbol, booleans string and nil nil.
179 180 181 182 183 184 185 186 187 188 |
# 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 |