diff options
author | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2014-01-20 21:59:20 -0200 |
---|---|---|
committer | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2014-01-21 12:45:53 -0200 |
commit | a57a2bcf4a2c29519d553277e4439790ca443cc7 (patch) | |
tree | 23cf734ab285435d39130eda92e97888ada742a6 /activerecord | |
parent | a4cc88d0851343ac16e2294c06c5a4101189c410 (diff) | |
download | rails-a57a2bcf4a2c29519d553277e4439790ca443cc7.tar.gz rails-a57a2bcf4a2c29519d553277e4439790ca443cc7.tar.bz2 rails-a57a2bcf4a2c29519d553277e4439790ca443cc7.zip |
Make enum feature work with dirty methods
To make this possible we have to override the save_changed_attribute
hook.
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/CHANGELOG.md | 18 | ||||
-rw-r--r-- | activerecord/lib/active_record/enum.rb | 19 | ||||
-rw-r--r-- | activerecord/test/cases/enum_test.rb | 40 |
3 files changed, 76 insertions, 1 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 170818cd1c..9de076961b 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,21 @@ +* Make enum fields work as expected with the `ActiveModel::Dirty` API. + + Before this change, using the dirty API would have surprising results: + + conversation = Conversation.new + conversation.status = :active + conversation.status = :archived + conversation.status_was # => 0 + + After this change, the same code would result in: + + conversation = Conversation.new + conversation.status = :active + conversation.status = :archived + conversation.status_was # => "active" + + *Rafael Mendonça França* + * Ensure `second` through `fifth` methods act like the `first` finder. The famous ordinal Array instance methods defined in ActiveSupport diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb index 3deb2d65f8..06e87cf854 100644 --- a/activerecord/lib/active_record/enum.rb +++ b/activerecord/lib/active_record/enum.rb @@ -63,6 +63,12 @@ module ActiveRecord # # Conversation.where("status <> ?", Conversation.statuses[:archived]) module Enum + DEFINED_ENUMS = [] # :nodoc: + + def enum_attribute?(attr_name) # :nodoc: + DEFINED_ENUMS.include?(attr_name.to_sym) + end + def enum(definitions) klass = self definitions.each do |name, values| @@ -70,6 +76,8 @@ module ActiveRecord enum_values = ActiveSupport::HashWithIndifferentAccess.new name = name.to_sym + DEFINED_ENUMS.unshift name + # def self.statuses statuses end klass.singleton_class.send(:define_method, name.to_s.pluralize) { enum_values } @@ -114,7 +122,16 @@ module ActiveRecord private def _enum_methods_module @_enum_methods_module ||= begin - mod = Module.new + mod = Module.new do + def save_changed_attribute(attr_name, value) + if self.class.enum_attribute?(attr_name) + old = clone_attribute_value(:read_attribute, attr_name) + changed_attributes[attr_name] = self.class.public_send(attr_name.pluralize).key old + else + super + end + end + end include mod mod end diff --git a/activerecord/test/cases/enum_test.rb b/activerecord/test/cases/enum_test.rb index 1f98801e93..0fe7dfe4ea 100644 --- a/activerecord/test/cases/enum_test.rb +++ b/activerecord/test/cases/enum_test.rb @@ -51,6 +51,46 @@ class EnumTest < ActiveRecord::TestCase assert @book.written? end + test "enum changed attributes" do + old_status = @book.status + @book.status = :published + assert_equal old_status, @book.changed_attributes[:status] + end + + test "enum changes" do + old_status = @book.status + @book.status = :published + assert_equal [old_status, 'published'], @book.changes[:status] + end + + test "enum attribute was" do + old_status = @book.status + @book.status = :published + assert_equal old_status, @book.attribute_was(:status) + end + + test "enum attribute changed" do + @book.status = :published + assert @book.attribute_changed?(:status) + end + + test "enum attribute changed to" do + @book.status = :published + assert @book.attribute_changed?(:status, to: 'published') + end + + test "enum attribute changed from" do + old_status = @book.status + @book.status = :published + assert @book.attribute_changed?(:status, from: old_status) + end + + test "enum attribute changed from old status to new status" do + old_status = @book.status + @book.status = :published + assert @book.attribute_changed?(:status, from: old_status, to: 'published') + end + test "assign non existing value raises an error" do e = assert_raises(ArgumentError) do @book.status = :unknown |