Skip to content

Commit

Permalink
Define id_was to get the previous value of the primary key
Browse files Browse the repository at this point in the history
Currently when we call id_was and we have a custom primary key name
Active Record will return the current value of the primary key. This
make impossible to correctly do an update operation if you change the
id.

Fixes #16413
  • Loading branch information
rafaelfranca committed Aug 7, 2014
1 parent ee25579 commit e6e81f8
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 1 deletion.
11 changes: 11 additions & 0 deletions activerecord/CHANGELOG.md
Original file line number Original file line Diff line number Diff line change
@@ -1,3 +1,14 @@
* Define `id_was` to get the previous value of the primary key.

Currently when we call id_was and we have a custom primary key name
Active Record will return the current value of the primary key. This
make impossible to correctly do an update operation if you change the
id.

Fixes #16413.

*Rafael Mendonça França*

* Deprecate `DatabaseTasks.load_schema` to act on the current connection. * Deprecate `DatabaseTasks.load_schema` to act on the current connection.
Use `.load_schema_current` instead. In the future `load_schema` will Use `.load_schema_current` instead. In the future `load_schema` will
require the `configuration` to act on as an argument. require the `configuration` to act on as an argument.
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ def id_before_type_cast
read_attribute_before_type_cast(self.class.primary_key) read_attribute_before_type_cast(self.class.primary_key)
end end


# Returns the primary key previous value.
def id_was
sync_with_transaction_state
attribute_was(self.class.primary_key)
end

protected protected


def attribute_method?(attr_name) def attribute_method?(attr_name)
Expand All @@ -54,7 +60,7 @@ def define_method_attribute(attr_name)
end end
end end


ID_ATTRIBUTE_METHODS = %w(id id= id? id_before_type_cast).to_set ID_ATTRIBUTE_METHODS = %w(id id= id? id_before_type_cast id_was).to_set


def dangerous_attribute_method?(method_name) def dangerous_attribute_method?(method_name)
super && !ID_ATTRIBUTE_METHODS.include?(method_name) super && !ID_ATTRIBUTE_METHODS.include?(method_name)
Expand Down
10 changes: 10 additions & 0 deletions activerecord/test/cases/primary_keys_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require 'models/movie' require 'models/movie'
require 'models/keyboard' require 'models/keyboard'
require 'models/mixed_case_monkey' require 'models/mixed_case_monkey'
require 'models/dashboard'


class PrimaryKeysTest < ActiveRecord::TestCase class PrimaryKeysTest < ActiveRecord::TestCase
fixtures :topics, :subscribers, :movies, :mixed_case_monkeys fixtures :topics, :subscribers, :movies, :mixed_case_monkeys
Expand Down Expand Up @@ -164,6 +165,15 @@ def test_auto_detect_primary_key_from_schema
MixedCaseMonkey.reset_primary_key MixedCaseMonkey.reset_primary_key
assert_equal "monkeyID", MixedCaseMonkey.primary_key assert_equal "monkeyID", MixedCaseMonkey.primary_key
end end

def test_primary_key_update_with_custom_key_name
dashboard = Dashboard.create!(dashboard_id: '1')
dashboard.id = '2'
dashboard.save!

dashboard = Dashboard.first
assert_equal '2', dashboard.id
end
end end


class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase
Expand Down

0 comments on commit e6e81f8

Please sign in to comment.