aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorXavier Noria <fxn@hashref.com>2010-06-08 21:23:29 +0200
committerXavier Noria <fxn@hashref.com>2010-06-08 21:23:29 +0200
commit751f79a03351f1f0d21436b2b947352b97ded093 (patch)
tree9dd053597389241398c9173ab7f565697bef055f /activerecord
parente7e6ee3e7b075f5447697a6038cb46d65f9b137a (diff)
parentab2877cbe89e266ee986fc12e603abd93ac017ad (diff)
downloadrails-751f79a03351f1f0d21436b2b947352b97ded093.tar.gz
rails-751f79a03351f1f0d21436b2b947352b97ded093.tar.bz2
rails-751f79a03351f1f0d21436b2b947352b97ded093.zip
Merge remote branch 'rails/master'
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG4
-rw-r--r--activerecord/activerecord.gemspec2
-rwxr-xr-xactiverecord/lib/active_record/associations.rb7
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb56
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb4
-rw-r--r--activerecord/lib/active_record/relation.rb7
-rw-r--r--activerecord/lib/active_record/transactions.rb118
-rw-r--r--activerecord/lib/active_record/version.rb2
-rw-r--r--activerecord/test/cases/adapter_test.rb17
-rw-r--r--activerecord/test/cases/associations/belongs_to_associations_test.rb4
-rw-r--r--activerecord/test/cases/associations/cascaded_eager_loading_test.rb10
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb2
-rwxr-xr-xactiverecord/test/cases/base_test.rb7
-rw-r--r--activerecord/test/cases/date_time_test.rb4
-rw-r--r--activerecord/test/cases/json_serialization_test.rb19
-rw-r--r--activerecord/test/cases/log_subscriber_test.rb4
-rw-r--r--activerecord/test/cases/migration_test.rb33
-rw-r--r--activerecord/test/cases/relations_test.rb2
-rw-r--r--activerecord/test/cases/transaction_callbacks_test.rb240
-rw-r--r--activerecord/test/cases/transactions_test.rb33
-rw-r--r--activerecord/test/connections/native_oracle/connection.rb2
-rw-r--r--activerecord/test/models/topic.rb6
22 files changed, 84 insertions, 499 deletions
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index d8f68d7c28..348248e849 100644
--- a/activerecord/CHANGELOG
+++ b/activerecord/CHANGELOG
@@ -1,4 +1,4 @@
-*Rails 3.0.0 [beta 4/release candidate] (unreleased)*
+*Rails 3.0.0 [beta 4] (June 8th, 2010)*
* Add index length support for MySQL. #1852 [Emili Parreno, Pratik Naik]
@@ -12,8 +12,6 @@
* find_or_create_by_attr(value, ...) works when attr is protected. #4457 [Santiago Pastorino, Marc-André Lafortune]
-* New callbacks: after_commit and after_rollback. Do expensive operations like image thumbnailing after_commit instead of after_save. #2991 [Brian Durand]
-
* Serialized attributes are not converted to YAML if they are any of the formats that can be serialized to XML (like Hash, Array and Strings). [José Valim]
* Destroy uses optimistic locking. If lock_version on the record you're destroying doesn't match lock_version in the database, a StaleObjectError is raised. #1966 [Curtis Hawthorne]
diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec
index 44c8fb83e1..5aea992801 100644
--- a/activerecord/activerecord.gemspec
+++ b/activerecord/activerecord.gemspec
@@ -23,6 +23,6 @@ Gem::Specification.new do |s|
s.add_dependency('activesupport', version)
s.add_dependency('activemodel', version)
- s.add_dependency('arel', '~> 0.3.3')
+ s.add_dependency('arel', '~> 0.4.0')
s.add_dependency('tzinfo', '~> 0.3.16')
end
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 284ae6695b..c1e16d08cb 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1756,7 +1756,8 @@ module ActiveRecord
end
def count_aliases_from_table_joins(name)
- quoted_name = join_base.active_record.connection.quote_table_name(name.downcase)
+ # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase
+ quoted_name = join_base.active_record.connection.quote_table_name(name.downcase).downcase
join_sql = join_base.table_joins.to_s.downcase
join_sql.blank? ? 0 :
# Table names
@@ -1902,7 +1903,7 @@ module ActiveRecord
end
def ==(other)
- other.is_a?(JoinBase) &&
+ other.class == self.class &&
other.active_record == active_record &&
other.table_joins == table_joins
end
@@ -1973,7 +1974,7 @@ module ActiveRecord
end
def ==(other)
- other.is_a?(JoinAssociation) &&
+ other.class == self.class &&
other.reflection == reflection &&
other.parent == parent
end
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 b9fb452eee..0c87e052c4 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
@@ -122,8 +122,6 @@ module ActiveRecord
requires_new = options[:requires_new] || !last_transaction_joinable
transaction_open = false
- @_current_transaction_records ||= []
-
begin
if block_given?
if requires_new || open_transactions == 0
@@ -134,7 +132,6 @@ module ActiveRecord
end
increment_open_transactions
transaction_open = true
- @_current_transaction_records.push([])
end
yield
end
@@ -144,10 +141,8 @@ module ActiveRecord
decrement_open_transactions
if open_transactions == 0
rollback_db_transaction
- rollback_transaction_records(true)
else
rollback_to_savepoint
- rollback_transaction_records(false)
end
end
raise unless database_transaction_rollback.is_a?(ActiveRecord::Rollback)
@@ -162,35 +157,20 @@ module ActiveRecord
begin
if open_transactions == 0
commit_db_transaction
- commit_transaction_records
else
release_savepoint
- save_point_records = @_current_transaction_records.pop
- unless save_point_records.blank?
- @_current_transaction_records.push([]) if @_current_transaction_records.empty?
- @_current_transaction_records.last.concat(save_point_records)
- end
end
rescue Exception => database_transaction_rollback
if open_transactions == 0
rollback_db_transaction
- rollback_transaction_records(true)
else
rollback_to_savepoint
- rollback_transaction_records(false)
end
raise
end
end
end
- # Register a record with the current transaction so that its after_commit and after_rollback callbacks
- # can be called.
- def add_transaction_record(record)
- last_batch = @_current_transaction_records.last
- last_batch << record if last_batch
- end
-
# Begins the transaction (and turns off auto-committing).
def begin_db_transaction() end
@@ -288,42 +268,6 @@ module ActiveRecord
limit.to_i
end
end
-
- # Send a rollback message to all records after they have been rolled back. If rollback
- # is false, only rollback records since the last save point.
- def rollback_transaction_records(rollback) #:nodoc
- if rollback
- records = @_current_transaction_records.flatten
- @_current_transaction_records.clear
- else
- records = @_current_transaction_records.pop
- end
-
- unless records.blank?
- records.uniq.each do |record|
- begin
- record.rolledback!(rollback)
- rescue Exception => e
- record.logger.error(e) if record.respond_to?(:logger)
- end
- end
- end
- end
-
- # Send a commit message to all records after they have been committed.
- def commit_transaction_records #:nodoc
- records = @_current_transaction_records.flatten
- @_current_transaction_records.clear
- unless records.blank?
- records.uniq.each do |record|
- begin
- record.committed!
- rescue Exception => e
- record.logger.error(e) if record.respond_to?(:logger)
- end
- end
- end
- end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
index e8a45bb3c6..deb62e3802 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
@@ -34,6 +34,10 @@ module ActiveRecord
end
def binary_to_string(value)
+ if value.respond_to?(:force_encoding) && value.encoding != Encoding::ASCII_8BIT
+ value = value.force_encoding(Encoding::ASCII_8BIT)
+ end
+
value.gsub(/%00|%25/n) do |b|
case b
when "%00" then "\0"
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 4e62187449..99c914d7fc 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -356,13 +356,16 @@ module ActiveRecord
end
def references_eager_loaded_tables?
- joined_tables = (tables_in_string(arel.joins(arel)) + [table.name, table.table_alias]).compact.uniq
+ # always convert table names to downcase as in Oracle quoted table names are in uppercase
+ joined_tables = (tables_in_string(arel.joins(arel)) + [table.name, table.table_alias]).compact.map(&:downcase).uniq
(tables_in_string(to_sql) - joined_tables).any?
end
def tables_in_string(string)
return [] if string.blank?
- string.scan(/([a-zA-Z_][\.\w]+).?\./).flatten.uniq
+ # always convert table names to downcase as in Oracle quoted table names are in uppercase
+ # ignore raw_sql_ that is used by Oracle adapter as alias for limit/offset subqueries
+ string.scan(/([a-zA-Z_][\.\w]+).?\./).flatten.map(&:downcase).uniq - ['raw_sql_']
end
end
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index 5a8e2ce880..3f2c1911e7 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -8,11 +8,6 @@ module ActiveRecord
class TransactionError < ActiveRecordError # :nodoc:
end
- included do
- define_model_callbacks :commit, :commit_on_update, :commit_on_create, :commit_on_destroy, :only => :after
- define_model_callbacks :rollback, :rollback_on_update, :rollback_on_create, :rollback_on_destroy
- end
-
# Transactions are protective blocks where SQL statements are only permanent
# if they can all succeed as one atomic action. The classic example is a
# transfer between two accounts where you can only have a deposit if the
@@ -163,21 +158,6 @@ module ActiveRecord
# http://dev.mysql.com/doc/refman/5.0/en/savepoints.html
# for more information about savepoints.
#
- # === Callbacks
- #
- # There are two types of callbacks associated with committing and rolling back transactions:
- # +after_commit+ and +after_rollback+.
- #
- # +after_commit+ callbacks are called on every record saved or destroyed within a
- # transaction immediately after the transaction is committed. +after_rollback+ callbacks
- # are called on every record saved or destroyed within a transaction immediately after the
- # transaction or savepoint is rolled back.
- #
- # These callbacks are useful for interacting with other systems since you will be guaranteed
- # that the callback is only executed when the database is in a permanent state. For example,
- # +after_commit+ is a good spot to put in a hook to clearing a cache since clearing it from
- # within a transaction could trigger the cache to be regenerated before the database is updated.
- #
# === Caveats
#
# If you're on MySQL, then do not use DDL operations in nested transactions
@@ -225,50 +205,19 @@ module ActiveRecord
# Reset id and @new_record if the transaction rolls back.
def rollback_active_record_state!
- remember_transaction_record_state
+ id_present = has_attribute?(self.class.primary_key)
+ previous_id = id
+ previous_new_record = new_record?
yield
rescue Exception
- restore_transaction_record_state
- raise
- ensure
- clear_transaction_record_state
- end
-
- # Call the after_commit callbacks
- def committed! #:nodoc:
- if transaction_record_state(:new_record)
- _run_commit_on_create_callbacks
- elsif transaction_record_state(:destroyed)
- _run_commit_on_destroy_callbacks
+ @new_record = previous_new_record
+ if id_present
+ self.id = previous_id
else
- _run_commit_on_update_callbacks
- end
- _run_commit_callbacks
- ensure
- clear_transaction_record_state
- end
-
- # Call the after rollback callbacks. The restore_state argument indicates if the record
- # state should be rolled back to the beginning or just to the last savepoint.
- def rolledback!(force_restore_state = false) #:nodoc:
- if transaction_record_state(:new_record)
- _run_rollback_on_create_callbacks
- elsif transaction_record_state(:destroyed)
- _run_rollback_on_destroy_callbacks
- else
- _run_rollback_on_update_callbacks
- end
- _run_rollback_callbacks
- ensure
- restore_transaction_record_state(force_restore_state)
- end
-
- # Add the record to the current transaction so that the :after_rollback and :after_commit callbacks
- # can be called.
- def add_to_transaction
- if self.class.connection.add_transaction_record(self)
- remember_transaction_record_state
+ @attributes.delete(self.class.primary_key)
+ @attributes_cache.delete(self.class.primary_key)
end
+ raise
end
# Executes +method+ within a transaction and captures its return value as a
@@ -280,59 +229,10 @@ module ActiveRecord
def with_transaction_returning_status
status = nil
self.class.transaction do
- add_to_transaction
status = yield
raise ActiveRecord::Rollback unless status
end
status
end
-
- protected
-
- # Save the new record state and id of a record so it can be restored later if a transaction fails.
- def remember_transaction_record_state #:nodoc
- @_start_transaction_state ||= {}
- unless @_start_transaction_state.include?(:new_record)
- @_start_transaction_state[:id] = id if has_attribute?(self.class.primary_key)
- @_start_transaction_state[:new_record] = @new_record
- end
- unless @_start_transaction_state.include?(:destroyed)
- @_start_transaction_state[:destroyed] = @new_record
- end
- @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
- end
-
- # Clear the new record state and id of a record.
- def clear_transaction_record_state #:nodoc
- if defined?(@_start_transaction_state)
- @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
- remove_instance_variable(:@_start_transaction_state) if @_start_transaction_state[:level] < 1
- end
- end
-
- # Restore the new record state and id of a record that was previously saved by a call to save_record_state.
- def restore_transaction_record_state(force = false) #:nodoc
- if defined?(@_start_transaction_state)
- @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
- if @_start_transaction_state[:level] < 1
- restore_state = remove_instance_variable(:@_start_transaction_state)
- if restore_state
- @new_record = restore_state[:new_record]
- @destroyed = restore_state[:destroyed]
- if restore_state[:id]
- self.id = restore_state[:id]
- else
- @attributes.delete(self.class.primary_key)
- @attributes_cache.delete(self.class.primary_key)
- end
- end
- end
- end
- end
-
- # Determine if a record was created or destroyed in a transaction. State should be one of :new_record or :destroyed.
- def transaction_record_state(state) #:nodoc
- @_start_transaction_state[state] if defined?(@_start_transaction_state)
- end
end
end
diff --git a/activerecord/lib/active_record/version.rb b/activerecord/lib/active_record/version.rb
index bf6b995a37..d18fed0131 100644
--- a/activerecord/lib/active_record/version.rb
+++ b/activerecord/lib/active_record/version.rb
@@ -3,7 +3,7 @@ module ActiveRecord
MAJOR = 3
MINOR = 0
TINY = 0
- BUILD = "beta3"
+ BUILD = "beta4"
STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
end
diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb
index 9b28766405..fc08c2178a 100644
--- a/activerecord/test/cases/adapter_test.rb
+++ b/activerecord/test/cases/adapter_test.rb
@@ -145,22 +145,13 @@ class AdapterTest < ActiveRecord::TestCase
def test_add_limit_offset_should_sanitize_sql_injection_for_limit_without_comas
sql_inject = "1 select * from schema"
- assert_equal " LIMIT 1", @connection.add_limit_offset!("", :limit => sql_inject)
- if current_adapter?(:MysqlAdapter)
- assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit => sql_inject, :offset => 7)
- else
- assert_equal " LIMIT 1 OFFSET 7", @connection.add_limit_offset!("", :limit => sql_inject, :offset => 7)
- end
+ assert_no_match(/schema/, @connection.add_limit_offset!("", :limit=>sql_inject))
+ assert_no_match(/schema/, @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7))
end
def test_add_limit_offset_should_sanitize_sql_injection_for_limit_with_comas
sql_inject = "1, 7 procedure help()"
- if current_adapter?(:MysqlAdapter)
- assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit => sql_inject)
- assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit => '1 ; DROP TABLE USERS', :offset => 7)
- else
- assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit => sql_inject)
- assert_equal " LIMIT 1,7 OFFSET 7", @connection.add_limit_offset!("", :limit => sql_inject, :offset => 7)
- end
+ assert_no_match(/procedure/, @connection.add_limit_offset!("", :limit=>sql_inject))
+ assert_no_match(/procedure/, @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7))
end
end
diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb
index 9258c987ef..fb1e6e7e70 100644
--- a/activerecord/test/cases/associations/belongs_to_associations_test.rb
+++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -37,6 +37,10 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
if current_adapter?(:MysqlAdapter)
assert_no_match(/`firm_with_primary_keys_companies`\.`id`/, sql)
assert_match(/`firm_with_primary_keys_companies`\.`name`/, sql)
+ elsif current_adapter?(:OracleAdapter)
+ # on Oracle aliases are truncated to 30 characters and are quoted in uppercase
+ assert_no_match(/"firm_with_primary_keys_compani"\."id"/i, sql)
+ assert_match(/"firm_with_primary_keys_compani"\."name"/i, sql)
else
assert_no_match(/"firm_with_primary_keys_companies"\."id"/, sql)
assert_match(/"firm_with_primary_keys_companies"\."name"/, sql)
diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb
index fe558f9d3b..7a4a33d177 100644
--- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb
+++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb
@@ -7,9 +7,10 @@ require 'models/categorization'
require 'models/company'
require 'models/topic'
require 'models/reply'
+require 'models/person'
class CascadedEagerLoadingTest < ActiveRecord::TestCase
- fixtures :authors, :mixins, :companies, :posts, :topics, :accounts, :comments, :categorizations
+ fixtures :authors, :mixins, :companies, :posts, :topics, :accounts, :comments, :categorizations, :people
def test_eager_association_loading_with_cascaded_two_levels
authors = Author.find(:all, :include=>{:posts=>:comments}, :order=>"authors.id")
@@ -38,6 +39,13 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase
assert_equal 9, assert_no_queries { authors[0].comments.size }
end
+ def test_eager_association_loading_grafts_stashed_associations_to_correct_parent
+ assert_nothing_raised do
+ Person.eager_load(:primary_contact => :primary_contact).where('primary_contacts_people_2.first_name = ?', 'Susan').all
+ end
+ assert_equal people(:michael), Person.eager_load(:primary_contact => :primary_contact).where('primary_contacts_people_2.first_name = ?', 'Susan').first
+ end
+
def test_eager_association_loading_with_cascaded_two_levels_with_two_has_many_associations
authors = Author.find(:all, :include=>{:posts=>[:comments, :categorizations]}, :order=>"authors.id")
assert_equal 2, authors.size
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 8e5bc56008..45c7498013 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -511,7 +511,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_deleting_updates_counter_cache
- topic = Topic.first
+ topic = Topic.first(:order => "id ASC")
assert_equal topic.replies.to_a.size, topic.replies_count
topic.replies.delete(topic.replies.first)
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 1d883f7ea8..36c572b5e7 100755
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -430,14 +430,14 @@ class BasicsTest < ActiveRecord::TestCase
end
def test_preserving_date_objects
- if current_adapter?(:SybaseAdapter, :OracleAdapter)
+ if current_adapter?(:SybaseAdapter)
# Sybase ctlib does not (yet?) support the date type; use datetime instead.
- # Oracle treats all dates/times as Time.
assert_kind_of(
Time, Topic.find(1).last_read,
"The last_read attribute should be of the Time class"
)
else
+ # Oracle enhanced adapter allows to define Date attributes in model class (see topic.rb)
assert_kind_of(
Date, Topic.find(1).last_read,
"The last_read attribute should be of the Date class"
@@ -2125,10 +2125,11 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal "integer", xml.elements["//parent-id"].attributes['type']
assert_equal "true", xml.elements["//parent-id"].attributes['nil']
- if current_adapter?(:SybaseAdapter, :OracleAdapter)
+ if current_adapter?(:SybaseAdapter)
assert_equal last_read_in_current_timezone, xml.elements["//last-read"].text
assert_equal "datetime" , xml.elements["//last-read"].attributes['type']
else
+ # Oracle enhanced adapter allows to define Date attributes in model class (see topic.rb)
assert_equal "2004-04-15", xml.elements["//last-read"].text
assert_equal "date" , xml.elements["//last-read"].attributes['type']
end
diff --git a/activerecord/test/cases/date_time_test.rb b/activerecord/test/cases/date_time_test.rb
index 36e1caa0b6..a8b4b7a096 100644
--- a/activerecord/test/cases/date_time_test.rb
+++ b/activerecord/test/cases/date_time_test.rb
@@ -5,7 +5,9 @@ require 'models/task'
class DateTimeTest < ActiveRecord::TestCase
def test_saves_both_date_and_time
time_values = [1807, 2, 10, 15, 30, 45]
- now = DateTime.civil(*time_values)
+ # create DateTime value with local time zone offset
+ local_offset = Rational(Time.local_time(*time_values).utc_offset, 86400)
+ now = DateTime.civil(*(time_values + [local_offset]))
task = Task.new
task.starting = now
diff --git a/activerecord/test/cases/json_serialization_test.rb b/activerecord/test/cases/json_serialization_test.rb
index a3145d2c04..c275557da8 100644
--- a/activerecord/test/cases/json_serialization_test.rb
+++ b/activerecord/test/cases/json_serialization_test.rb
@@ -8,7 +8,7 @@ require 'models/comment'
class JsonSerializationTest < ActiveRecord::TestCase
class NamespacedContact < Contact
- column :name, :string
+ column :name, :string
end
def setup
@@ -23,16 +23,12 @@ class JsonSerializationTest < ActiveRecord::TestCase
end
def test_should_demodulize_root_in_json
- NamespacedContact.include_root_in_json = true
@contact = NamespacedContact.new :name => 'whatever'
json = @contact.to_json
assert_match %r{^\{"namespaced_contact":\{}, json
- ensure
- NamespacedContact.include_root_in_json = false
end
def test_should_include_root_in_json
- Contact.include_root_in_json = true
json = @contact.to_json
assert_match %r{^\{"contact":\{}, json
@@ -41,8 +37,6 @@ class JsonSerializationTest < ActiveRecord::TestCase
assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
assert_match %r{"awesome":true}, json
assert_match %r{"preferences":\{"shows":"anime"\}}, json
- ensure
- Contact.include_root_in_json = false
end
def test_should_encode_all_encodable_attributes
@@ -170,15 +164,19 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase
end
def test_should_allow_only_option_for_list_of_authors
+ ActiveRecord::Base.include_root_in_json = false
authors = [@david, @mary]
-
assert_equal %([{"name":"David"},{"name":"Mary"}]), ActiveSupport::JSON.encode(authors, :only => :name)
+ ensure
+ ActiveRecord::Base.include_root_in_json = true
end
def test_should_allow_except_option_for_list_of_authors
+ ActiveRecord::Base.include_root_in_json = false
authors = [@david, @mary]
-
assert_equal %([{"id":1},{"id":2}]), ActiveSupport::JSON.encode(authors, :except => [:name, :author_address_id, :author_address_extra_id])
+ ensure
+ ActiveRecord::Base.include_root_in_json = true
end
def test_should_allow_includes_for_list_of_authors
@@ -201,7 +199,6 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase
1 => @david,
2 => @mary
}
-
- assert_equal %({"1":{"name":"David"}}), ActiveSupport::JSON.encode(authors_hash, :only => [1, :name])
+ assert_equal %({"1":{"author":{"name":"David"}}}), ActiveSupport::JSON.encode(authors_hash, :only => [1, :name])
end
end
diff --git a/activerecord/test/cases/log_subscriber_test.rb b/activerecord/test/cases/log_subscriber_test.rb
index 6ba84fa57b..1f544b4211 100644
--- a/activerecord/test/cases/log_subscriber_test.rb
+++ b/activerecord/test/cases/log_subscriber_test.rb
@@ -27,7 +27,7 @@ class LogSubscriberTest < ActiveSupport::TestCase
wait
assert_equal 1, @logger.logged(:debug).size
assert_match(/Developer Load/, @logger.logged(:debug).last)
- assert_match(/SELECT .*?FROM .?developers.?/, @logger.logged(:debug).last)
+ assert_match(/SELECT .*?FROM .?developers.?/i, @logger.logged(:debug).last)
end
def test_cached_queries
@@ -38,6 +38,6 @@ class LogSubscriberTest < ActiveSupport::TestCase
wait
assert_equal 2, @logger.logged(:debug).size
assert_match(/CACHE/, @logger.logged(:debug).last)
- assert_match(/SELECT .*?FROM .?developers.?/, @logger.logged(:debug).last)
+ assert_match(/SELECT .*?FROM .?developers.?/i, @logger.logged(:debug).last)
end
end
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index b5fa258f7b..1edec66c25 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -30,13 +30,14 @@ if ActiveRecord::Base.connection.supports_migrations?
conn = ActiveRecord::Base.connection
conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
- ActiveRecord::Base.table_name_prefix = 'foo_'
- ActiveRecord::Base.table_name_suffix = '_bar'
+ # Use shorter prefix and suffix as in Oracle database identifier cannot be larger than 30 characters
+ ActiveRecord::Base.table_name_prefix = 'p_'
+ ActiveRecord::Base.table_name_suffix = '_s'
conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
conn.initialize_schema_migrations_table
- assert_equal "foo_unique_schema_migrations_bar", conn.indexes(ActiveRecord::Migrator.schema_migrations_table_name)[0][:name]
+ assert_equal "p_unique_schema_migrations_s", conn.indexes(ActiveRecord::Migrator.schema_migrations_table_name)[0][:name]
ensure
ActiveRecord::Base.table_name_prefix = ""
ActiveRecord::Base.table_name_suffix = ""
@@ -83,13 +84,17 @@ if ActiveRecord::Base.connection.supports_migrations?
# Orcl nds shrt indx nms. Sybs 2.
# OpenBase does not have named indexes. You must specify a single column name
- unless current_adapter?(:OracleAdapter, :SybaseAdapter, :OpenBaseAdapter)
+ unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
assert_nothing_raised { Person.connection.remove_index("people", :column => ["last_name", "first_name"]) }
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
- assert_nothing_raised { Person.connection.remove_index("people", :name => "index_people_on_last_name_and_first_name") }
- assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
- assert_nothing_raised { Person.connection.remove_index("people", "last_name_and_first_name") }
+ # Oracle adapter cannot have specified index name larger than 30 characters
+ # Oracle adapter is shortening index name when just column list is given
+ unless current_adapter?(:OracleAdapter)
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
+ assert_nothing_raised { Person.connection.remove_index("people", :name => "index_people_on_last_name_and_first_name") }
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
+ assert_nothing_raised { Person.connection.remove_index("people", "last_name_and_first_name") }
+ end
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => 10) }
@@ -736,13 +741,7 @@ if ActiveRecord::Base.connection.supports_migrations?
table.column :hat_size, :integer
table.column :hat_style, :string, :limit => 100
end
- # Oracle index names should be 30 or less characters
- if current_adapter?(:OracleAdapter)
- ActiveRecord::Base.connection.add_index "hats", ["hat_style", "hat_size"], :unique => true,
- :name => 'index_hats_on_hat_style_size'
- else
- ActiveRecord::Base.connection.add_index "hats", ["hat_style", "hat_size"], :unique => true
- end
+ ActiveRecord::Base.connection.add_index "hats", ["hat_style", "hat_size"], :unique => true
assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") }
ensure
@@ -1375,8 +1374,8 @@ if ActiveRecord::Base.connection.supports_migrations?
return unless current_adapter? :OracleAdapter
# table name is 29 chars, the standard sequence name will
- # be 33 chars and fail
- assert_raise(ActiveRecord::StatementInvalid) do
+ # be 33 chars and should be shortened
+ assert_nothing_raised do
begin
Person.connection.create_table :table_with_name_thats_just_ok do |t|
t.column :foo, :string, :null => false
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index 4097c5119e..43519db976 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -114,7 +114,7 @@ class RelationTest < ActiveRecord::TestCase
def test_select_with_block
even_ids = Developer.scoped.select {|d| d.id % 2 == 0 }.map(&:id)
- assert_equal [2, 4, 6, 8, 10], even_ids
+ assert_equal [2, 4, 6, 8, 10], even_ids.sort
end
def test_finding_with_hash_conditions_on_joined_table
diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb
deleted file mode 100644
index ebc16653cb..0000000000
--- a/activerecord/test/cases/transaction_callbacks_test.rb
+++ /dev/null
@@ -1,240 +0,0 @@
-require "cases/helper"
-require 'models/topic'
-require 'models/reply'
-
-class TransactionCallbacksTest < ActiveRecord::TestCase
- self.use_transactional_fixtures = false
- fixtures :topics
-
- class TopicWithCallbacks < ActiveRecord::Base
- set_table_name :topics
-
- after_commit{|record| record.send(:do_after_commit, nil)}
- after_commit(:on => :create){|record| record.send(:do_after_commit, :create)}
- after_commit(:on => :update){|record| record.send(:do_after_commit, :update)}
- after_commit(:on => :destroy){|record| record.send(:do_after_commit, :destroy)}
- after_rollback{|record| record.send(:do_after_rollback, nil)}
- after_rollback(:on => :create){|record| record.send(:do_after_rollback, :create)}
- after_rollback(:on => :update){|record| record.send(:do_after_rollback, :update)}
- after_rollback(:on => :destroy){|record| record.send(:do_after_rollback, :destroy)}
-
- def history
- @history ||= []
- end
-
- def after_commit_block(on = nil, &block)
- @after_commit ||= {}
- @after_commit[on] ||= []
- @after_commit[on] << block
- end
-
- def after_rollback_block(on = nil, &block)
- @after_rollback ||= {}
- @after_rollback[on] ||= []
- @after_rollback[on] << block
- end
-
- def do_after_commit(on)
- blocks = @after_commit[on] if defined?(@after_commit)
- blocks.each{|b| b.call(self)} if blocks
- end
-
- def do_after_rollback(on)
- blocks = @after_rollback[on] if defined?(@after_rollback)
- blocks.each{|b| b.call(self)} if blocks
- end
- end
-
- def setup
- @first, @second = TopicWithCallbacks.find(1, 3).sort_by { |t| t.id }
- end
-
- def test_call_after_commit_after_transaction_commits
- @first.after_commit_block{|r| r.history << :after_commit}
- @first.after_rollback_block{|r| r.history << :after_rollback}
-
- @first.save!
- assert_equal [:after_commit], @first.history
- end
-
- def test_only_call_after_commit_on_update_after_transaction_commits_for_existing_record
- @first.after_commit_block(:create){|r| r.history << :commit_on_create}
- @first.after_commit_block(:update){|r| r.history << :commit_on_update}
- @first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
- @first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
- @first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
- @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
-
- @first.save!
- assert_equal [:commit_on_update], @first.history
- end
-
- def test_only_call_after_commit_on_destroy_after_transaction_commits_for_destroyed_record
- @first.after_commit_block(:create){|r| r.history << :commit_on_create}
- @first.after_commit_block(:update){|r| r.history << :commit_on_update}
- @first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
- @first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
- @first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
- @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
-
- @first.destroy
- assert_equal [:commit_on_destroy], @first.history
- end
-
- def test_only_call_after_commit_on_create_after_transaction_commits_for_new_record
- @new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Date.today)
- @new_record.after_commit_block(:create){|r| r.history << :commit_on_create}
- @new_record.after_commit_block(:update){|r| r.history << :commit_on_update}
- @new_record.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
- @new_record.after_rollback_block(:create){|r| r.history << :rollback_on_create}
- @new_record.after_rollback_block(:update){|r| r.history << :rollback_on_update}
- @new_record.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
-
- @new_record.save!
- assert_equal [:commit_on_create], @new_record.history
- end
-
- def test_call_after_rollback_after_transaction_rollsback
- @first.after_commit_block{|r| r.history << :after_commit}
- @first.after_rollback_block{|r| r.history << :after_rollback}
-
- Topic.transaction do
- @first.save!
- raise ActiveRecord::Rollback
- end
-
- assert_equal [:after_rollback], @first.history
- end
-
- def test_only_call_after_rollback_on_update_after_transaction_rollsback_for_existing_record
- @first.after_commit_block(:create){|r| r.history << :commit_on_create}
- @first.after_commit_block(:update){|r| r.history << :commit_on_update}
- @first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
- @first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
- @first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
- @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
-
- Topic.transaction do
- @first.save!
- raise ActiveRecord::Rollback
- end
-
- assert_equal [:rollback_on_update], @first.history
- end
-
- def test_only_call_after_rollback_on_destroy_after_transaction_rollsback_for_destroyed_record
- @first.after_commit_block(:create){|r| r.history << :commit_on_create}
- @first.after_commit_block(:update){|r| r.history << :commit_on_update}
- @first.after_commit_block(:destroy){|r| r.history << :commit_on_update}
- @first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
- @first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
- @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
-
- Topic.transaction do
- @first.destroy
- raise ActiveRecord::Rollback
- end
-
- assert_equal [:rollback_on_destroy], @first.history
- end
-
- def test_only_call_after_rollback_on_create_after_transaction_rollsback_for_new_record
- @new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Date.today)
- @new_record.after_commit_block(:create){|r| r.history << :commit_on_create}
- @new_record.after_commit_block(:update){|r| r.history << :commit_on_update}
- @new_record.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
- @new_record.after_rollback_block(:create){|r| r.history << :rollback_on_create}
- @new_record.after_rollback_block(:update){|r| r.history << :rollback_on_update}
- @new_record.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
-
- Topic.transaction do
- @new_record.save!
- raise ActiveRecord::Rollback
- end
-
- assert_equal [:rollback_on_create], @new_record.history
- end
-
- def test_call_after_rollback_when_commit_fails
- @first.connection.class.send(:alias_method, :real_method_commit_db_transaction, :commit_db_transaction)
- begin
- @first.connection.class.class_eval do
- def commit_db_transaction; raise "boom!"; end
- end
-
- @first.after_commit_block{|r| r.history << :after_commit}
- @first.after_rollback_block{|r| r.history << :after_rollback}
-
- assert !@first.save rescue nil
- assert_equal [:after_rollback], @first.history
- ensure
- @first.connection.class.send(:remove_method, :commit_db_transaction)
- @first.connection.class.send(:alias_method, :commit_db_transaction, :real_method_commit_db_transaction)
- end
- end
-
- def test_only_call_after_rollback_on_records_rolled_back_to_a_savepoint
- def @first.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end
- def @first.commits(i=0); @commits ||= 0; @commits += i if i; end
- @first.after_rollback_block{|r| r.rollbacks(1)}
- @first.after_commit_block{|r| r.commits(1)}
-
- def @second.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end
- def @second.commits(i=0); @commits ||= 0; @commits += i if i; end
- @second.after_rollback_block{|r| r.rollbacks(1)}
- @second.after_commit_block{|r| r.commits(1)}
-
- Topic.transaction do
- @first.save!
- Topic.transaction(:requires_new => true) do
- @second.save!
- raise ActiveRecord::Rollback
- end
- end
-
- assert_equal 1, @first.commits
- assert_equal 0, @first.rollbacks
- assert_equal 0, @second.commits
- assert_equal 1, @second.rollbacks
- end
-
- def test_only_call_after_rollback_on_records_rolled_back_to_a_savepoint_when_release_savepoint_fails
- def @first.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end
- def @first.commits(i=0); @commits ||= 0; @commits += i if i; end
-
- @first.after_rollback_block{|r| r.rollbacks(1)}
- @first.after_commit_block{|r| r.commits(1)}
-
- Topic.transaction do
- @first.save
- Topic.transaction(:requires_new => true) do
- @first.save!
- raise ActiveRecord::Rollback
- end
- Topic.transaction(:requires_new => true) do
- @first.save!
- raise ActiveRecord::Rollback
- end
- end
-
- assert_equal 1, @first.commits
- assert_equal 2, @first.rollbacks
- end
-
- def test_after_transaction_callbacks_should_not_raise_errors
- def @first.last_after_transaction_error=(e); @last_transaction_error = e; end
- def @first.last_after_transaction_error; @last_transaction_error; end
- @first.after_commit_block{|r| r.last_after_transaction_error = :commit; raise "fail!";}
- @first.after_rollback_block{|r| r.last_after_transaction_error = :rollback; raise "fail!";}
-
- @first.save!
- assert_equal :commit, @first.last_after_transaction_error
-
- Topic.transaction do
- @first.save!
- raise ActiveRecord::Rollback
- end
-
- assert_equal :rollback, @first.last_after_transaction_error
- end
-end
diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb
index 958a4e4f94..00f3b527d7 100644
--- a/activerecord/test/cases/transactions_test.rb
+++ b/activerecord/test/cases/transactions_test.rb
@@ -320,33 +320,6 @@ class TransactionTest < ActiveRecord::TestCase
end
end
- def test_restore_active_record_state_for_all_records_in_a_transaction
- topic_1 = Topic.new(:title => 'test_1')
- topic_2 = Topic.new(:title => 'test_2')
- Topic.transaction do
- assert topic_1.save
- assert topic_2.save
- @first.save
- @second.destroy
- assert_equal false, topic_1.new_record?
- assert_not_nil topic_1.id
- assert_equal false, topic_2.new_record?
- assert_not_nil topic_2.id
- assert_equal false, @first.new_record?
- assert_not_nil @first.id
- assert_equal true, @second.destroyed?
- raise ActiveRecord::Rollback
- end
-
- assert_equal true, topic_1.new_record?
- assert_nil topic_1.id
- assert_equal true, topic_2.new_record?
- assert_nil topic_2.id
- assert_equal false, @first.new_record?
- assert_not_nil @first.id
- assert_equal false, @second.destroyed?
- end
-
if current_adapter?(:PostgreSQLAdapter) && defined?(PGconn::PQTRANS_IDLE)
def test_outside_transaction_works
assert Topic.connection.outside_transaction?
@@ -409,12 +382,6 @@ class TransactionTest < ActiveRecord::TestCase
end
private
- def define_callback_method(callback_method)
- define_method(callback_method) do
- self.history << [callback_method, :method]
- end
- end
-
def add_exception_raising_after_save_callback_to_topic
Topic.class_eval <<-eoruby, __FILE__, __LINE__ + 1
remove_method(:after_save_for_transaction)
diff --git a/activerecord/test/connections/native_oracle/connection.rb b/activerecord/test/connections/native_oracle/connection.rb
index c8183dc0fb..bb4040058f 100644
--- a/activerecord/test/connections/native_oracle/connection.rb
+++ b/activerecord/test/connections/native_oracle/connection.rb
@@ -53,7 +53,7 @@ Course.establish_connection 'arunit2'
# for assert_queries test helper
ActiveRecord::Base.connection.class.class_eval do
- IGNORED_SELECT_SQL = [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^\s*select .* from all_tab_columns/im]
+ IGNORED_SELECT_SQL = [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from ((all|user)_tab_columns|(all|user)_triggers|(all|user)_constraints)/im]
def select_with_query_record(sql, name = nil, return_column_names = false)
$queries_executed ||= []
diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb
index 91fc7c9416..617f01b47d 100644
--- a/activerecord/test/models/topic.rb
+++ b/activerecord/test/models/topic.rb
@@ -43,6 +43,12 @@ class Topic < ActiveRecord::Base
before_create :default_written_on
before_destroy :destroy_children
+ # Explicitly define as :date column so that returned Oracle DATE values would be typecasted to Date and not Time.
+ # Some tests depend on assumption that this attribute will have Date values.
+ if current_adapter?(:OracleEnhancedAdapter)
+ set_date_columns :last_read
+ end
+
def parent
Topic.find(parent_id)
end