diff options
-rw-r--r-- | activerecord/CHANGELOG.md | 18 | ||||
-rw-r--r-- | activerecord/lib/active_record/enum.rb | 17 | ||||
-rw-r--r-- | activerecord/test/cases/enum_test.rb | 6 |
3 files changed, 31 insertions, 10 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index ada5a57f3b..e85300c951 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,21 @@ +* Enum mappings are now exposed via class methods instead of constants. + + Example: + + class Conversation < ActiveRecord::Base + enum status: [ :active, :archived ] + end + + Before: + + Conversation::STATUS # => { "active" => 0, "archived" => 1 } + + After: + + Conversation.statuses # => { "active" => 0, "archived" => 1 } + + *Godfrey Chan* + * Set `NameError#name` when STI-class-lookup fails. *Chulki Lee* diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb index d1bc785bee..c34fc086e2 100644 --- a/activerecord/lib/active_record/enum.rb +++ b/activerecord/lib/active_record/enum.rb @@ -56,21 +56,24 @@ module ActiveRecord # In rare circumstances you might need to access the mapping directly. # The mappings are exposed through a constant with the attributes name: # - # Conversation::STATUS # => { "active" => 0, "archived" => 1 } + # Conversation.statuses # => { "active" => 0, "archived" => 1 } # # Use that constant when you need to know the ordinal value of an enum: # - # Conversation.where("status <> ?", Conversation::STATUS[:archived]) + # Conversation.where("status <> ?", Conversation.statuses[:archived]) module Enum def enum(definitions) klass = self definitions.each do |name, values| - # STATUS = { } - enum_values = _enum_methods_module.const_set name.to_s.upcase, ActiveSupport::HashWithIndifferentAccess.new + # statuses = { } + enum_values = ActiveSupport::HashWithIndifferentAccess.new name = name.to_sym + # def self.statuses statuses end + klass.singleton_class.send(:define_method, name.to_s.pluralize) { enum_values } + _enum_methods_module.module_eval do - # def status=(value) self[:status] = STATUS[value] end + # def status=(value) self[:status] = statuses[value] end define_method("#{name}=") { |value| if enum_values.has_key?(value) || value.blank? self[name] = enum_values[value] @@ -84,10 +87,10 @@ module ActiveRecord end } - # def status() STATUS.key self[:status] end + # def status() statuses.key self[:status] end define_method(name) { enum_values.key self[name] } - # def status_before_type_cast() STATUS.key self[:status] end + # def status_before_type_cast() statuses.key self[:status] end define_method("#{name}_before_type_cast") { enum_values.key self[name] } pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index diff --git a/activerecord/test/cases/enum_test.rb b/activerecord/test/cases/enum_test.rb index 0075df8b8d..1f98801e93 100644 --- a/activerecord/test/cases/enum_test.rb +++ b/activerecord/test/cases/enum_test.rb @@ -74,9 +74,9 @@ class EnumTest < ActiveRecord::TestCase end test "constant to access the mapping" do - assert_equal 0, Book::STATUS[:proposed] - assert_equal 1, Book::STATUS["written"] - assert_equal 2, Book::STATUS[:published] + assert_equal 0, Book.statuses[:proposed] + assert_equal 1, Book.statuses["written"] + assert_equal 2, Book.statuses[:published] end test "building new objects with enum scopes" do |