activerecord 2.3.18 → 3.0.0.beta
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 +105 -34
- data/examples/performance.rb +3 -39
- data/examples/simple.rb +14 -0
- data/lib/active_record.rb +81 -47
- data/lib/active_record/aggregations.rb +1 -3
- data/lib/active_record/association_preload.rb +39 -54
- data/lib/active_record/associations.rb +262 -419
- data/lib/active_record/associations/association_collection.rb +85 -100
- data/lib/active_record/associations/association_proxy.rb +20 -18
- data/lib/active_record/associations/belongs_to_association.rb +8 -8
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +13 -35
- data/lib/active_record/associations/has_many_association.rb +11 -19
- data/lib/active_record/associations/has_many_through_association.rb +30 -183
- data/lib/active_record/associations/has_one_association.rb +10 -10
- data/lib/active_record/associations/has_one_through_association.rb +13 -11
- data/lib/active_record/associations/through_association_scope.rb +153 -0
- data/lib/active_record/attribute_methods.rb +17 -370
- data/lib/active_record/attribute_methods/before_type_cast.rb +33 -0
- data/lib/active_record/attribute_methods/dirty.rb +87 -0
- data/lib/active_record/attribute_methods/primary_key.rb +44 -0
- data/lib/active_record/attribute_methods/query.rb +37 -0
- data/lib/active_record/attribute_methods/read.rb +116 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +60 -0
- data/lib/active_record/attribute_methods/write.rb +37 -0
- data/lib/active_record/autosave_association.rb +20 -41
- data/lib/active_record/base.rb +357 -1180
- data/lib/active_record/batches.rb +10 -16
- data/lib/active_record/callbacks.rb +66 -126
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +17 -13
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +5 -25
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +4 -43
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +18 -72
- data/lib/active_record/connection_adapters/abstract_adapter.rb +16 -49
- data/lib/active_record/connection_adapters/mysql_adapter.rb +15 -27
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +84 -46
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +9 -3
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +34 -65
- data/lib/active_record/fixtures.rb +21 -25
- data/lib/active_record/locale/en.yml +9 -27
- data/lib/active_record/locking/optimistic.rb +16 -48
- data/lib/active_record/migration.rb +59 -46
- data/lib/active_record/named_scope.rb +85 -92
- data/lib/active_record/nested_attributes.rb +18 -24
- data/lib/active_record/observer.rb +18 -94
- data/lib/active_record/railtie.rb +83 -0
- data/lib/active_record/railties/controller_runtime.rb +38 -0
- data/lib/active_record/railties/databases.rake +477 -0
- data/lib/active_record/railties/subscriber.rb +27 -0
- data/lib/active_record/reflection.rb +2 -15
- data/lib/active_record/relation.rb +339 -0
- data/lib/active_record/relation/calculations.rb +259 -0
- data/lib/active_record/relation/finder_methods.rb +315 -0
- data/lib/active_record/relation/predicate_builder.rb +46 -0
- data/lib/active_record/relation/query_methods.rb +218 -0
- data/lib/active_record/relation/spawn_methods.rb +102 -0
- data/lib/active_record/schema_dumper.rb +10 -6
- data/lib/active_record/serialization.rb +31 -74
- data/lib/active_record/serializers/xml_serializer.rb +33 -121
- data/lib/active_record/session_store.rb +1 -9
- data/lib/active_record/test_case.rb +1 -3
- data/lib/active_record/timestamp.rb +7 -5
- data/lib/active_record/transactions.rb +9 -9
- data/lib/active_record/validations.rb +51 -1100
- data/lib/active_record/validations/associated.rb +47 -0
- data/lib/active_record/validations/uniqueness.rb +181 -0
- data/lib/active_record/version.rb +3 -3
- data/lib/generators/active_record.rb +30 -0
- data/lib/generators/active_record/migration/migration_generator.rb +25 -0
- data/lib/generators/active_record/migration/templates/migration.rb +11 -0
- data/lib/generators/active_record/model/model_generator.rb +33 -0
- data/lib/generators/active_record/model/templates/migration.rb +16 -0
- data/lib/generators/active_record/model/templates/model.rb +5 -0
- data/lib/generators/active_record/observer/observer_generator.rb +15 -0
- data/lib/generators/active_record/observer/templates/observer.rb +2 -0
- data/lib/generators/active_record/session_migration/session_migration_generator.rb +24 -0
- data/lib/generators/active_record/session_migration/templates/migration.rb +16 -0
- metadata +67 -325
- data/RUNNING_UNIT_TESTS +0 -36
- data/Rakefile +0 -268
- data/install.rb +0 -30
- data/lib/active_record/calculations.rb +0 -321
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -57
- data/lib/active_record/dirty.rb +0 -183
- data/lib/active_record/serializers/json_serializer.rb +0 -91
- data/lib/activerecord.rb +0 -2
- data/test/assets/example.log +0 -1
- data/test/assets/flowers.jpg +0 -0
- data/test/cases/aaa_create_tables_test.rb +0 -24
- data/test/cases/active_schema_test_mysql.rb +0 -122
- data/test/cases/active_schema_test_postgresql.rb +0 -24
- data/test/cases/adapter_test.rb +0 -144
- data/test/cases/aggregations_test.rb +0 -167
- data/test/cases/ar_schema_test.rb +0 -32
- data/test/cases/associations/belongs_to_associations_test.rb +0 -438
- data/test/cases/associations/callbacks_test.rb +0 -161
- data/test/cases/associations/cascaded_eager_loading_test.rb +0 -131
- data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +0 -36
- data/test/cases/associations/eager_load_nested_include_test.rb +0 -131
- data/test/cases/associations/eager_load_nested_polymorphic_include.rb +0 -19
- data/test/cases/associations/eager_singularization_test.rb +0 -145
- data/test/cases/associations/eager_test.rb +0 -852
- data/test/cases/associations/extension_test.rb +0 -62
- data/test/cases/associations/habtm_join_table_test.rb +0 -56
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +0 -827
- data/test/cases/associations/has_many_associations_test.rb +0 -1273
- data/test/cases/associations/has_many_through_associations_test.rb +0 -360
- data/test/cases/associations/has_one_associations_test.rb +0 -330
- data/test/cases/associations/has_one_through_associations_test.rb +0 -209
- data/test/cases/associations/inner_join_association_test.rb +0 -93
- data/test/cases/associations/inverse_associations_test.rb +0 -566
- data/test/cases/associations/join_model_test.rb +0 -712
- data/test/cases/associations_test.rb +0 -282
- data/test/cases/attribute_methods_test.rb +0 -305
- data/test/cases/autosave_association_test.rb +0 -1218
- data/test/cases/base_test.rb +0 -2166
- data/test/cases/batches_test.rb +0 -81
- data/test/cases/binary_test.rb +0 -30
- data/test/cases/calculations_test.rb +0 -360
- data/test/cases/callbacks_observers_test.rb +0 -38
- data/test/cases/callbacks_test.rb +0 -438
- data/test/cases/class_inheritable_attributes_test.rb +0 -32
- data/test/cases/column_alias_test.rb +0 -17
- data/test/cases/column_definition_test.rb +0 -70
- data/test/cases/connection_pool_test.rb +0 -25
- data/test/cases/connection_test_firebird.rb +0 -8
- data/test/cases/connection_test_mysql.rb +0 -65
- data/test/cases/copy_table_test_sqlite.rb +0 -80
- data/test/cases/counter_cache_test.rb +0 -84
- data/test/cases/database_statements_test.rb +0 -12
- data/test/cases/datatype_test_postgresql.rb +0 -204
- data/test/cases/date_time_test.rb +0 -37
- data/test/cases/default_test_firebird.rb +0 -16
- data/test/cases/defaults_test.rb +0 -111
- data/test/cases/deprecated_finder_test.rb +0 -30
- data/test/cases/dirty_test.rb +0 -316
- data/test/cases/finder_respond_to_test.rb +0 -76
- data/test/cases/finder_test.rb +0 -1098
- data/test/cases/fixtures_test.rb +0 -661
- data/test/cases/helper.rb +0 -68
- data/test/cases/i18n_test.rb +0 -46
- data/test/cases/inheritance_test.rb +0 -262
- data/test/cases/invalid_date_test.rb +0 -24
- data/test/cases/json_serialization_test.rb +0 -219
- data/test/cases/lifecycle_test.rb +0 -193
- data/test/cases/locking_test.rb +0 -350
- data/test/cases/method_scoping_test.rb +0 -704
- data/test/cases/migration_test.rb +0 -1649
- data/test/cases/migration_test_firebird.rb +0 -124
- data/test/cases/mixin_test.rb +0 -96
- data/test/cases/modules_test.rb +0 -109
- data/test/cases/multiple_db_test.rb +0 -85
- data/test/cases/named_scope_test.rb +0 -372
- data/test/cases/nested_attributes_test.rb +0 -840
- data/test/cases/pk_test.rb +0 -119
- data/test/cases/pooled_connections_test.rb +0 -103
- data/test/cases/query_cache_test.rb +0 -129
- data/test/cases/readonly_test.rb +0 -107
- data/test/cases/reflection_test.rb +0 -234
- data/test/cases/reload_models_test.rb +0 -22
- data/test/cases/repair_helper.rb +0 -50
- data/test/cases/reserved_word_test_mysql.rb +0 -176
- data/test/cases/sanitize_test.rb +0 -25
- data/test/cases/schema_authorization_test_postgresql.rb +0 -75
- data/test/cases/schema_dumper_test.rb +0 -211
- data/test/cases/schema_test_postgresql.rb +0 -178
- data/test/cases/serialization_test.rb +0 -47
- data/test/cases/sp_test_mysql.rb +0 -16
- data/test/cases/synonym_test_oracle.rb +0 -17
- data/test/cases/timestamp_test.rb +0 -75
- data/test/cases/transactions_test.rb +0 -543
- data/test/cases/unconnected_test.rb +0 -32
- data/test/cases/validations_i18n_test.rb +0 -925
- data/test/cases/validations_test.rb +0 -1684
- data/test/cases/xml_serialization_test.rb +0 -240
- data/test/cases/yaml_serialization_test.rb +0 -11
- data/test/config.rb +0 -5
- data/test/connections/jdbc_jdbcderby/connection.rb +0 -18
- data/test/connections/jdbc_jdbch2/connection.rb +0 -18
- data/test/connections/jdbc_jdbchsqldb/connection.rb +0 -18
- data/test/connections/jdbc_jdbcmysql/connection.rb +0 -26
- data/test/connections/jdbc_jdbcpostgresql/connection.rb +0 -26
- data/test/connections/jdbc_jdbcsqlite3/connection.rb +0 -25
- data/test/connections/native_db2/connection.rb +0 -25
- data/test/connections/native_firebird/connection.rb +0 -26
- data/test/connections/native_frontbase/connection.rb +0 -27
- data/test/connections/native_mysql/connection.rb +0 -25
- data/test/connections/native_openbase/connection.rb +0 -21
- data/test/connections/native_oracle/connection.rb +0 -27
- data/test/connections/native_postgresql/connection.rb +0 -21
- data/test/connections/native_sqlite/connection.rb +0 -25
- data/test/connections/native_sqlite3/connection.rb +0 -25
- data/test/connections/native_sqlite3/in_memory_connection.rb +0 -18
- data/test/connections/native_sybase/connection.rb +0 -23
- data/test/fixtures/accounts.yml +0 -29
- 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_addresses.yml +0 -5
- data/test/fixtures/author_favorites.yml +0 -4
- data/test/fixtures/authors.yml +0 -9
- data/test/fixtures/binaries.yml +0 -132
- data/test/fixtures/books.yml +0 -7
- data/test/fixtures/categories.yml +0 -14
- data/test/fixtures/categories/special_categories.yml +0 -9
- data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +0 -4
- data/test/fixtures/categories_ordered.yml +0 -7
- data/test/fixtures/categories_posts.yml +0 -23
- data/test/fixtures/categorizations.yml +0 -17
- data/test/fixtures/clubs.yml +0 -6
- data/test/fixtures/comments.yml +0 -59
- data/test/fixtures/companies.yml +0 -56
- data/test/fixtures/computers.yml +0 -4
- data/test/fixtures/courses.yml +0 -7
- data/test/fixtures/customers.yml +0 -26
- data/test/fixtures/developers.yml +0 -21
- data/test/fixtures/developers_projects.yml +0 -17
- data/test/fixtures/edges.yml +0 -6
- data/test/fixtures/entrants.yml +0 -14
- data/test/fixtures/faces.yml +0 -11
- data/test/fixtures/fk_test_has_fk.yml +0 -3
- data/test/fixtures/fk_test_has_pk.yml +0 -2
- data/test/fixtures/funny_jokes.yml +0 -10
- data/test/fixtures/interests.yml +0 -33
- data/test/fixtures/items.yml +0 -4
- data/test/fixtures/jobs.yml +0 -7
- data/test/fixtures/legacy_things.yml +0 -3
- data/test/fixtures/mateys.yml +0 -4
- data/test/fixtures/member_types.yml +0 -6
- data/test/fixtures/members.yml +0 -6
- data/test/fixtures/memberships.yml +0 -20
- data/test/fixtures/men.yml +0 -5
- data/test/fixtures/minimalistics.yml +0 -2
- data/test/fixtures/mixed_case_monkeys.yml +0 -6
- data/test/fixtures/mixins.yml +0 -29
- data/test/fixtures/movies.yml +0 -7
- data/test/fixtures/naked/csv/accounts.csv +0 -1
- data/test/fixtures/naked/yml/accounts.yml +0 -1
- data/test/fixtures/naked/yml/companies.yml +0 -1
- data/test/fixtures/naked/yml/courses.yml +0 -1
- data/test/fixtures/organizations.yml +0 -5
- data/test/fixtures/owners.yml +0 -7
- data/test/fixtures/parrots.yml +0 -27
- data/test/fixtures/parrots_pirates.yml +0 -7
- data/test/fixtures/people.yml +0 -15
- data/test/fixtures/pets.yml +0 -14
- data/test/fixtures/pirates.yml +0 -9
- data/test/fixtures/polymorphic_designs.yml +0 -19
- data/test/fixtures/polymorphic_prices.yml +0 -19
- data/test/fixtures/posts.yml +0 -52
- data/test/fixtures/price_estimates.yml +0 -7
- data/test/fixtures/projects.yml +0 -7
- data/test/fixtures/readers.yml +0 -9
- data/test/fixtures/references.yml +0 -17
- data/test/fixtures/reserved_words/distinct.yml +0 -5
- data/test/fixtures/reserved_words/distincts_selects.yml +0 -11
- data/test/fixtures/reserved_words/group.yml +0 -14
- data/test/fixtures/reserved_words/select.yml +0 -8
- data/test/fixtures/reserved_words/values.yml +0 -7
- data/test/fixtures/ships.yml +0 -5
- data/test/fixtures/sponsors.yml +0 -9
- data/test/fixtures/subscribers.yml +0 -7
- data/test/fixtures/subscriptions.yml +0 -12
- data/test/fixtures/taggings.yml +0 -28
- data/test/fixtures/tags.yml +0 -7
- data/test/fixtures/tasks.yml +0 -7
- data/test/fixtures/tees.yml +0 -4
- data/test/fixtures/ties.yml +0 -4
- data/test/fixtures/topics.yml +0 -42
- data/test/fixtures/toys.yml +0 -4
- data/test/fixtures/treasures.yml +0 -10
- data/test/fixtures/vertices.yml +0 -4
- data/test/fixtures/warehouse-things.yml +0 -3
- data/test/fixtures/zines.yml +0 -5
- data/test/migrations/broken/100_migration_that_raises_exception.rb +0 -10
- data/test/migrations/decimal/1_give_me_big_numbers.rb +0 -15
- data/test/migrations/duplicate/1_people_have_last_names.rb +0 -9
- data/test/migrations/duplicate/2_we_need_reminders.rb +0 -12
- data/test/migrations/duplicate/3_foo.rb +0 -7
- data/test/migrations/duplicate/3_innocent_jointable.rb +0 -12
- data/test/migrations/duplicate_names/20080507052938_chunky.rb +0 -7
- data/test/migrations/duplicate_names/20080507053028_chunky.rb +0 -7
- data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +0 -12
- data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +0 -9
- data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +0 -12
- data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +0 -9
- data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +0 -8
- data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +0 -12
- data/test/migrations/missing/1000_people_have_middle_names.rb +0 -9
- data/test/migrations/missing/1_people_have_last_names.rb +0 -9
- data/test/migrations/missing/3_we_need_reminders.rb +0 -12
- data/test/migrations/missing/4_innocent_jointable.rb +0 -12
- data/test/migrations/valid/1_people_have_last_names.rb +0 -9
- data/test/migrations/valid/2_we_need_reminders.rb +0 -12
- data/test/migrations/valid/3_innocent_jointable.rb +0 -12
- data/test/models/author.rb +0 -151
- data/test/models/auto_id.rb +0 -4
- data/test/models/binary.rb +0 -2
- data/test/models/bird.rb +0 -9
- data/test/models/book.rb +0 -4
- data/test/models/categorization.rb +0 -5
- data/test/models/category.rb +0 -34
- data/test/models/citation.rb +0 -6
- data/test/models/club.rb +0 -13
- data/test/models/column_name.rb +0 -3
- data/test/models/comment.rb +0 -29
- data/test/models/company.rb +0 -173
- data/test/models/company_in_module.rb +0 -78
- data/test/models/computer.rb +0 -3
- data/test/models/contact.rb +0 -16
- data/test/models/contract.rb +0 -5
- data/test/models/course.rb +0 -3
- data/test/models/customer.rb +0 -73
- data/test/models/default.rb +0 -2
- data/test/models/developer.rb +0 -101
- data/test/models/edge.rb +0 -5
- data/test/models/entrant.rb +0 -3
- data/test/models/essay.rb +0 -3
- data/test/models/event.rb +0 -3
- data/test/models/event_author.rb +0 -8
- data/test/models/face.rb +0 -7
- data/test/models/guid.rb +0 -2
- data/test/models/interest.rb +0 -5
- data/test/models/invoice.rb +0 -4
- data/test/models/item.rb +0 -7
- data/test/models/job.rb +0 -5
- data/test/models/joke.rb +0 -3
- data/test/models/keyboard.rb +0 -3
- data/test/models/legacy_thing.rb +0 -3
- data/test/models/line_item.rb +0 -3
- data/test/models/man.rb +0 -9
- data/test/models/matey.rb +0 -4
- data/test/models/member.rb +0 -12
- data/test/models/member_detail.rb +0 -5
- data/test/models/member_type.rb +0 -3
- data/test/models/membership.rb +0 -9
- data/test/models/minimalistic.rb +0 -2
- data/test/models/mixed_case_monkey.rb +0 -3
- data/test/models/movie.rb +0 -5
- data/test/models/order.rb +0 -4
- data/test/models/organization.rb +0 -6
- data/test/models/owner.rb +0 -5
- data/test/models/parrot.rb +0 -22
- data/test/models/person.rb +0 -16
- data/test/models/pet.rb +0 -5
- data/test/models/pirate.rb +0 -80
- data/test/models/polymorphic_design.rb +0 -3
- data/test/models/polymorphic_price.rb +0 -3
- data/test/models/post.rb +0 -102
- data/test/models/price_estimate.rb +0 -3
- data/test/models/project.rb +0 -30
- data/test/models/reader.rb +0 -4
- data/test/models/reference.rb +0 -4
- data/test/models/reply.rb +0 -46
- data/test/models/ship.rb +0 -19
- data/test/models/ship_part.rb +0 -7
- data/test/models/sponsor.rb +0 -4
- data/test/models/subject.rb +0 -4
- data/test/models/subscriber.rb +0 -8
- data/test/models/subscription.rb +0 -4
- data/test/models/tag.rb +0 -7
- data/test/models/tagging.rb +0 -10
- data/test/models/task.rb +0 -3
- data/test/models/tee.rb +0 -4
- data/test/models/tie.rb +0 -4
- data/test/models/topic.rb +0 -80
- data/test/models/toy.rb +0 -6
- data/test/models/treasure.rb +0 -8
- data/test/models/vertex.rb +0 -9
- data/test/models/warehouse_thing.rb +0 -5
- data/test/models/zine.rb +0 -3
- data/test/schema/mysql_specific_schema.rb +0 -31
- data/test/schema/postgresql_specific_schema.rb +0 -114
- data/test/schema/schema.rb +0 -550
- data/test/schema/schema2.rb +0 -6
- data/test/schema/sqlite_specific_schema.rb +0 -25
@@ -1,47 +0,0 @@
|
|
1
|
-
require "cases/helper"
|
2
|
-
require 'models/contact'
|
3
|
-
|
4
|
-
class SerializationTest < ActiveRecord::TestCase
|
5
|
-
FORMATS = [ :xml, :json ]
|
6
|
-
|
7
|
-
def setup
|
8
|
-
@contact_attributes = {
|
9
|
-
:name => 'aaron stack',
|
10
|
-
:age => 25,
|
11
|
-
:avatar => 'binarydata',
|
12
|
-
:created_at => Time.utc(2006, 8, 1),
|
13
|
-
:awesome => false,
|
14
|
-
:preferences => { :gem => '<strong>ruby</strong>' }
|
15
|
-
}
|
16
|
-
|
17
|
-
@contact = Contact.new(@contact_attributes)
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_serialize_should_be_reversible
|
21
|
-
for format in FORMATS
|
22
|
-
@serialized = Contact.new.send("to_#{format}")
|
23
|
-
contact = Contact.new.send("from_#{format}", @serialized)
|
24
|
-
|
25
|
-
assert_equal @contact_attributes.keys.collect(&:to_s).sort, contact.attributes.keys.collect(&:to_s).sort, "For #{format}"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_serialize_should_allow_attribute_only_filtering
|
30
|
-
for format in FORMATS
|
31
|
-
@serialized = Contact.new(@contact_attributes).send("to_#{format}", :only => [ :age, :name ])
|
32
|
-
contact = Contact.new.send("from_#{format}", @serialized)
|
33
|
-
assert_equal @contact_attributes[:name], contact.name, "For #{format}"
|
34
|
-
assert_nil contact.avatar, "For #{format}"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_serialize_should_allow_attribute_except_filtering
|
39
|
-
for format in FORMATS
|
40
|
-
@serialized = Contact.new(@contact_attributes).send("to_#{format}", :except => [ :age, :name ])
|
41
|
-
contact = Contact.new.send("from_#{format}", @serialized)
|
42
|
-
assert_nil contact.name, "For #{format}"
|
43
|
-
assert_nil contact.age, "For #{format}"
|
44
|
-
assert_equal @contact_attributes[:awesome], contact.awesome, "For #{format}"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
data/test/cases/sp_test_mysql.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
require "cases/helper"
|
2
|
-
require 'models/topic'
|
3
|
-
require 'models/minimalistic'
|
4
|
-
|
5
|
-
class StoredProcedureTest < ActiveRecord::TestCase
|
6
|
-
fixtures :topics
|
7
|
-
|
8
|
-
# Test that MySQL allows multiple results for stored procedures
|
9
|
-
if Mysql.const_defined?(:CLIENT_MULTI_RESULTS)
|
10
|
-
def test_multi_results_from_find_by_sql
|
11
|
-
topics = Topic.find_by_sql 'CALL topics();'
|
12
|
-
assert_equal 1, topics.size
|
13
|
-
assert ActiveRecord::Base.connection.active?, "Bad connection use by 'MysqlAdapter.select'"
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
require "cases/helper"
|
2
|
-
require 'models/topic'
|
3
|
-
require 'models/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 < ActiveRecord::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
|
@@ -1,75 +0,0 @@
|
|
1
|
-
require 'cases/helper'
|
2
|
-
require 'models/developer'
|
3
|
-
require 'models/owner'
|
4
|
-
require 'models/pet'
|
5
|
-
|
6
|
-
class TimestampTest < ActiveRecord::TestCase
|
7
|
-
fixtures :developers, :owners, :pets
|
8
|
-
|
9
|
-
def setup
|
10
|
-
@developer = Developer.first
|
11
|
-
@previously_updated_at = @developer.updated_at
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_saving_a_changed_record_updates_its_timestamp
|
15
|
-
@developer.name = "Jack Bauer"
|
16
|
-
@developer.save!
|
17
|
-
|
18
|
-
assert @previously_updated_at != @developer.updated_at
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_saving_a_unchanged_record_doesnt_update_its_timestamp
|
22
|
-
@developer.save!
|
23
|
-
|
24
|
-
assert @previously_updated_at == @developer.updated_at
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_touching_a_record_updates_its_timestamp
|
28
|
-
@developer.touch
|
29
|
-
|
30
|
-
assert @previously_updated_at != @developer.updated_at
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_touching_a_different_attribute
|
34
|
-
previously_created_at = @developer.created_at
|
35
|
-
@developer.touch(:created_at)
|
36
|
-
|
37
|
-
assert previously_created_at != @developer.created_at
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_saving_a_record_with_a_belongs_to_that_specifies_touching_the_parent_should_update_the_parent_updated_at
|
41
|
-
pet = Pet.first
|
42
|
-
owner = pet.owner
|
43
|
-
previously_owner_updated_at = owner.updated_at
|
44
|
-
|
45
|
-
pet.name = "Fluffy the Third"
|
46
|
-
pet.save
|
47
|
-
|
48
|
-
assert previously_owner_updated_at != pet.owner.updated_at
|
49
|
-
end
|
50
|
-
|
51
|
-
def test_destroying_a_record_with_a_belongs_to_that_specifies_touching_the_parent_should_update_the_parent_updated_at
|
52
|
-
pet = Pet.first
|
53
|
-
owner = pet.owner
|
54
|
-
previously_owner_updated_at = owner.updated_at
|
55
|
-
|
56
|
-
pet.destroy
|
57
|
-
|
58
|
-
assert previously_owner_updated_at != pet.owner.updated_at
|
59
|
-
end
|
60
|
-
|
61
|
-
def test_saving_a_record_with_a_belongs_to_that_specifies_touching_a_specific_attribute_the_parent_should_update_that_attribute
|
62
|
-
Pet.belongs_to :owner, :touch => :happy_at
|
63
|
-
|
64
|
-
pet = Pet.first
|
65
|
-
owner = pet.owner
|
66
|
-
previously_owner_happy_at = owner.happy_at
|
67
|
-
|
68
|
-
pet.name = "Fluffy the Third"
|
69
|
-
pet.save
|
70
|
-
|
71
|
-
assert previously_owner_happy_at != pet.owner.happy_at
|
72
|
-
ensure
|
73
|
-
Pet.belongs_to :owner, :touch => true
|
74
|
-
end
|
75
|
-
end
|
@@ -1,543 +0,0 @@
|
|
1
|
-
require "cases/helper"
|
2
|
-
require 'models/topic'
|
3
|
-
require 'models/reply'
|
4
|
-
require 'models/developer'
|
5
|
-
require 'models/book'
|
6
|
-
require 'models/author'
|
7
|
-
require 'models/post'
|
8
|
-
|
9
|
-
class TransactionTest < ActiveRecord::TestCase
|
10
|
-
self.use_transactional_fixtures = false
|
11
|
-
fixtures :topics, :developers, :authors, :posts
|
12
|
-
|
13
|
-
def setup
|
14
|
-
@first, @second = Topic.find(1, 2).sort_by { |t| t.id }
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_successful
|
18
|
-
Topic.transaction do
|
19
|
-
@first.approved = true
|
20
|
-
@second.approved = false
|
21
|
-
@first.save
|
22
|
-
@second.save
|
23
|
-
end
|
24
|
-
|
25
|
-
assert Topic.find(1).approved?, "First should have been approved"
|
26
|
-
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
27
|
-
end
|
28
|
-
|
29
|
-
def transaction_with_return
|
30
|
-
Topic.transaction do
|
31
|
-
@first.approved = true
|
32
|
-
@second.approved = false
|
33
|
-
@first.save
|
34
|
-
@second.save
|
35
|
-
return
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def test_update_attributes_should_rollback_on_failure
|
40
|
-
author = Author.find(1)
|
41
|
-
posts_count = author.posts.size
|
42
|
-
assert posts_count > 0
|
43
|
-
status = author.update_attributes(:name => nil, :post_ids => [])
|
44
|
-
assert !status
|
45
|
-
assert_equal posts_count, author.posts(true).size
|
46
|
-
end
|
47
|
-
|
48
|
-
def test_update_attributes_should_rollback_on_failure!
|
49
|
-
author = Author.find(1)
|
50
|
-
posts_count = author.posts.size
|
51
|
-
assert posts_count > 0
|
52
|
-
assert_raise(ActiveRecord::RecordInvalid) do
|
53
|
-
author.update_attributes!(:name => nil, :post_ids => [])
|
54
|
-
end
|
55
|
-
assert_equal posts_count, author.posts(true).size
|
56
|
-
end
|
57
|
-
|
58
|
-
def test_successful_with_return
|
59
|
-
class << Topic.connection
|
60
|
-
alias :real_commit_db_transaction :commit_db_transaction
|
61
|
-
def commit_db_transaction
|
62
|
-
$committed = true
|
63
|
-
real_commit_db_transaction
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
$committed = false
|
68
|
-
transaction_with_return
|
69
|
-
assert $committed
|
70
|
-
|
71
|
-
assert Topic.find(1).approved?, "First should have been approved"
|
72
|
-
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
73
|
-
ensure
|
74
|
-
class << Topic.connection
|
75
|
-
alias :commit_db_transaction :real_commit_db_transaction rescue nil
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def test_successful_with_instance_method
|
80
|
-
@first.transaction do
|
81
|
-
@first.approved = true
|
82
|
-
@second.approved = false
|
83
|
-
@first.save
|
84
|
-
@second.save
|
85
|
-
end
|
86
|
-
|
87
|
-
assert Topic.find(1).approved?, "First should have been approved"
|
88
|
-
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
89
|
-
end
|
90
|
-
|
91
|
-
def test_failing_on_exception
|
92
|
-
begin
|
93
|
-
Topic.transaction do
|
94
|
-
@first.approved = true
|
95
|
-
@second.approved = false
|
96
|
-
@first.save
|
97
|
-
@second.save
|
98
|
-
raise "Bad things!"
|
99
|
-
end
|
100
|
-
rescue
|
101
|
-
# caught it
|
102
|
-
end
|
103
|
-
|
104
|
-
assert @first.approved?, "First should still be changed in the objects"
|
105
|
-
assert !@second.approved?, "Second should still be changed in the objects"
|
106
|
-
|
107
|
-
assert !Topic.find(1).approved?, "First shouldn't have been approved"
|
108
|
-
assert Topic.find(2).approved?, "Second should still be approved"
|
109
|
-
end
|
110
|
-
|
111
|
-
def test_raising_exception_in_callback_rollbacks_in_save
|
112
|
-
add_exception_raising_after_save_callback_to_topic
|
113
|
-
|
114
|
-
begin
|
115
|
-
@first.approved = true
|
116
|
-
@first.save
|
117
|
-
flunk
|
118
|
-
rescue => e
|
119
|
-
assert_equal "Make the transaction rollback", e.message
|
120
|
-
assert !Topic.find(1).approved?
|
121
|
-
ensure
|
122
|
-
remove_exception_raising_after_save_callback_to_topic
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def test_cancellation_from_before_destroy_rollbacks_in_destroy
|
127
|
-
add_cancelling_before_destroy_with_db_side_effect_to_topic
|
128
|
-
begin
|
129
|
-
nbooks_before_destroy = Book.count
|
130
|
-
status = @first.destroy
|
131
|
-
assert !status
|
132
|
-
assert_nothing_raised(ActiveRecord::RecordNotFound) { @first.reload }
|
133
|
-
assert_equal nbooks_before_destroy, Book.count
|
134
|
-
ensure
|
135
|
-
remove_cancelling_before_destroy_with_db_side_effect_to_topic
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def test_cancellation_from_before_filters_rollbacks_in_save
|
140
|
-
%w(validation save).each do |filter|
|
141
|
-
send("add_cancelling_before_#{filter}_with_db_side_effect_to_topic")
|
142
|
-
begin
|
143
|
-
nbooks_before_save = Book.count
|
144
|
-
original_author_name = @first.author_name
|
145
|
-
@first.author_name += '_this_should_not_end_up_in_the_db'
|
146
|
-
status = @first.save
|
147
|
-
assert !status
|
148
|
-
assert_equal original_author_name, @first.reload.author_name
|
149
|
-
assert_equal nbooks_before_save, Book.count
|
150
|
-
ensure
|
151
|
-
send("remove_cancelling_before_#{filter}_with_db_side_effect_to_topic")
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
def test_cancellation_from_before_filters_rollbacks_in_save!
|
157
|
-
%w(validation save).each do |filter|
|
158
|
-
send("add_cancelling_before_#{filter}_with_db_side_effect_to_topic")
|
159
|
-
begin
|
160
|
-
nbooks_before_save = Book.count
|
161
|
-
original_author_name = @first.author_name
|
162
|
-
@first.author_name += '_this_should_not_end_up_in_the_db'
|
163
|
-
@first.save!
|
164
|
-
flunk
|
165
|
-
rescue => e
|
166
|
-
assert_equal original_author_name, @first.reload.author_name
|
167
|
-
assert_equal nbooks_before_save, Book.count
|
168
|
-
ensure
|
169
|
-
send("remove_cancelling_before_#{filter}_with_db_side_effect_to_topic")
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
def test_callback_rollback_in_create
|
175
|
-
new_topic = Topic.new(
|
176
|
-
:title => "A new topic",
|
177
|
-
:author_name => "Ben",
|
178
|
-
:author_email_address => "ben@example.com",
|
179
|
-
:written_on => "2003-07-16t15:28:11.2233+01:00",
|
180
|
-
:last_read => "2004-04-15",
|
181
|
-
:bonus_time => "2005-01-30t15:28:00.00+01:00",
|
182
|
-
:content => "Have a nice day",
|
183
|
-
:approved => false)
|
184
|
-
new_record_snapshot = new_topic.new_record?
|
185
|
-
id_present = new_topic.has_attribute?(Topic.primary_key)
|
186
|
-
id_snapshot = new_topic.id
|
187
|
-
|
188
|
-
# Make sure the second save gets the after_create callback called.
|
189
|
-
2.times do
|
190
|
-
begin
|
191
|
-
add_exception_raising_after_create_callback_to_topic
|
192
|
-
new_topic.approved = true
|
193
|
-
new_topic.save
|
194
|
-
flunk
|
195
|
-
rescue => e
|
196
|
-
assert_equal "Make the transaction rollback", e.message
|
197
|
-
assert_equal new_record_snapshot, new_topic.new_record?, "The topic should have its old new_record value"
|
198
|
-
assert_equal id_snapshot, new_topic.id, "The topic should have its old id"
|
199
|
-
assert_equal id_present, new_topic.has_attribute?(Topic.primary_key)
|
200
|
-
ensure
|
201
|
-
remove_exception_raising_after_create_callback_to_topic
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
def test_nested_explicit_transactions
|
207
|
-
Topic.transaction do
|
208
|
-
Topic.transaction do
|
209
|
-
@first.approved = true
|
210
|
-
@second.approved = false
|
211
|
-
@first.save
|
212
|
-
@second.save
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
assert Topic.find(1).approved?, "First should have been approved"
|
217
|
-
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
218
|
-
end
|
219
|
-
|
220
|
-
def test_manually_rolling_back_a_transaction
|
221
|
-
Topic.transaction do
|
222
|
-
@first.approved = true
|
223
|
-
@second.approved = false
|
224
|
-
@first.save
|
225
|
-
@second.save
|
226
|
-
|
227
|
-
raise ActiveRecord::Rollback
|
228
|
-
end
|
229
|
-
|
230
|
-
assert @first.approved?, "First should still be changed in the objects"
|
231
|
-
assert !@second.approved?, "Second should still be changed in the objects"
|
232
|
-
|
233
|
-
assert !Topic.find(1).approved?, "First shouldn't have been approved"
|
234
|
-
assert Topic.find(2).approved?, "Second should still be approved"
|
235
|
-
end
|
236
|
-
|
237
|
-
def test_invalid_keys_for_transaction
|
238
|
-
assert_raise ArgumentError do
|
239
|
-
Topic.transaction :nested => true do
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
def test_force_savepoint_in_nested_transaction
|
245
|
-
Topic.transaction do
|
246
|
-
@first.approved = true
|
247
|
-
@second.approved = false
|
248
|
-
@first.save!
|
249
|
-
@second.save!
|
250
|
-
|
251
|
-
begin
|
252
|
-
Topic.transaction :requires_new => true do
|
253
|
-
@first.happy = false
|
254
|
-
@first.save!
|
255
|
-
raise
|
256
|
-
end
|
257
|
-
rescue
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
assert @first.reload.approved?
|
262
|
-
assert !@second.reload.approved?
|
263
|
-
end if Topic.connection.supports_savepoints?
|
264
|
-
|
265
|
-
def test_no_savepoint_in_nested_transaction_without_force
|
266
|
-
Topic.transaction do
|
267
|
-
@first.approved = true
|
268
|
-
@second.approved = false
|
269
|
-
@first.save!
|
270
|
-
@second.save!
|
271
|
-
|
272
|
-
begin
|
273
|
-
Topic.transaction do
|
274
|
-
@first.approved = false
|
275
|
-
@first.save!
|
276
|
-
raise
|
277
|
-
end
|
278
|
-
rescue
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
assert !@first.reload.approved?
|
283
|
-
assert !@second.reload.approved?
|
284
|
-
end if Topic.connection.supports_savepoints?
|
285
|
-
|
286
|
-
def test_many_savepoints
|
287
|
-
Topic.transaction do
|
288
|
-
@first.content = "One"
|
289
|
-
@first.save!
|
290
|
-
|
291
|
-
begin
|
292
|
-
Topic.transaction :requires_new => true do
|
293
|
-
@first.content = "Two"
|
294
|
-
@first.save!
|
295
|
-
|
296
|
-
begin
|
297
|
-
Topic.transaction :requires_new => true do
|
298
|
-
@first.content = "Three"
|
299
|
-
@first.save!
|
300
|
-
|
301
|
-
begin
|
302
|
-
Topic.transaction :requires_new => true do
|
303
|
-
@first.content = "Four"
|
304
|
-
@first.save!
|
305
|
-
raise
|
306
|
-
end
|
307
|
-
rescue
|
308
|
-
end
|
309
|
-
|
310
|
-
@three = @first.reload.content
|
311
|
-
raise
|
312
|
-
end
|
313
|
-
rescue
|
314
|
-
end
|
315
|
-
|
316
|
-
@two = @first.reload.content
|
317
|
-
raise
|
318
|
-
end
|
319
|
-
rescue
|
320
|
-
end
|
321
|
-
|
322
|
-
@one = @first.reload.content
|
323
|
-
end
|
324
|
-
|
325
|
-
assert_equal "One", @one
|
326
|
-
assert_equal "Two", @two
|
327
|
-
assert_equal "Three", @three
|
328
|
-
end if Topic.connection.supports_savepoints?
|
329
|
-
|
330
|
-
def test_rollback_when_commit_raises
|
331
|
-
Topic.connection.expects(:begin_db_transaction)
|
332
|
-
Topic.connection.expects(:commit_db_transaction).raises('OH NOES')
|
333
|
-
Topic.connection.expects(:outside_transaction?).returns(false)
|
334
|
-
Topic.connection.expects(:rollback_db_transaction)
|
335
|
-
|
336
|
-
assert_raise RuntimeError do
|
337
|
-
Topic.transaction do
|
338
|
-
# do nothing
|
339
|
-
end
|
340
|
-
end
|
341
|
-
end
|
342
|
-
|
343
|
-
if current_adapter?(:PostgreSQLAdapter) && defined?(PGconn::PQTRANS_IDLE)
|
344
|
-
def test_outside_transaction_works
|
345
|
-
assert Topic.connection.outside_transaction?
|
346
|
-
Topic.connection.begin_db_transaction
|
347
|
-
assert !Topic.connection.outside_transaction?
|
348
|
-
Topic.connection.rollback_db_transaction
|
349
|
-
assert Topic.connection.outside_transaction?
|
350
|
-
end
|
351
|
-
|
352
|
-
def test_rollback_wont_be_executed_if_no_transaction_active
|
353
|
-
assert_raise RuntimeError do
|
354
|
-
Topic.transaction do
|
355
|
-
Topic.connection.rollback_db_transaction
|
356
|
-
Topic.connection.expects(:rollback_db_transaction).never
|
357
|
-
raise "Rails doesn't scale!"
|
358
|
-
end
|
359
|
-
end
|
360
|
-
end
|
361
|
-
|
362
|
-
def test_open_transactions_count_is_reset_to_zero_if_no_transaction_active
|
363
|
-
Topic.transaction do
|
364
|
-
Topic.transaction do
|
365
|
-
Topic.connection.rollback_db_transaction
|
366
|
-
end
|
367
|
-
assert_equal 0, Topic.connection.open_transactions
|
368
|
-
end
|
369
|
-
assert_equal 0, Topic.connection.open_transactions
|
370
|
-
end
|
371
|
-
end
|
372
|
-
|
373
|
-
def test_sqlite_add_column_in_transaction
|
374
|
-
return true unless current_adapter?(:SQLite3Adapter, :SQLiteAdapter)
|
375
|
-
|
376
|
-
# Test first if column creation/deletion works correctly when no
|
377
|
-
# transaction is in place.
|
378
|
-
#
|
379
|
-
# We go back to the connection for the column queries because
|
380
|
-
# Topic.columns is cached and won't report changes to the DB
|
381
|
-
|
382
|
-
assert_nothing_raised do
|
383
|
-
Topic.reset_column_information
|
384
|
-
Topic.connection.add_column('topics', 'stuff', :string)
|
385
|
-
assert Topic.column_names.include?('stuff')
|
386
|
-
|
387
|
-
Topic.reset_column_information
|
388
|
-
Topic.connection.remove_column('topics', 'stuff')
|
389
|
-
assert !Topic.column_names.include?('stuff')
|
390
|
-
end
|
391
|
-
|
392
|
-
if Topic.connection.supports_ddl_transactions?
|
393
|
-
assert_nothing_raised do
|
394
|
-
Topic.transaction { Topic.connection.add_column('topics', 'stuff', :string) }
|
395
|
-
end
|
396
|
-
else
|
397
|
-
Topic.transaction do
|
398
|
-
assert_raise(ActiveRecord::StatementInvalid) { Topic.connection.add_column('topics', 'stuff', :string) }
|
399
|
-
raise ActiveRecord::Rollback
|
400
|
-
end
|
401
|
-
end
|
402
|
-
end
|
403
|
-
|
404
|
-
private
|
405
|
-
def add_exception_raising_after_save_callback_to_topic
|
406
|
-
Topic.class_eval { def after_save() raise "Make the transaction rollback" end }
|
407
|
-
end
|
408
|
-
|
409
|
-
def remove_exception_raising_after_save_callback_to_topic
|
410
|
-
Topic.class_eval { remove_method :after_save }
|
411
|
-
end
|
412
|
-
|
413
|
-
def add_exception_raising_after_create_callback_to_topic
|
414
|
-
Topic.class_eval { def after_create() raise "Make the transaction rollback" end }
|
415
|
-
end
|
416
|
-
|
417
|
-
def remove_exception_raising_after_create_callback_to_topic
|
418
|
-
Topic.class_eval { remove_method :after_create }
|
419
|
-
end
|
420
|
-
|
421
|
-
%w(validation save destroy).each do |filter|
|
422
|
-
define_method("add_cancelling_before_#{filter}_with_db_side_effect_to_topic") do
|
423
|
-
Topic.class_eval "def before_#{filter}() Book.create; false end"
|
424
|
-
end
|
425
|
-
|
426
|
-
define_method("remove_cancelling_before_#{filter}_with_db_side_effect_to_topic") do
|
427
|
-
Topic.class_eval "remove_method :before_#{filter}"
|
428
|
-
end
|
429
|
-
end
|
430
|
-
end
|
431
|
-
|
432
|
-
class TransactionsWithTransactionalFixturesTest < ActiveRecord::TestCase
|
433
|
-
self.use_transactional_fixtures = true
|
434
|
-
fixtures :topics
|
435
|
-
|
436
|
-
def test_automatic_savepoint_in_outer_transaction
|
437
|
-
@first = Topic.find(1)
|
438
|
-
|
439
|
-
begin
|
440
|
-
Topic.transaction do
|
441
|
-
@first.approved = true
|
442
|
-
@first.save!
|
443
|
-
raise
|
444
|
-
end
|
445
|
-
rescue
|
446
|
-
assert !@first.reload.approved?
|
447
|
-
end
|
448
|
-
end
|
449
|
-
|
450
|
-
def test_no_automatic_savepoint_for_inner_transaction
|
451
|
-
@first = Topic.find(1)
|
452
|
-
|
453
|
-
Topic.transaction do
|
454
|
-
@first.approved = true
|
455
|
-
@first.save!
|
456
|
-
|
457
|
-
begin
|
458
|
-
Topic.transaction do
|
459
|
-
@first.approved = false
|
460
|
-
@first.save!
|
461
|
-
raise
|
462
|
-
end
|
463
|
-
rescue
|
464
|
-
end
|
465
|
-
end
|
466
|
-
|
467
|
-
assert !@first.reload.approved?
|
468
|
-
end
|
469
|
-
end if Topic.connection.supports_savepoints?
|
470
|
-
|
471
|
-
if current_adapter?(:PostgreSQLAdapter)
|
472
|
-
class ConcurrentTransactionTest < TransactionTest
|
473
|
-
use_concurrent_connections
|
474
|
-
|
475
|
-
# This will cause transactions to overlap and fail unless they are performed on
|
476
|
-
# separate database connections.
|
477
|
-
def test_transaction_per_thread
|
478
|
-
assert_nothing_raised do
|
479
|
-
threads = (1..3).map do
|
480
|
-
Thread.new do
|
481
|
-
Topic.transaction do
|
482
|
-
topic = Topic.find(1)
|
483
|
-
topic.approved = !topic.approved?
|
484
|
-
topic.save!
|
485
|
-
topic.approved = !topic.approved?
|
486
|
-
topic.save!
|
487
|
-
end
|
488
|
-
end
|
489
|
-
end
|
490
|
-
|
491
|
-
threads.each { |t| t.join }
|
492
|
-
end
|
493
|
-
end
|
494
|
-
|
495
|
-
# Test for dirty reads among simultaneous transactions.
|
496
|
-
def test_transaction_isolation__read_committed
|
497
|
-
# Should be invariant.
|
498
|
-
original_salary = Developer.find(1).salary
|
499
|
-
temporary_salary = 200000
|
500
|
-
|
501
|
-
assert_nothing_raised do
|
502
|
-
threads = (1..3).map do
|
503
|
-
Thread.new do
|
504
|
-
Developer.transaction do
|
505
|
-
# Expect original salary.
|
506
|
-
dev = Developer.find(1)
|
507
|
-
assert_equal original_salary, dev.salary
|
508
|
-
|
509
|
-
dev.salary = temporary_salary
|
510
|
-
dev.save!
|
511
|
-
|
512
|
-
# Expect temporary salary.
|
513
|
-
dev = Developer.find(1)
|
514
|
-
assert_equal temporary_salary, dev.salary
|
515
|
-
|
516
|
-
dev.salary = original_salary
|
517
|
-
dev.save!
|
518
|
-
|
519
|
-
# Expect original salary.
|
520
|
-
dev = Developer.find(1)
|
521
|
-
assert_equal original_salary, dev.salary
|
522
|
-
end
|
523
|
-
end
|
524
|
-
end
|
525
|
-
|
526
|
-
# Keep our eyes peeled.
|
527
|
-
threads << Thread.new do
|
528
|
-
10.times do
|
529
|
-
sleep 0.05
|
530
|
-
Developer.transaction do
|
531
|
-
# Always expect original salary.
|
532
|
-
assert_equal original_salary, Developer.find(1).salary
|
533
|
-
end
|
534
|
-
end
|
535
|
-
end
|
536
|
-
|
537
|
-
threads.each { |t| t.join }
|
538
|
-
end
|
539
|
-
|
540
|
-
assert_equal original_salary, Developer.find(1).salary
|
541
|
-
end
|
542
|
-
end
|
543
|
-
end
|