activerecord 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG +4928 -3
- data/README +45 -46
- data/RUNNING_UNIT_TESTS +8 -11
- data/Rakefile +247 -0
- data/install.rb +8 -38
- data/lib/active_record/aggregations.rb +64 -49
- data/lib/active_record/associations/association_collection.rb +217 -47
- data/lib/active_record/associations/association_proxy.rb +159 -0
- data/lib/active_record/associations/belongs_to_association.rb +56 -0
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +155 -37
- data/lib/active_record/associations/has_many_association.rb +145 -75
- data/lib/active_record/associations/has_many_through_association.rb +283 -0
- data/lib/active_record/associations/has_one_association.rb +96 -0
- data/lib/active_record/associations.rb +1537 -304
- data/lib/active_record/attribute_methods.rb +328 -0
- data/lib/active_record/base.rb +2001 -588
- data/lib/active_record/calculations.rb +269 -0
- data/lib/active_record/callbacks.rb +169 -165
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +308 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +171 -0
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +87 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +69 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +472 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +306 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +125 -279
- data/lib/active_record/connection_adapters/mysql_adapter.rb +442 -77
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +805 -135
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -0
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +353 -69
- data/lib/active_record/fixtures.rb +946 -100
- data/lib/active_record/locking/optimistic.rb +144 -0
- data/lib/active_record/locking/pessimistic.rb +77 -0
- data/lib/active_record/migration.rb +417 -0
- data/lib/active_record/observer.rb +142 -32
- data/lib/active_record/query_cache.rb +23 -0
- data/lib/active_record/reflection.rb +163 -70
- data/lib/active_record/schema.rb +58 -0
- data/lib/active_record/schema_dumper.rb +171 -0
- data/lib/active_record/serialization.rb +98 -0
- data/lib/active_record/serializers/json_serializer.rb +71 -0
- data/lib/active_record/serializers/xml_serializer.rb +315 -0
- data/lib/active_record/timestamp.rb +41 -0
- data/lib/active_record/transactions.rb +87 -57
- data/lib/active_record/validations.rb +909 -122
- data/lib/active_record/vendor/db2.rb +362 -0
- data/lib/active_record/vendor/mysql.rb +126 -29
- data/lib/active_record/version.rb +9 -0
- data/lib/active_record.rb +35 -7
- data/lib/activerecord.rb +1 -0
- data/test/aaa_create_tables_test.rb +72 -0
- data/test/abstract_unit.rb +73 -5
- data/test/active_schema_test_mysql.rb +43 -0
- data/test/adapter_test.rb +105 -0
- data/test/adapter_test_sqlserver.rb +95 -0
- data/test/aggregations_test.rb +110 -16
- data/test/all.sh +2 -2
- data/test/ar_schema_test.rb +33 -0
- data/test/association_inheritance_reload.rb +14 -0
- data/test/associations/ar_joins_test.rb +0 -0
- data/test/associations/callbacks_test.rb +147 -0
- data/test/associations/cascaded_eager_loading_test.rb +110 -0
- data/test/associations/eager_singularization_test.rb +145 -0
- data/test/associations/eager_test.rb +442 -0
- data/test/associations/extension_test.rb +47 -0
- data/test/associations/inner_join_association_test.rb +88 -0
- data/test/associations/join_model_test.rb +553 -0
- data/test/associations_test.rb +1930 -267
- data/test/attribute_methods_test.rb +146 -0
- data/test/base_test.rb +1316 -84
- data/test/binary_test.rb +32 -0
- data/test/calculations_test.rb +251 -0
- data/test/callbacks_test.rb +400 -0
- data/test/class_inheritable_attributes_test.rb +3 -4
- data/test/column_alias_test.rb +17 -0
- data/test/connection_test_firebird.rb +8 -0
- data/test/connection_test_mysql.rb +30 -0
- data/test/connections/native_db2/connection.rb +25 -0
- data/test/connections/native_firebird/connection.rb +26 -0
- data/test/connections/native_frontbase/connection.rb +27 -0
- data/test/connections/native_mysql/connection.rb +21 -18
- data/test/connections/native_openbase/connection.rb +21 -0
- data/test/connections/native_oracle/connection.rb +27 -0
- data/test/connections/native_postgresql/connection.rb +17 -18
- data/test/connections/native_sqlite/connection.rb +17 -16
- data/test/connections/native_sqlite3/connection.rb +25 -0
- data/test/connections/native_sqlite3/in_memory_connection.rb +18 -0
- data/test/connections/native_sybase/connection.rb +23 -0
- data/test/copy_table_test_sqlite.rb +69 -0
- data/test/datatype_test_postgresql.rb +203 -0
- data/test/date_time_test.rb +37 -0
- data/test/default_test_firebird.rb +16 -0
- data/test/defaults_test.rb +67 -0
- data/test/deprecated_finder_test.rb +30 -0
- data/test/finder_test.rb +607 -32
- data/test/fixtures/accounts.yml +28 -0
- data/test/fixtures/all/developers.yml +0 -0
- data/test/fixtures/all/people.csv +0 -0
- data/test/fixtures/all/tasks.yml +0 -0
- data/test/fixtures/author.rb +107 -0
- data/test/fixtures/author_favorites.yml +4 -0
- data/test/fixtures/authors.yml +7 -0
- data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +1 -0
- data/test/fixtures/bad_fixtures/attr_with_spaces +1 -0
- data/test/fixtures/bad_fixtures/blank_line +3 -0
- data/test/fixtures/bad_fixtures/duplicate_attributes +3 -0
- data/test/fixtures/bad_fixtures/missing_value +1 -0
- data/test/fixtures/binaries.yml +132 -0
- data/test/fixtures/binary.rb +2 -0
- data/test/fixtures/book.rb +4 -0
- data/test/fixtures/books.yml +7 -0
- data/test/fixtures/categories/special_categories.yml +9 -0
- data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
- data/test/fixtures/categories.yml +14 -0
- data/test/fixtures/categories_ordered.yml +7 -0
- data/test/fixtures/categories_posts.yml +23 -0
- data/test/fixtures/categorization.rb +5 -0
- data/test/fixtures/categorizations.yml +17 -0
- data/test/fixtures/category.rb +26 -0
- data/test/fixtures/citation.rb +6 -0
- data/test/fixtures/comment.rb +23 -0
- data/test/fixtures/comments.yml +59 -0
- data/test/fixtures/companies.yml +55 -0
- data/test/fixtures/company.rb +81 -4
- data/test/fixtures/company_in_module.rb +32 -6
- data/test/fixtures/computer.rb +4 -0
- data/test/fixtures/computers.yml +4 -0
- data/test/fixtures/contact.rb +16 -0
- data/test/fixtures/courses.yml +7 -0
- data/test/fixtures/customer.rb +28 -3
- data/test/fixtures/customers.yml +17 -0
- data/test/fixtures/db_definitions/db2.drop.sql +33 -0
- data/test/fixtures/db_definitions/db2.sql +235 -0
- data/test/fixtures/db_definitions/db22.drop.sql +2 -0
- data/test/fixtures/db_definitions/db22.sql +5 -0
- data/test/fixtures/db_definitions/firebird.drop.sql +65 -0
- data/test/fixtures/db_definitions/firebird.sql +310 -0
- data/test/fixtures/db_definitions/firebird2.drop.sql +2 -0
- data/test/fixtures/db_definitions/firebird2.sql +6 -0
- data/test/fixtures/db_definitions/frontbase.drop.sql +33 -0
- data/test/fixtures/db_definitions/frontbase.sql +273 -0
- data/test/fixtures/db_definitions/frontbase2.drop.sql +1 -0
- data/test/fixtures/db_definitions/frontbase2.sql +4 -0
- data/test/fixtures/db_definitions/openbase.drop.sql +2 -0
- data/test/fixtures/db_definitions/openbase.sql +318 -0
- data/test/fixtures/db_definitions/openbase2.drop.sql +2 -0
- data/test/fixtures/db_definitions/openbase2.sql +7 -0
- data/test/fixtures/db_definitions/oracle.drop.sql +67 -0
- data/test/fixtures/db_definitions/oracle.sql +330 -0
- data/test/fixtures/db_definitions/oracle2.drop.sql +2 -0
- data/test/fixtures/db_definitions/oracle2.sql +6 -0
- data/test/fixtures/db_definitions/postgresql.drop.sql +44 -0
- data/test/fixtures/db_definitions/postgresql.sql +217 -38
- data/test/fixtures/db_definitions/postgresql2.drop.sql +2 -0
- data/test/fixtures/db_definitions/postgresql2.sql +2 -2
- data/test/fixtures/db_definitions/schema.rb +354 -0
- data/test/fixtures/db_definitions/schema2.rb +11 -0
- data/test/fixtures/db_definitions/sqlite.drop.sql +33 -0
- data/test/fixtures/db_definitions/sqlite.sql +139 -5
- data/test/fixtures/db_definitions/sqlite2.drop.sql +2 -0
- data/test/fixtures/db_definitions/sqlite2.sql +1 -0
- data/test/fixtures/db_definitions/sybase.drop.sql +35 -0
- data/test/fixtures/db_definitions/sybase.sql +222 -0
- data/test/fixtures/db_definitions/sybase2.drop.sql +4 -0
- data/test/fixtures/db_definitions/sybase2.sql +5 -0
- data/test/fixtures/developer.rb +70 -6
- data/test/fixtures/developers.yml +21 -0
- data/test/fixtures/developers_projects/david_action_controller +2 -1
- data/test/fixtures/developers_projects/david_active_record +2 -1
- data/test/fixtures/developers_projects.yml +17 -0
- data/test/fixtures/edge.rb +5 -0
- data/test/fixtures/edges.yml +6 -0
- data/test/fixtures/entrants.yml +14 -0
- data/test/fixtures/example.log +1 -0
- data/test/fixtures/fk_test_has_fk.yml +3 -0
- data/test/fixtures/fk_test_has_pk.yml +2 -0
- data/test/fixtures/flowers.jpg +0 -0
- data/test/fixtures/funny_jokes.yml +10 -0
- data/test/fixtures/item.rb +7 -0
- data/test/fixtures/items.yml +4 -0
- data/test/fixtures/joke.rb +3 -0
- data/test/fixtures/keyboard.rb +3 -0
- data/test/fixtures/legacy_thing.rb +3 -0
- data/test/fixtures/legacy_things.yml +3 -0
- data/test/fixtures/matey.rb +4 -0
- data/test/fixtures/mateys.yml +4 -0
- data/test/fixtures/migrations/1_people_have_last_names.rb +9 -0
- data/test/fixtures/migrations/2_we_need_reminders.rb +12 -0
- data/test/fixtures/migrations/3_innocent_jointable.rb +12 -0
- data/test/fixtures/migrations_with_decimal/1_give_me_big_numbers.rb +15 -0
- data/test/fixtures/migrations_with_duplicate/1_people_have_last_names.rb +9 -0
- data/test/fixtures/migrations_with_duplicate/2_we_need_reminders.rb +12 -0
- data/test/fixtures/migrations_with_duplicate/3_foo.rb +7 -0
- data/test/fixtures/migrations_with_duplicate/3_innocent_jointable.rb +12 -0
- data/test/fixtures/migrations_with_missing_versions/1000_people_have_middle_names.rb +9 -0
- data/test/fixtures/migrations_with_missing_versions/1_people_have_last_names.rb +9 -0
- data/test/fixtures/migrations_with_missing_versions/3_we_need_reminders.rb +12 -0
- data/test/fixtures/migrations_with_missing_versions/4_innocent_jointable.rb +12 -0
- data/test/fixtures/minimalistic.rb +2 -0
- data/test/fixtures/minimalistics.yml +2 -0
- data/test/fixtures/mixed_case_monkey.rb +3 -0
- data/test/fixtures/mixed_case_monkeys.yml +6 -0
- data/test/fixtures/mixins.yml +29 -0
- data/test/fixtures/movies.yml +7 -0
- data/test/fixtures/naked/csv/accounts.csv +1 -0
- data/test/fixtures/naked/yml/accounts.yml +1 -0
- data/test/fixtures/naked/yml/companies.yml +1 -0
- data/test/fixtures/naked/yml/courses.yml +1 -0
- data/test/fixtures/order.rb +4 -0
- data/test/fixtures/parrot.rb +13 -0
- data/test/fixtures/parrots.yml +27 -0
- data/test/fixtures/parrots_pirates.yml +7 -0
- data/test/fixtures/people.yml +3 -0
- data/test/fixtures/person.rb +4 -0
- data/test/fixtures/pirate.rb +5 -0
- data/test/fixtures/pirates.yml +9 -0
- data/test/fixtures/post.rb +59 -0
- data/test/fixtures/posts.yml +48 -0
- data/test/fixtures/project.rb +27 -2
- data/test/fixtures/projects.yml +7 -0
- data/test/fixtures/reader.rb +4 -0
- data/test/fixtures/readers.yml +4 -0
- data/test/fixtures/reply.rb +18 -2
- data/test/fixtures/reserved_words/distinct.yml +5 -0
- data/test/fixtures/reserved_words/distincts_selects.yml +11 -0
- data/test/fixtures/reserved_words/group.yml +14 -0
- data/test/fixtures/reserved_words/select.yml +8 -0
- data/test/fixtures/reserved_words/values.yml +7 -0
- data/test/fixtures/ship.rb +3 -0
- data/test/fixtures/ships.yml +5 -0
- data/test/fixtures/subject.rb +4 -0
- data/test/fixtures/subscriber.rb +4 -3
- data/test/fixtures/tag.rb +7 -0
- data/test/fixtures/tagging.rb +10 -0
- data/test/fixtures/taggings.yml +25 -0
- data/test/fixtures/tags.yml +7 -0
- data/test/fixtures/task.rb +3 -0
- data/test/fixtures/tasks.yml +7 -0
- data/test/fixtures/topic.rb +20 -3
- data/test/fixtures/topics.yml +22 -0
- data/test/fixtures/treasure.rb +4 -0
- data/test/fixtures/treasures.yml +10 -0
- data/test/fixtures/vertex.rb +9 -0
- data/test/fixtures/vertices.yml +4 -0
- data/test/fixtures_test.rb +574 -8
- data/test/inheritance_test.rb +113 -27
- data/test/json_serialization_test.rb +180 -0
- data/test/lifecycle_test.rb +56 -29
- data/test/locking_test.rb +273 -0
- data/test/method_scoping_test.rb +416 -0
- data/test/migration_test.rb +933 -0
- data/test/migration_test_firebird.rb +124 -0
- data/test/mixin_test.rb +95 -0
- data/test/modules_test.rb +23 -10
- data/test/multiple_db_test.rb +17 -3
- data/test/pk_test.rb +59 -15
- data/test/query_cache_test.rb +104 -0
- data/test/readonly_test.rb +107 -0
- data/test/reflection_test.rb +124 -27
- data/test/reserved_word_test_mysql.rb +177 -0
- data/test/schema_authorization_test_postgresql.rb +75 -0
- data/test/schema_dumper_test.rb +131 -0
- data/test/schema_test_postgresql.rb +64 -0
- data/test/serialization_test.rb +47 -0
- data/test/synonym_test_oracle.rb +17 -0
- data/test/table_name_test_sqlserver.rb +23 -0
- data/test/threaded_connections_test.rb +48 -0
- data/test/transactions_test.rb +227 -29
- data/test/unconnected_test.rb +14 -6
- data/test/validations_test.rb +1293 -32
- data/test/xml_serialization_test.rb +202 -0
- metadata +347 -143
- data/dev-utils/eval_debugger.rb +0 -9
- data/examples/associations.rb +0 -87
- data/examples/shared_setup.rb +0 -15
- data/examples/validation.rb +0 -88
- data/lib/active_record/deprecated_associations.rb +0 -70
- data/lib/active_record/support/class_attribute_accessors.rb +0 -43
- data/lib/active_record/support/class_inheritable_attributes.rb +0 -37
- data/lib/active_record/support/clean_logger.rb +0 -10
- data/lib/active_record/support/inflector.rb +0 -70
- data/lib/active_record/vendor/simple.rb +0 -702
- data/lib/active_record/wrappers/yaml_wrapper.rb +0 -15
- data/lib/active_record/wrappings.rb +0 -59
- data/rakefile +0 -122
- data/test/deprecated_associations_test.rb +0 -336
- data/test/fixtures/accounts/signals37 +0 -3
- data/test/fixtures/accounts/unknown +0 -2
- data/test/fixtures/companies/first_client +0 -6
- data/test/fixtures/companies/first_firm +0 -4
- data/test/fixtures/companies/second_client +0 -6
- data/test/fixtures/courses/java +0 -2
- data/test/fixtures/courses/ruby +0 -2
- data/test/fixtures/customers/david +0 -6
- data/test/fixtures/db_definitions/mysql.sql +0 -96
- data/test/fixtures/db_definitions/mysql2.sql +0 -4
- data/test/fixtures/developers/david +0 -2
- data/test/fixtures/developers/jamis +0 -2
- data/test/fixtures/entrants/first +0 -3
- data/test/fixtures/entrants/second +0 -3
- data/test/fixtures/entrants/third +0 -3
- data/test/fixtures/fixture_database.sqlite +0 -0
- data/test/fixtures/fixture_database_2.sqlite +0 -0
- data/test/fixtures/movies/first +0 -2
- data/test/fixtures/movies/second +0 -2
- data/test/fixtures/projects/action_controller +0 -2
- data/test/fixtures/projects/active_record +0 -2
- data/test/fixtures/topics/first +0 -9
- data/test/fixtures/topics/second +0 -8
- data/test/inflector_test.rb +0 -104
- data/test/thread_safety_test.rb +0 -33
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
require 'fixtures/topic'
|
3
|
+
require 'fixtures/subject'
|
4
|
+
|
5
|
+
# confirm that synonyms work just like tables; in this case
|
6
|
+
# the "subjects" table in Oracle (defined in oci.sql) is just
|
7
|
+
# a synonym to the "topics" table
|
8
|
+
|
9
|
+
class TestOracleSynonym < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def test_oracle_synonym
|
12
|
+
topic = Topic.new
|
13
|
+
subject = Subject.new
|
14
|
+
assert_equal(topic.attributes, subject.attributes)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
require "#{File.dirname(__FILE__)}/../lib/active_record/schema"
|
3
|
+
|
4
|
+
if ActiveRecord::Base.connection.supports_migrations?
|
5
|
+
class Order < ActiveRecord::Base
|
6
|
+
self.table_name = '[order]'
|
7
|
+
end
|
8
|
+
|
9
|
+
class TableNameTest < Test::Unit::TestCase
|
10
|
+
self.use_transactional_fixtures = false
|
11
|
+
|
12
|
+
# Ensures Model.columns works when using SQLServer escape characters.
|
13
|
+
# Enables legacy schemas using SQL reserved words as table names.
|
14
|
+
# Should work with table names with spaces as well ('table name').
|
15
|
+
def test_escaped_table_name
|
16
|
+
assert_nothing_raised do
|
17
|
+
ActiveRecord::Base.connection.select_all 'SELECT * FROM [order]'
|
18
|
+
end
|
19
|
+
assert_equal '[order]', Order.table_name
|
20
|
+
assert_equal 5, Order.columns.length
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
require 'fixtures/topic'
|
3
|
+
require 'fixtures/reply'
|
4
|
+
|
5
|
+
unless %w(FrontBase).include? ActiveRecord::Base.connection.adapter_name
|
6
|
+
class ThreadedConnectionsTest < Test::Unit::TestCase
|
7
|
+
self.use_transactional_fixtures = false
|
8
|
+
|
9
|
+
fixtures :topics
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@connection = ActiveRecord::Base.remove_connection
|
13
|
+
@connections = []
|
14
|
+
@allow_concurrency = ActiveRecord::Base.allow_concurrency
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
# clear the connection cache
|
19
|
+
ActiveRecord::Base.send(:clear_all_cached_connections!)
|
20
|
+
# set allow_concurrency to saved value
|
21
|
+
ActiveRecord::Base.allow_concurrency = @allow_concurrency
|
22
|
+
# reestablish old connection
|
23
|
+
ActiveRecord::Base.establish_connection(@connection)
|
24
|
+
end
|
25
|
+
|
26
|
+
def gather_connections(use_threaded_connections)
|
27
|
+
ActiveRecord::Base.allow_concurrency = use_threaded_connections
|
28
|
+
ActiveRecord::Base.establish_connection(@connection)
|
29
|
+
|
30
|
+
5.times do
|
31
|
+
Thread.new do
|
32
|
+
Topic.find :first
|
33
|
+
@connections << ActiveRecord::Base.active_connections.values.first
|
34
|
+
end.join
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_threaded_connections
|
39
|
+
gather_connections(true)
|
40
|
+
assert_equal @connections.uniq.length, 5
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_unthreaded_connections
|
44
|
+
gather_connections(false)
|
45
|
+
assert_equal @connections.uniq.length, 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/test/transactions_test.rb
CHANGED
@@ -1,25 +1,71 @@
|
|
1
1
|
require 'abstract_unit'
|
2
2
|
require 'fixtures/topic'
|
3
|
-
|
3
|
+
require 'fixtures/reply'
|
4
|
+
require 'fixtures/developer'
|
4
5
|
|
5
6
|
class TransactionTest < Test::Unit::TestCase
|
7
|
+
self.use_transactional_fixtures = false
|
8
|
+
fixtures :topics, :developers
|
9
|
+
|
6
10
|
def setup
|
7
|
-
@
|
8
|
-
@first, @second = Topic.find(1, 2)
|
11
|
+
@first, @second = Topic.find(1, 2).sort_by { |t| t.id }
|
9
12
|
end
|
10
13
|
|
11
|
-
def
|
14
|
+
def test_successful
|
12
15
|
Topic.transaction do
|
13
|
-
@first.approved =
|
14
|
-
@second.approved =
|
16
|
+
@first.approved = true
|
17
|
+
@second.approved = false
|
18
|
+
@first.save
|
19
|
+
@second.save
|
20
|
+
end
|
21
|
+
|
22
|
+
assert Topic.find(1).approved?, "First should have been approved"
|
23
|
+
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
24
|
+
end
|
25
|
+
|
26
|
+
def transaction_with_return
|
27
|
+
Topic.transaction do
|
28
|
+
@first.approved = true
|
29
|
+
@second.approved = false
|
30
|
+
@first.save
|
31
|
+
@second.save
|
32
|
+
return
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_successful_with_return
|
37
|
+
class << Topic.connection
|
38
|
+
alias :real_commit_db_transaction :commit_db_transaction
|
39
|
+
def commit_db_transaction
|
40
|
+
$committed = true
|
41
|
+
real_commit_db_transaction
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
$committed = false
|
46
|
+
transaction_with_return
|
47
|
+
assert $committed
|
48
|
+
|
49
|
+
assert Topic.find(1).approved?, "First should have been approved"
|
50
|
+
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
51
|
+
ensure
|
52
|
+
class << Topic.connection
|
53
|
+
alias :commit_db_transaction :real_commit_db_transaction rescue nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_successful_with_instance_method
|
58
|
+
@first.transaction do
|
59
|
+
@first.approved = true
|
60
|
+
@second.approved = false
|
15
61
|
@first.save
|
16
62
|
@second.save
|
17
63
|
end
|
18
|
-
|
64
|
+
|
19
65
|
assert Topic.find(1).approved?, "First should have been approved"
|
20
66
|
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
21
67
|
end
|
22
|
-
|
68
|
+
|
23
69
|
def test_failing_on_exception
|
24
70
|
begin
|
25
71
|
Topic.transaction do
|
@@ -35,28 +81,12 @@ class TransactionTest < Test::Unit::TestCase
|
|
35
81
|
|
36
82
|
assert @first.approved?, "First should still be changed in the objects"
|
37
83
|
assert !@second.approved?, "Second should still be changed in the objects"
|
38
|
-
|
84
|
+
|
39
85
|
assert !Topic.find(1).approved?, "First shouldn't have been approved"
|
40
86
|
assert Topic.find(2).approved?, "Second should still be approved"
|
41
87
|
end
|
42
|
-
|
43
|
-
|
44
|
-
begin
|
45
|
-
Topic.transaction(@first, @second) do
|
46
|
-
@first.approved = true
|
47
|
-
@second.approved = false
|
48
|
-
@first.save
|
49
|
-
@second.save
|
50
|
-
raise "Bad things!"
|
51
|
-
end
|
52
|
-
rescue
|
53
|
-
# caught it
|
54
|
-
end
|
55
|
-
|
56
|
-
assert !@first.approved?, "First shouldn't have been approved"
|
57
|
-
assert @second.approved?, "Second should still be approved"
|
58
|
-
end
|
59
|
-
|
88
|
+
|
89
|
+
|
60
90
|
def test_callback_rollback_in_save
|
61
91
|
add_exception_raising_after_save_callback_to_topic
|
62
92
|
|
@@ -72,12 +102,180 @@ class TransactionTest < Test::Unit::TestCase
|
|
72
102
|
end
|
73
103
|
end
|
74
104
|
|
105
|
+
def test_callback_rollback_in_create
|
106
|
+
new_topic = Topic.new(
|
107
|
+
:title => "A new topic",
|
108
|
+
:author_name => "Ben",
|
109
|
+
:author_email_address => "ben@example.com",
|
110
|
+
:written_on => "2003-07-16t15:28:11.2233+01:00",
|
111
|
+
:last_read => "2004-04-15",
|
112
|
+
:bonus_time => "2005-01-30t15:28:00.00+01:00",
|
113
|
+
:content => "Have a nice day",
|
114
|
+
:approved => false)
|
115
|
+
new_record_snapshot = new_topic.new_record?
|
116
|
+
id_present = new_topic.has_attribute?(Topic.primary_key)
|
117
|
+
id_snapshot = new_topic.id
|
118
|
+
|
119
|
+
# Make sure the second save gets the after_create callback called.
|
120
|
+
2.times do
|
121
|
+
begin
|
122
|
+
add_exception_raising_after_create_callback_to_topic
|
123
|
+
new_topic.approved = true
|
124
|
+
new_topic.save
|
125
|
+
flunk
|
126
|
+
rescue => e
|
127
|
+
assert_equal "Make the transaction rollback", e.message
|
128
|
+
assert_equal new_record_snapshot, new_topic.new_record?, "The topic should have its old new_record value"
|
129
|
+
assert_equal id_snapshot, new_topic.id, "The topic should have its old id"
|
130
|
+
assert_equal id_present, new_topic.has_attribute?(Topic.primary_key)
|
131
|
+
ensure
|
132
|
+
remove_exception_raising_after_create_callback_to_topic
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_nested_explicit_transactions
|
138
|
+
Topic.transaction do
|
139
|
+
Topic.transaction do
|
140
|
+
@first.approved = true
|
141
|
+
@second.approved = false
|
142
|
+
@first.save
|
143
|
+
@second.save
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
assert Topic.find(1).approved?, "First should have been approved"
|
148
|
+
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_manually_rolling_back_a_transaction
|
152
|
+
Topic.transaction do
|
153
|
+
@first.approved = true
|
154
|
+
@second.approved = false
|
155
|
+
@first.save
|
156
|
+
@second.save
|
157
|
+
|
158
|
+
raise ActiveRecord::Rollback
|
159
|
+
end
|
160
|
+
|
161
|
+
assert @first.approved?, "First should still be changed in the objects"
|
162
|
+
assert !@second.approved?, "Second should still be changed in the objects"
|
163
|
+
|
164
|
+
assert !Topic.find(1).approved?, "First shouldn't have been approved"
|
165
|
+
assert Topic.find(2).approved?, "Second should still be approved"
|
166
|
+
end
|
167
|
+
|
168
|
+
uses_mocha 'mocking connection.commit_db_transaction' do
|
169
|
+
def test_rollback_when_commit_raises
|
170
|
+
Topic.connection.expects(:begin_db_transaction)
|
171
|
+
Topic.connection.expects(:commit_db_transaction).raises('OH NOES')
|
172
|
+
Topic.connection.expects(:rollback_db_transaction)
|
173
|
+
|
174
|
+
assert_raise RuntimeError do
|
175
|
+
Topic.transaction do
|
176
|
+
# do nothing
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
75
182
|
private
|
76
183
|
def add_exception_raising_after_save_callback_to_topic
|
77
184
|
Topic.class_eval { def after_save() raise "Make the transaction rollback" end }
|
78
185
|
end
|
79
|
-
|
186
|
+
|
80
187
|
def remove_exception_raising_after_save_callback_to_topic
|
81
188
|
Topic.class_eval { remove_method :after_save }
|
82
189
|
end
|
83
|
-
|
190
|
+
|
191
|
+
def add_exception_raising_after_create_callback_to_topic
|
192
|
+
Topic.class_eval { def after_create() raise "Make the transaction rollback" end }
|
193
|
+
end
|
194
|
+
|
195
|
+
def remove_exception_raising_after_create_callback_to_topic
|
196
|
+
Topic.class_eval { remove_method :after_create }
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
if current_adapter?(:PostgreSQLAdapter)
|
201
|
+
class ConcurrentTransactionTest < TransactionTest
|
202
|
+
def setup
|
203
|
+
@allow_concurrency = ActiveRecord::Base.allow_concurrency
|
204
|
+
ActiveRecord::Base.allow_concurrency = true
|
205
|
+
super
|
206
|
+
end
|
207
|
+
|
208
|
+
def teardown
|
209
|
+
super
|
210
|
+
ActiveRecord::Base.allow_concurrency = @allow_concurrency
|
211
|
+
end
|
212
|
+
|
213
|
+
# This will cause transactions to overlap and fail unless they are performed on
|
214
|
+
# separate database connections.
|
215
|
+
def test_transaction_per_thread
|
216
|
+
assert_nothing_raised do
|
217
|
+
threads = (1..3).map do
|
218
|
+
Thread.new do
|
219
|
+
Topic.transaction do
|
220
|
+
topic = Topic.find(1)
|
221
|
+
topic.approved = !topic.approved?
|
222
|
+
topic.save!
|
223
|
+
topic.approved = !topic.approved?
|
224
|
+
topic.save!
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
threads.each { |t| t.join }
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# Test for dirty reads among simultaneous transactions.
|
234
|
+
def test_transaction_isolation__read_committed
|
235
|
+
# Should be invariant.
|
236
|
+
original_salary = Developer.find(1).salary
|
237
|
+
temporary_salary = 200000
|
238
|
+
|
239
|
+
assert_nothing_raised do
|
240
|
+
threads = (1..3).map do
|
241
|
+
Thread.new do
|
242
|
+
Developer.transaction do
|
243
|
+
# Expect original salary.
|
244
|
+
dev = Developer.find(1)
|
245
|
+
assert_equal original_salary, dev.salary
|
246
|
+
|
247
|
+
dev.salary = temporary_salary
|
248
|
+
dev.save!
|
249
|
+
|
250
|
+
# Expect temporary salary.
|
251
|
+
dev = Developer.find(1)
|
252
|
+
assert_equal temporary_salary, dev.salary
|
253
|
+
|
254
|
+
dev.salary = original_salary
|
255
|
+
dev.save!
|
256
|
+
|
257
|
+
# Expect original salary.
|
258
|
+
dev = Developer.find(1)
|
259
|
+
assert_equal original_salary, dev.salary
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Keep our eyes peeled.
|
265
|
+
threads << Thread.new do
|
266
|
+
10.times do
|
267
|
+
sleep 0.05
|
268
|
+
Developer.transaction do
|
269
|
+
# Always expect original salary.
|
270
|
+
assert_equal original_salary, Developer.find(1).salary
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
threads.each { |t| t.join }
|
276
|
+
end
|
277
|
+
|
278
|
+
assert_equal original_salary, Developer.find(1).salary
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
data/test/unconnected_test.rb
CHANGED
@@ -3,22 +3,30 @@ require 'abstract_unit'
|
|
3
3
|
class TestRecord < ActiveRecord::Base
|
4
4
|
end
|
5
5
|
|
6
|
-
class
|
6
|
+
class TestUnconnectedAdapter < Test::Unit::TestCase
|
7
|
+
self.use_transactional_fixtures = false
|
7
8
|
|
8
9
|
def setup
|
9
|
-
@
|
10
|
+
@underlying = ActiveRecord::Base.connection
|
11
|
+
@specification = ActiveRecord::Base.remove_connection
|
10
12
|
end
|
11
13
|
|
12
14
|
def teardown
|
13
|
-
|
15
|
+
@underlying = nil
|
16
|
+
ActiveRecord::Base.establish_connection(@specification)
|
14
17
|
end
|
15
18
|
|
16
|
-
def
|
19
|
+
def test_connection_no_longer_established
|
17
20
|
assert_raise(ActiveRecord::ConnectionNotEstablished) do
|
18
|
-
TestRecord.find(1)
|
21
|
+
TestRecord.find(1)
|
19
22
|
end
|
23
|
+
|
20
24
|
assert_raise(ActiveRecord::ConnectionNotEstablished) do
|
21
|
-
TestRecord.new.save
|
25
|
+
TestRecord.new.save
|
22
26
|
end
|
23
27
|
end
|
28
|
+
|
29
|
+
def test_underlying_adapter_no_longer_active
|
30
|
+
assert !@underlying.active?, "Removed adapter should no longer be active"
|
31
|
+
end
|
24
32
|
end
|