symbolize 4.5.0 → 4.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5fa03980e8f95cd5a9f9517d246364128972c3fd
4
- data.tar.gz: 934d6ff3ef97dd046ed3d3d7f5241ee0bebf3bff
3
+ metadata.gz: d8c8248c8a57a1c3e3248a339ec6214fd6fe93ef
4
+ data.tar.gz: 5a2a2faba8acc56b88545a583507a714ea03f495
5
5
  SHA512:
6
- metadata.gz: a1b4cc6c15e0bfb030401926817481f578f4e37d9292066996b3bc42346f6023dfe32ca3a6fb0ebfa7ec9ed8b3d8c41d7e44bf0f9d189b027cb14f3d12e923ec
7
- data.tar.gz: ad06350b50ecd3bcd63abbda8baa36ab34a2fecea34a10c8af86ce50e8421fe135ceda22fb693ac096beca821adf7fffb8b257e4cd678e57281fda95694dd708
6
+ metadata.gz: a6cbd772314ae69fc054ea373487d515f3f3fb6a7eea1144ceda2382c463c0797114a5df969ee7e7e79c48f3f050003b651c5f5a453c7aa096b0dddbb12508c7
7
+ data.tar.gz: 7dea8dbec2121d3357c269bcfad8926db2b3309a5d40a670911a9bdb972fd86ad9e9bad1bc862dede94acffc156c4a62a04fc263eb285e60d87c5d12847c6e3e
data/README.md CHANGED
@@ -56,7 +56,7 @@ Mongoid:
56
56
 
57
57
  Other examples:
58
58
 
59
- symbolize :so, :in => {
59
+ symbolize :os, :in => {
60
60
  :linux => "Linux",
61
61
  :mac => "Mac OS X"
62
62
  }, :scopes => true
data/Rakefile CHANGED
@@ -1,7 +1,9 @@
1
1
  require 'bundler/gem_tasks'
2
2
 
3
3
  require 'rspec/core/rake_task'
4
+ require 'rubocop/rake_task'
4
5
 
5
6
  RSpec::Core::RakeTask.new
7
+ RuboCop::RakeTask.new
6
8
 
7
- task :default => [:spec]
9
+ task :default => [:spec, :rubocop]
@@ -1,4 +1,3 @@
1
- # Todo: is this the best way for AR?
2
1
  module Symbolize
3
2
  autoload :ActiveRecord, 'symbolize/active_record'
4
3
  end
@@ -1,211 +1,219 @@
1
1
  require 'active_support/concern'
2
+ require 'active_support/core_ext/hash/keys'
2
3
 
3
4
  module Symbolize
4
- end
5
-
6
- module Symbolize::ActiveRecord
7
- extend ActiveSupport::Concern
5
+ module ActiveRecord
6
+ extend ActiveSupport::Concern
8
7
 
9
- included do
10
- # Returns an array of all the attributes that have been specified for symbolization
11
- class_attribute :symbolized_attributes, :instance_reader => false
12
- self.symbolized_attributes = []
13
- end
8
+ included do
9
+ # Returns an array of all the attributes that have been specified for symbolization
10
+ class_attribute :symbolized_attributes, :instance_reader => false
11
+ self.symbolized_attributes = []
12
+ end
14
13
 
15
- # Symbolize ActiveRecord attributes. Add
16
- # symbolize :attr_name
17
- # to your model class, to make an attribute return symbols instead of
18
- # string values. Setting such an attribute will accept symbols as well
19
- # as strings. In the database, the symbolized attribute should have
20
- # the column-type :string.
21
- #
22
- # Example:
23
- # class User < ActiveRecord::Base
24
- # symbolize :gender, :in => [:female, :male]
25
- # symbolize :so, :in => {
26
- # :linux => "Linux",
27
- # :mac => "Mac OS X"
28
- # }
29
- # symbolize :gui, , :in => [:gnome, :kde, :xfce], :allow_blank => true
30
- # symbolize :browser, :in => [:firefox, :opera], :i18n => false
31
- # end
32
- #
33
- # It will automattically lookup for i18n:
34
- #
35
- # activerecord:
36
- # symbolizes:
37
- # user:
38
- # gender:
39
- # female: Girl
40
- # male: Boy
41
- #
42
- # You can skip i18n lookup with :i18n => false
43
- # symbolize :gender, :in => [:female, :male], :i18n => false
44
- #
45
- # Its possible to use boolean fields also.
46
- # symbolize :switch, :in => [true, false]
47
- #
48
- # ...
49
- # switch:
50
- # "true": On
51
- # "false": Off
52
- # "nil": Unknown
53
- #
54
- module ClassMethods
55
- # Specifies that values of the given attributes should be returned
56
- # as symbols. The table column should be created of type string.
57
-
58
- def symbolize *attr_names
59
- configuration = {}
60
- configuration.update(attr_names.extract_options!)
61
-
62
- enum = configuration[:in] || configuration[:within]
63
- i18n = configuration.delete(:i18n) || (!enum.instance_of?(Hash) && enum)
64
- scopes = configuration.delete :scopes
65
- methods = configuration.delete :methods
66
- capitalize = configuration.delete :capitalize
67
- validation = configuration.delete(:validate) != false
68
- default_option = configuration.delete :default
69
-
70
- unless enum.nil?
14
+ # Symbolize ActiveRecord attributes. Add
15
+ # symbolize :attr_name
16
+ # to your model class, to make an attribute return symbols instead of
17
+ # string values. Setting such an attribute will accept symbols as well
18
+ # as strings. In the database, the symbolized attribute should have
19
+ # the column-type :string.
20
+ #
21
+ # Example:
22
+ # class User < ActiveRecord::Base
23
+ # symbolize :gender, :in => [:female, :male]
24
+ # symbolize :so, :in => {
25
+ # :linux => "Linux",
26
+ # :mac => "Mac OS X"
27
+ # }
28
+ # symbolize :gui, , :in => [:gnome, :kde, :xfce], :allow_blank => true
29
+ # symbolize :browser, :in => [:firefox, :opera], :i18n => false
30
+ # end
31
+ #
32
+ # It will automattically lookup for i18n:
33
+ #
34
+ # activerecord:
35
+ # symbolizes:
36
+ # user:
37
+ # gender:
38
+ # female: Girl
39
+ # male: Boy
40
+ #
41
+ # You can skip i18n lookup with :i18n => false
42
+ # symbolize :gender, :in => [:female, :male], :i18n => false
43
+ #
44
+ # Its possible to use boolean fields also.
45
+ # symbolize :switch, :in => [true, false]
46
+ #
47
+ # ...
48
+ # switch:
49
+ # "true": On
50
+ # "false": Off
51
+ # "nil": Unknown
52
+ #
53
+ module ClassMethods
54
+ # Specifies that values of the given attributes should be returned
55
+ # as symbols. The table column should be created of type string.
56
+
57
+ def symbolize(*attr_names)
58
+ configuration = attr_names.extract_options!
59
+ configuration.assert_valid_keys(:in, :within, :i18n, :scopes, :methods, :capitalize, :validate, :default, :allow_blank, :allow_nil)
60
+
61
+ enum = configuration[:in] || configuration[:within]
62
+ i18n = configuration[:i18n]
63
+ i18n = enum && !enum.is_a?(Hash) if i18n.nil?
64
+ scopes = configuration[:scopes]
65
+ methods = configuration[:methods]
66
+ capitalize = configuration[:capitalize]
67
+ validation = configuration[:validate] != false
68
+ default_option = configuration[:default]
71
69
 
72
70
  attr_names.each do |attr_name|
73
- attr_name = attr_name.to_s
74
- const = "#{attr_name}_values"
75
- if enum.is_a?(Hash)
76
- values = enum
77
- else
78
- values = ActiveSupport::OrderedHash.new
79
- enum.map do |val|
80
- key = val.respond_to?(:to_sym) ? val.to_sym : val
81
- values[key] = capitalize ? val.to_s.capitalize : val.to_s
71
+ attr_name_str = attr_name.to_s
72
+
73
+ if enum
74
+ enum_hash = \
75
+ if enum.is_a?(Hash)
76
+ enum
77
+ else
78
+ enum.map do |val|
79
+ [
80
+ val.respond_to?(:to_sym) ? val.to_sym : val,
81
+ capitalize ? val.to_s.capitalize : val.to_s,
82
+ ]
83
+ end.to_h
82
84
  end
83
- end
84
85
 
85
- # Get the values of :in
86
- const_set const.upcase, values unless const_defined? const.upcase
87
- ev = if i18n
88
- # This one is a dropdown helper
89
- code = "#{const.upcase}.map { |k,v| [I18n.translate(\"activerecord.symbolizes.\#{ActiveSupport::Inflector.underscore(self.model_name)}.#{attr_name}.\#{k}\"), k] }" #.to_sym rescue nila
90
- "def self.get_#{const}; #{code}; end;"
91
- else
92
- "def self.get_#{const}; #{const.upcase}.map(&:reverse); end"
93
- end
94
- class_eval(ev)
95
- class_eval "def self.#{attr_name}_enum; self.get_#{const}; end"
86
+ values_name = attr_name_str + '_values'
87
+ values_const_name = values_name.upcase
88
+
89
+ # Get the values of :in
90
+ const_set values_const_name, enum_hash unless const_defined? values_const_name
91
+
92
+ [
93
+ 'get_' + values_name,
94
+ attr_name_str + '_enum',
95
+ ].each do |enum_method_name|
96
96
 
97
- if methods
98
- values.each do |value|
99
- key = value[0]
97
+ define_singleton_method(enum_method_name) do
98
+ if i18n
99
+ enum_hash.each_key.map do |symbol|
100
+ [i18n_translation_for(attr_name_str, symbol), symbol]
101
+ end
102
+ else
103
+ enum_hash.map(&:reverse)
104
+ end
105
+ end
106
+ end
100
107
 
101
- # It's a good idea to test for name collisions here and raise exceptions.
102
- # However, the existing software with this kind of errors will start crashing,
103
- # so I'd postpone this improvement until the next major version
104
- # this way it will not affect those people who use ~> in their Gemfiles
108
+ if methods
109
+ enum_hash.each_key do |key|
110
+ # It's a good idea to test for name collisions here and raise exceptions.
111
+ # However, the existing software with this kind of errors will start crashing,
112
+ # so I'd postpone this improvement until the next major version
113
+ # this way it will not affect those people who use ~> in their Gemfiles
105
114
 
106
- # raise ArgumentError, "re-defined #{key}? method of #{self.name} class due to 'symbolize'" if method_defined?("#{key}?")
115
+ # raise ArgumentError, "re-defined #{key}? method of #{self.name} class due to 'symbolize'" if method_defined?("#{key}?")
107
116
 
108
- define_method("#{key}?") do
109
- self.send(attr_name) == key.to_sym
117
+ define_method("#{key}?") do
118
+ send(attr_name_str) == key.to_sym
119
+ end
110
120
  end
111
121
  end
112
- end
113
122
 
114
- if scopes
115
- if scopes == :shallow
116
- values.each do |value|
117
- name = value[0]
118
- if name.respond_to?(:to_sym)
119
- scope name.to_sym, -> { where(attr_name => name.to_s) }
123
+ if scopes
124
+ if scopes == :shallow
125
+ enum_hash.each_key do |name|
126
+ next unless name.respond_to?(:to_sym)
127
+
128
+ scope name, -> { where(attr_name_str => name) }
120
129
  # Figure out if this as another option, or default...
121
- # scope_comm.call "not_#{attr_name}".to_sym, :conditions => { attr_name != name }
130
+ # scope "not_#{name}", -> { where.not(attr_name_str => name)
122
131
  end
132
+ else
133
+ scope attr_name_str, ->(val) { where(attr_name_str => val) }
123
134
  end
124
- else
125
- scope attr_name, ->(enum) { where(attr_name => enum) }
126
135
  end
136
+
137
+ if validation
138
+ validates(*attr_names, configuration.slice(:allow_nil, :allow_blank).merge(:inclusion => { :in => enum_hash.keys }))
139
+ end
140
+ end
141
+
142
+ define_method(attr_name_str) { read_and_symbolize_attribute(attr_name_str) || default_option }
143
+ define_method(attr_name_str + '=') { |value| write_symbolized_attribute(attr_name_str, value) }
144
+
145
+ if default_option
146
+ before_save { self[attr_name_str] ||= default_option }
147
+ else
148
+ define_method(attr_name_str) { read_and_symbolize_attribute(attr_name_str) }
127
149
  end
128
150
 
129
- if validation
130
- validation = "validates :#{attr_names.join(', :')}"
131
- validation += ", :inclusion => { :in => #{values.keys.inspect} }"
132
- validation += ", :allow_nil => true" if configuration[:allow_nil]
133
- validation += ", :allow_blank => true" if configuration[:allow_blank]
134
- class_eval validation
151
+ define_method(attr_name_str + '_text') do
152
+ if i18n
153
+ read_i18n_attribute(attr_name_str)
154
+ else
155
+ attr_value = send(attr_name_str)
156
+ if enum
157
+ enum_hash[attr_value]
158
+ else
159
+ attr_value.to_s
160
+ end
161
+ end
135
162
  end
136
163
  end
137
- end
138
164
 
139
- attr_names.each do |attr_name|
165
+ # merge new symbolized attribute and create a new array to ensure that each class in inheritance hierarchy
166
+ # has its own array of symbolized attributes
167
+ self.symbolized_attributes += attr_names.map(&:to_s)
168
+ end
140
169
 
141
- if default_option
142
- class_eval("def #{attr_name}; read_and_symbolize_attribute('#{attr_name}') || :#{default_option}; end")
143
- class_eval("def #{attr_name}= (value); write_symbolized_attribute('#{attr_name}', value); end")
144
- class_eval("def set_default_for_attr_#{attr_name}; self[:#{attr_name}] ||= :#{default_option}; end")
145
- class_eval("before_save :set_default_for_attr_#{attr_name}")
146
- else
147
- class_eval("def #{attr_name}; read_and_symbolize_attribute('#{attr_name}'); end")
148
- class_eval("def #{attr_name}= (value); write_symbolized_attribute('#{attr_name}', value); end")
170
+ # Hook used by Rails to do extra stuff to attributes when they are initialized.
171
+ def initialize_attributes(*args)
172
+ super.tap do |attributes|
173
+ # Make sure any default values read from the database are symbolized
174
+ symbolized_attributes.each do |attr_name|
175
+ attributes[attr_name] = symbolize_attribute(attributes[attr_name])
176
+ end
149
177
  end
150
- if i18n
151
- class_eval("def #{attr_name}_text; read_i18n_attribute('#{attr_name}'); end")
152
- elsif enum
153
- class_eval("def #{attr_name}_text; #{attr_name.to_s.upcase}_VALUES[#{attr_name}]; end")
178
+ end
179
+
180
+ # String becomes symbol, booleans string and nil nil.
181
+ def symbolize_attribute(value)
182
+ case value
183
+ when String
184
+ value.presence.try(:to_sym)
185
+ when Symbol, TrueClass, FalseClass, Numeric
186
+ value
154
187
  else
155
- class_eval("def #{attr_name}_text; #{attr_name}.to_s; end")
188
+ nil
156
189
  end
157
190
  end
158
191
 
159
- # merge new symbolized attribute and create a new array to ensure that each class in inheritance hierarchy
160
- # has its own array of symbolized attributes
161
- self.symbolized_attributes += attr_names.map(&:to_s)
162
- end
163
-
164
- # Hook used by Rails to do extra stuff to attributes when they are initialized.
165
- def initialize_attributes *args
166
- super.tap do |attributes|
167
- # Make sure any default values read from the database are symbolized
168
- symbolized_attributes.each do |attr_name|
169
- attributes[attr_name] = symbolize_attribute(attributes[attr_name])
170
- end
192
+ def i18n_translation_for(attr_name, attr_value)
193
+ I18n.translate("activerecord.symbolizes.#{model_name.to_s.underscore}.#{attr_name}.#{attr_value}")
171
194
  end
172
195
  end
173
196
 
174
197
  # String becomes symbol, booleans string and nil nil.
175
- def symbolize_attribute value
176
- case value
177
- when String
178
- value.presence.try(:to_sym)
179
- when Symbol, TrueClass, FalseClass, Numeric
180
- value
181
- else
182
- nil
183
- end
198
+ def symbolize_attribute(value)
199
+ self.class.symbolize_attribute(value)
184
200
  end
185
- end
186
-
187
- # String becomes symbol, booleans string and nil nil.
188
- def symbolize_attribute value
189
- self.class.symbolize_attribute value
190
- end
191
-
192
- # Return an attribute's value as a symbol or nil
193
- def read_and_symbolize_attribute attr_name
194
- symbolize_attribute self[attr_name]
195
- end
196
201
 
197
- # Return an attribute's i18n
198
- def read_i18n_attribute attr_name
199
- attr = read_attribute(attr_name)
200
- t = I18n.translate("activerecord.symbolizes.#{self.class.model_name.to_s.underscore}.#{attr_name}.#{attr}") #.to_sym rescue nila
201
- t.is_a?(Hash) ? nil : t
202
- end
202
+ # Return an attribute's value as a symbol or nil
203
+ def read_and_symbolize_attribute(attr_name)
204
+ symbolize_attribute(read_attribute(attr_name))
205
+ end
203
206
 
204
- # Write a symbolized value. Watch out for booleans.
205
- def write_symbolized_attribute attr_name, value
206
- val = { "true" => true, "false" => false }[value]
207
- val = symbolize_attribute(value) if val.nil?
207
+ # Return an attribute's i18n
208
+ def read_i18n_attribute(attr_name)
209
+ unless (t = self.class.i18n_translation_for(attr_name, read_attribute(attr_name))).is_a?(Hash)
210
+ t
211
+ end
212
+ end
208
213
 
209
- self[attr_name] = val #.to_s
214
+ # Write a symbolized value. Watch out for booleans.
215
+ def write_symbolized_attribute(attr_name, value)
216
+ write_attribute(attr_name, symbolize_attribute(value))
217
+ end
210
218
  end
211
219
  end
@@ -1,4 +1,5 @@
1
1
  require 'active_support/concern'
2
+ require 'active_support/core_ext/hash/keys'
2
3
 
3
4
  module Mongoid
4
5
  module Symbolize
@@ -49,106 +50,117 @@ module Mongoid
49
50
  # Specifies that values of the given attributes should be returned
50
51
  # as symbols. The table column should be created of type string.
51
52
 
52
- def symbolize *attr_names
53
- configuration = {}
54
- configuration.update(attr_names.extract_options!)
53
+ def symbolize(*attr_names)
54
+ configuration = attr_names.extract_options!
55
+ configuration.assert_valid_keys(:in, :within, :i18n, :scopes, :methods, :capitalize, :validate, :default, :allow_blank, :allow_nil, :type)
55
56
 
56
- enum = configuration[:in] || configuration[:within]
57
- i18n = configuration.delete(:i18n)
58
- i18n = (!enum.instance_of?(Hash) && enum) if i18n.nil?
59
- scopes = configuration.delete :scopes
60
- methods = configuration.delete :methods
61
- capitalize = configuration.delete :capitalize
62
- validation = configuration.delete(:validate) != false
63
- field_type = configuration.delete :type
64
- default_opt = configuration.delete :default
65
- enum = [true, false] if [Boolean, ::Boolean].include?(field_type)
57
+ enum = configuration[:in] || configuration[:within]
58
+ i18n = configuration[:i18n]
59
+ i18n = enum && !enum.is_a?(Hash) if i18n.nil?
60
+ scopes = configuration[:scopes]
61
+ methods = configuration[:methods]
62
+ capitalize = configuration[:capitalize]
63
+ validation = configuration[:validate] != false
64
+ default_option = configuration[:default]
66
65
 
67
- unless enum.nil?
66
+ field_type = configuration[:type] || Symbol
67
+ enum = [true, false] if [Boolean, ::Boolean].include?(field_type)
68
68
 
69
- attr_names.each do |attr_name|
70
- # attr_name = attr_name.to_s
71
-
72
- #
73
- # Builds Mongoid 'field :name, type: type, :default'
74
- #
75
- const = "#{attr_name}_values"
76
- mongo_opts = ", :type => #{field_type || 'Symbol'}"
77
- mongo_opts += ", :default => :#{default_opt}" if default_opt
78
- class_eval("field :#{attr_name} #{mongo_opts}")
69
+ attr_names.each do |attr_name|
70
+ attr_name_str = attr_name.to_s
79
71
 
72
+ if enum
73
+ enum_hash = \
80
74
  if enum.is_a?(Hash)
81
- values = enum
75
+ enum
82
76
  else
83
- values = {}
84
- enum.map do |val|
85
- key = val.respond_to?(:to_sym) ? val.to_sym : val
86
- values[key] = capitalize ? val.to_s.capitalize : val.to_s
77
+ enum.each_with_object({}) do |val, hsh|
78
+ hsh.store(val.respond_to?(:to_sym) ? val.to_sym : val,
79
+ capitalize ? val.to_s.capitalize : val.to_s)
87
80
  end
88
81
  end
89
82
 
83
+ #
84
+ # Builds Mongoid 'field :name, type: type, :default'
85
+ #
86
+ { :type => field_type }.tap do |field_opts|
87
+ field_opts.merge!(:default => default_option) if default_option
88
+ field attr_name, field_opts
89
+ end
90
+
91
+ values_name = attr_name_str + '_values'
92
+ values_const_name = values_name.upcase
93
+
90
94
  # Get the values of :in
91
- const_set const.upcase, values unless const_defined? const.upcase
92
- ev = if i18n
93
- # This one is a dropdown helper
94
- code = "#{const.upcase}.map { |k,v| [I18n.t(\"mongoid.symbolizes.\#{ActiveSupport::Inflector.underscore(self.model_name)}.#{attr_name}.\#{k}\"), k] }" #.to_sym rescue nila
95
- "def self.get_#{const}; #{code}; end;"
96
- else
97
- "def self.get_#{const}; #{const.upcase}.map(&:reverse); end"
98
- end
99
- class_eval(ev)
100
- class_eval "def self.#{attr_name}_enum; self.get_#{const}; end"
95
+ const_set values_const_name, enum_hash unless const_defined? values_const_name
96
+
97
+ [
98
+ 'get_' + values_name, attr_name_str + '_enum'
99
+ ].each do |enum_method_name|
100
+
101
+ define_singleton_method(enum_method_name) do
102
+ if i18n
103
+ enum_hash.each_key.map do |symbol|
104
+ [i18n_translation_for(attr_name_str, symbol), symbol]
105
+ end
106
+ else
107
+ enum_hash.map(&:reverse)
108
+ end
109
+ end
110
+ end
101
111
 
102
112
  if methods
103
- values.each do |k, v|
104
- define_method("#{k}?") do
105
- self.send(attr_name) == k
113
+ enum_hash.each_key do |key|
114
+ define_method("#{key}?") do
115
+ send(attr_name_str) == key.to_sym
106
116
  end
107
117
  end
108
118
  end
109
119
 
110
120
  if scopes
111
121
  if scopes == :shallow
112
- values.each do |k, v|
113
- next unless k.respond_to?(:to_sym)
114
- scope k.to_sym, -> { where(attr_name => k) }
122
+ enum_hash.each_key do |name|
123
+ next unless name.respond_to?(:to_sym)
124
+ scope name, -> { where(attr_name_str => name) }
115
125
  end
116
126
  else # scoped scopes
117
- scope attr_name, ->(enum) { where(attr_name => enum) }
127
+ scope attr_name_str, ->(val) { where(attr_name_str => val) }
118
128
  end
119
129
  end
120
130
 
121
131
  if validation
122
- v = "validates :#{attr_names.join(', :')}" +
123
- ",:inclusion => { :in => #{values.keys.inspect} }"
124
- v += ',:allow_nil => true' if configuration[:allow_nil]
125
- v += ',:allow_blank => true' if configuration[:allow_blank]
126
- class_eval v
132
+ validates(*attr_names, configuration.slice(:allow_nil, :allow_blank).merge(:inclusion => { :in => enum_hash.keys }))
127
133
  end
128
-
129
134
  end
130
- end
131
135
 
132
- #
133
- # Creates <attribute>_text helper, human text for attribute.
134
- #
135
- attr_names.each do |attr_name|
136
- if i18n # memoize call to translate... good idea?
137
- define_method "#{attr_name}_text" do
138
- attr = read_attribute(attr_name)
139
- return nil if attr.nil?
140
- I18n.t("mongoid.symbolizes.#{self.class.model_name.to_s.underscore}.#{attr_name}.#{attr}")
136
+ #
137
+ # Creates <attribute>_text helper, human text for attribute.
138
+ #
139
+ define_method(attr_name_str + '_text') do
140
+ if i18n
141
+ read_i18n_attribute(attr_name_str)
142
+ else
143
+ attr_value = send(attr_name_str)
144
+ if enum
145
+ enum_hash[attr_value]
146
+ else
147
+ attr_value.to_s
148
+ end
141
149
  end
142
- elsif enum
143
- class_eval("def #{attr_name}_text; #{attr_name.to_s.upcase}_VALUES[#{attr_name}]; end")
144
- else
145
- class_eval("def #{attr_name}_text; #{attr_name}.to_s; end")
146
150
  end
147
- end
148
151
 
152
+ def i18n_translation_for(attr_name, attr_value)
153
+ I18n.translate("mongoid.symbolizes.#{model_name.to_s.underscore}.#{attr_name}.#{attr_value}")
154
+ end
155
+ end
149
156
  end
150
-
151
157
  end # ClassMethods
158
+
159
+ # Return an attribute's i18n
160
+ def read_i18n_attribute(attr_name)
161
+ t = self.class.i18n_translation_for(attr_name, read_attribute(attr_name))
162
+ t.is_a?(Hash) ? nil : t
163
+ end
152
164
  end # Symbolize
153
165
  end # Mongoid
154
166