aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md2
-rw-r--r--activerecord/lib/active_record/attribute_methods/dirty.rb7
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/savepoints.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb4
-rw-r--r--activerecord/lib/active_record/relation.rb14
-rw-r--r--activerecord/lib/active_record/touch_later.rb1
-rw-r--r--activerecord/lib/active_record/transactions.rb4
-rw-r--r--activerecord/lib/rails/generators/active_record/migration/migration_generator.rb1
-rw-r--r--activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb4
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb20
-rw-r--r--activerecord/test/cases/test_case.rb10
16 files changed, 58 insertions, 37 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index f708d42e43..8c5342edb2 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,5 @@
+* Allow generated `create_table` migrations to include or skip timestamps.
+ *Michael Duchemin*
Please check [6-0-stable](https://github.com/rails/rails/blob/6-0-stable/activerecord/CHANGELOG.md) for previous changes.
diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb
index a43ebdf60d..45341765c1 100644
--- a/activerecord/lib/active_record/attribute_methods/dirty.rb
+++ b/activerecord/lib/active_record/attribute_methods/dirty.rb
@@ -177,6 +177,11 @@ module ActiveRecord
affected_rows = super
+ if @_skip_dirty_tracking ||= false
+ clear_attribute_changes(@_touch_attr_names)
+ return affected_rows
+ end
+
changes = {}
@attributes.keys.each do |attr_name|
next if @_touch_attr_names.include?(attr_name)
@@ -193,7 +198,7 @@ module ActiveRecord
affected_rows
ensure
- @_touch_attr_names = nil
+ @_touch_attr_names, @_skip_dirty_tracking = nil, nil
end
def _update_record(attribute_names = attribute_names_for_partial_writes)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
index ef19538447..044272ea51 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
@@ -205,8 +205,6 @@ module ActiveRecord
# In order to get around this problem, #transaction will emulate the effect
# of nested transactions, by using savepoints:
# https://dev.mysql.com/doc/refman/5.7/en/savepoint.html
- # Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8'
- # supports savepoints.
#
# It is safe to call this method if a database transaction is already open,
# i.e. if #transaction is called within another #transaction block. In case
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/savepoints.rb b/activerecord/lib/active_record/connection_adapters/abstract/savepoints.rb
index 52a796b926..d6dbef3fc8 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/savepoints.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/savepoints.rb
@@ -8,15 +8,15 @@ module ActiveRecord
end
def create_savepoint(name = current_savepoint_name)
- execute("SAVEPOINT #{name}")
+ execute("SAVEPOINT #{name}", "TRANSACTION")
end
def exec_rollback_to_savepoint(name = current_savepoint_name)
- execute("ROLLBACK TO SAVEPOINT #{name}")
+ execute("ROLLBACK TO SAVEPOINT #{name}", "TRANSACTION")
end
def release_savepoint(name = current_savepoint_name)
- execute("RELEASE SAVEPOINT #{name}")
+ execute("RELEASE SAVEPOINT #{name}", "TRANSACTION")
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index 2b64e96450..f97842b3f5 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -735,7 +735,7 @@ module ActiveRecord
#
# CREATE UNIQUE INDEX index_accounts_on_branch_id_and_party_id ON accounts(branch_id, party_id) WHERE active
#
- # Note: Partial indexes are only supported for PostgreSQL and SQLite 3.8.0+.
+ # Note: Partial indexes are only supported for PostgreSQL and SQLite.
#
# ====== Creating an index with a specific method
#
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index 282b2b1838..d239ecff89 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -204,7 +204,7 @@ module ActiveRecord
end
def begin_db_transaction
- execute "BEGIN"
+ execute("BEGIN", "TRANSACTION")
end
def begin_isolated_db_transaction(isolation)
@@ -213,11 +213,11 @@ module ActiveRecord
end
def commit_db_transaction #:nodoc:
- execute "COMMIT"
+ execute("COMMIT", "TRANSACTION")
end
def exec_rollback_db_transaction #:nodoc:
- execute "ROLLBACK"
+ execute("ROLLBACK", "TRANSACTION")
end
def empty_insert_statement_value(primary_key = nil)
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb
index d872bd662f..45ec79ca78 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb
@@ -145,7 +145,7 @@ module ActiveRecord
# Begins a transaction.
def begin_db_transaction
- execute "BEGIN"
+ execute("BEGIN", "TRANSACTION")
end
def begin_isolated_db_transaction(isolation)
@@ -155,12 +155,12 @@ module ActiveRecord
# Commits a transaction.
def commit_db_transaction
- execute "COMMIT"
+ execute("COMMIT", "TRANSACTION")
end
# Aborts a transaction.
def exec_rollback_db_transaction
- execute "ROLLBACK"
+ execute("ROLLBACK", "TRANSACTION")
end
private
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb
index 46ce1a15b5..73b80e8c15 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb
@@ -68,15 +68,15 @@ module ActiveRecord
alias :exec_update :exec_delete
def begin_db_transaction #:nodoc:
- log("begin transaction", nil) { @connection.transaction }
+ log("begin transaction", "TRANSACTION") { @connection.transaction }
end
def commit_db_transaction #:nodoc:
- log("commit transaction", nil) { @connection.commit }
+ log("commit transaction", "TRANSACTION") { @connection.commit }
end
def exec_rollback_db_transaction #:nodoc:
- log("rollback transaction", nil) { @connection.rollback }
+ log("rollback transaction", "TRANSACTION") { @connection.rollback }
end
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index f5f5827d04..41b35d9fc6 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -48,8 +48,8 @@ module ActiveRecord
end
module ConnectionAdapters #:nodoc:
- # The SQLite3 adapter works SQLite 3.6.16 or newer
- # with the sqlite3-ruby drivers (available as gem from https://rubygems.org/gems/sqlite3).
+ # The SQLite3 adapter works with the sqlite3-ruby drivers
+ # (available as gem from https://rubygems.org/gems/sqlite3).
#
# Options:
#
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index add95f6a0a..ea8f44752b 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -468,7 +468,19 @@ module ActiveRecord
end
end
- def update_counters(counters) # :nodoc:
+ # Updates the counters of the records in the current relation.
+ #
+ # === Parameters
+ #
+ # * +counter+ - A Hash containing the names of the fields to update as keys and the amount to update as values.
+ # * <tt>:touch</tt> option - Touch the timestamp columns when updating.
+ # * If attributes names are passed, they are updated along with update_at/on attributes.
+ #
+ # === Examples
+ #
+ # # For Posts by a given author increment the comment_count by 1.
+ # Post.where(author_id: author.id).update_counters(comment_count: 1)
+ def update_counters(counters)
touch = counters.delete(:touch)
updates = {}
diff --git a/activerecord/lib/active_record/touch_later.rb b/activerecord/lib/active_record/touch_later.rb
index 6872b7844e..bc63c8d987 100644
--- a/activerecord/lib/active_record/touch_later.rb
+++ b/activerecord/lib/active_record/touch_later.rb
@@ -44,6 +44,7 @@ module ActiveRecord
def touch_deferred_attributes
if has_defer_touch_attrs? && persisted?
+ @_skip_dirty_tracking = true
touch(*@_defer_touch_attrs, time: @_touch_time)
@_defer_touch_attrs, @_touch_time = nil, nil
end
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index 148bc0550c..cbb970ac98 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -164,12 +164,12 @@ module ActiveRecord
# end
# end
#
- # only "Kotori" is created. This works on MySQL and PostgreSQL. SQLite3 version >= '3.6.8' also supports it.
+ # only "Kotori" is created.
#
# Most databases don't support true nested transactions. At the time of
# writing, the only database that we're aware of that supports true nested
# transactions, is MS-SQL. Because of this, Active Record emulates nested
- # transactions by using savepoints on MySQL and PostgreSQL. See
+ # transactions by using savepoints. See
# https://dev.mysql.com/doc/refman/5.7/en/savepoint.html
# for more information about savepoints.
#
diff --git a/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb b/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb
index cb2c74f1ca..0620a515bd 100644
--- a/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb
+++ b/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb
@@ -7,6 +7,7 @@ module ActiveRecord
class MigrationGenerator < Base # :nodoc:
argument :attributes, type: :array, default: [], banner: "field[:type][:index] field[:type][:index]"
+ class_option :timestamps, type: :boolean
class_option :primary_key_type, type: :string, desc: "The type for primary key"
class_option :database, type: :string, aliases: %i(--db), desc: "The database for your migration. By default, the current environment's primary database is used."
diff --git a/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb b/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb
index ba477c63f4..96cfabf58f 100644
--- a/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb
@@ -13,7 +13,7 @@ class PostgreSQLReferentialIntegrityTest < ActiveRecord::PostgreSQLTestCase
end
module MissingSuperuserPrivileges
- def execute(sql)
+ def execute(sql, name = nil)
if IS_REFERENTIAL_INTEGRITY_SQL.call(sql)
super "BROKEN;" rescue nil # put transaction in broken state
raise ActiveRecord::StatementInvalid, "PG::InsufficientPrivilege"
@@ -24,7 +24,7 @@ class PostgreSQLReferentialIntegrityTest < ActiveRecord::PostgreSQLTestCase
end
module ProgrammerMistake
- def execute(sql)
+ def execute(sql, name = nil)
if IS_REFERENTIAL_INTEGRITY_SQL.call(sql)
raise ArgumentError, "something is not right."
else
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 32285f269a..9869657961 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -2711,18 +2711,22 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
bulb = Bulb.create!
tyre = Tyre.create!
- car = Car.create! do |c|
+ car = Car.create!(name: "honda") do |c|
c.bulbs << bulb
c.tyres << tyre
end
+ assert_equal [nil, "honda"], car.saved_change_to_name
+
assert_equal 1, car.bulbs.count
assert_equal 1, car.tyres.count
end
test "associations replace in memory when records have the same id" do
bulb = Bulb.create!
- car = Car.create!(bulbs: [bulb])
+ car = Car.create!(name: "honda", bulbs: [bulb])
+
+ assert_equal [nil, "honda"], car.saved_change_to_name
new_bulb = Bulb.find(bulb.id)
new_bulb.name = "foo"
@@ -2733,7 +2737,9 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
test "in memory replacement executes no queries" do
bulb = Bulb.create!
- car = Car.create!(bulbs: [bulb])
+ car = Car.create!(name: "honda", bulbs: [bulb])
+
+ assert_equal [nil, "honda"], car.saved_change_to_name
new_bulb = Bulb.find(bulb.id)
@@ -2765,7 +2771,9 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
test "in memory replacements sets inverse instance" do
bulb = Bulb.create!
- car = Car.create!(bulbs: [bulb])
+ car = Car.create!(name: "honda", bulbs: [bulb])
+
+ assert_equal [nil, "honda"], car.saved_change_to_name
new_bulb = Bulb.find(bulb.id)
car.bulbs = [new_bulb]
@@ -2785,7 +2793,9 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
test "in memory replacement maintains order" do
first_bulb = Bulb.create!
second_bulb = Bulb.create!
- car = Car.create!(bulbs: [first_bulb, second_bulb])
+ car = Car.create!(name: "honda", bulbs: [first_bulb, second_bulb])
+
+ assert_equal [nil, "honda"], car.saved_change_to_name
same_bulb = Bulb.find(first_bulb.id)
car.bulbs = [second_bulb, same_bulb]
diff --git a/activerecord/test/cases/test_case.rb b/activerecord/test/cases/test_case.rb
index 78dc0a6d9f..81f7226718 100644
--- a/activerecord/test/cases/test_case.rb
+++ b/activerecord/test/cases/test_case.rb
@@ -107,20 +107,12 @@ module ActiveRecord
clear_log
- self.ignored_sql = [/^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/]
-
- attr_reader :ignore
-
- def initialize(ignore = Regexp.union(self.class.ignored_sql))
- @ignore = ignore
- end
-
def call(name, start, finish, message_id, values)
return if values[:cached]
sql = values[:sql]
self.class.log_all << sql
- self.class.log << sql unless values[:name] == "SCHEMA" || ignore.match?(sql)
+ self.class.log << sql unless ["SCHEMA", "TRANSACTION"].include? values[:name]
end
end