activerecord 2.0.5 → 2.1.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 +168 -6
- data/README +27 -22
- data/RUNNING_UNIT_TESTS +7 -4
- data/Rakefile +22 -25
- data/lib/active_record.rb +8 -2
- data/lib/active_record/aggregations.rb +21 -12
- data/lib/active_record/association_preload.rb +277 -0
- data/lib/active_record/associations.rb +481 -295
- data/lib/active_record/associations/association_collection.rb +162 -37
- data/lib/active_record/associations/association_proxy.rb +71 -7
- data/lib/active_record/associations/belongs_to_association.rb +5 -3
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +5 -6
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +12 -64
- data/lib/active_record/associations/has_many_association.rb +8 -73
- data/lib/active_record/associations/has_many_through_association.rb +68 -117
- data/lib/active_record/associations/has_one_association.rb +7 -5
- data/lib/active_record/associations/has_one_through_association.rb +28 -0
- data/lib/active_record/attribute_methods.rb +69 -19
- data/lib/active_record/base.rb +496 -275
- data/lib/active_record/calculations.rb +28 -21
- data/lib/active_record/callbacks.rb +9 -38
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -2
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +232 -45
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +141 -27
- data/lib/active_record/connection_adapters/abstract_adapter.rb +9 -13
- data/lib/active_record/connection_adapters/mysql_adapter.rb +57 -24
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +143 -42
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +18 -10
- data/lib/active_record/dirty.rb +158 -0
- data/lib/active_record/fixtures.rb +121 -156
- data/lib/active_record/locking/optimistic.rb +14 -11
- data/lib/active_record/locking/pessimistic.rb +2 -2
- data/lib/active_record/migration.rb +157 -77
- data/lib/active_record/named_scope.rb +163 -0
- data/lib/active_record/observer.rb +19 -5
- data/lib/active_record/reflection.rb +34 -14
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +4 -4
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/serializers/json_serializer.rb +37 -28
- data/lib/active_record/serializers/xml_serializer.rb +52 -29
- data/lib/active_record/test_case.rb +36 -0
- data/lib/active_record/timestamp.rb +4 -4
- data/lib/active_record/transactions.rb +3 -3
- data/lib/active_record/validations.rb +182 -248
- data/lib/active_record/version.rb +2 -2
- data/test/{fixtures → assets}/example.log +0 -0
- data/test/{fixtures → assets}/flowers.jpg +0 -0
- data/test/cases/aaa_create_tables_test.rb +24 -0
- data/test/cases/active_schema_test_mysql.rb +95 -0
- data/test/cases/active_schema_test_postgresql.rb +24 -0
- data/test/{adapter_test.rb → cases/adapter_test.rb} +15 -14
- data/test/{adapter_test_sqlserver.rb → cases/adapter_test_sqlserver.rb} +95 -95
- data/test/{aggregations_test.rb → cases/aggregations_test.rb} +20 -20
- data/test/{ar_schema_test.rb → cases/ar_schema_test.rb} +6 -6
- data/test/cases/associations/belongs_to_associations_test.rb +412 -0
- data/test/{associations → cases/associations}/callbacks_test.rb +24 -10
- data/test/{associations → cases/associations}/cascaded_eager_loading_test.rb +18 -17
- data/test/cases/associations/eager_load_nested_include_test.rb +83 -0
- data/test/{associations → cases/associations}/eager_singularization_test.rb +5 -5
- data/test/{associations → cases/associations}/eager_test.rb +216 -51
- data/test/{associations → cases/associations}/extension_test.rb +8 -8
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +684 -0
- data/test/cases/associations/has_many_associations_test.rb +932 -0
- data/test/cases/associations/has_many_through_associations_test.rb +190 -0
- data/test/cases/associations/has_one_associations_test.rb +323 -0
- data/test/cases/associations/has_one_through_associations_test.rb +74 -0
- data/test/{associations → cases/associations}/inner_join_association_test.rb +20 -20
- data/test/{associations → cases/associations}/join_model_test.rb +175 -35
- data/test/cases/associations_test.rb +262 -0
- data/test/{attribute_methods_test.rb → cases/attribute_methods_test.rb} +103 -11
- data/test/{base_test.rb → cases/base_test.rb} +338 -191
- data/test/{binary_test.rb → cases/binary_test.rb} +6 -4
- data/test/{calculations_test.rb → cases/calculations_test.rb} +35 -23
- data/test/{callbacks_test.rb → cases/callbacks_test.rb} +7 -7
- data/test/{class_inheritable_attributes_test.rb → cases/class_inheritable_attributes_test.rb} +3 -3
- data/test/{column_alias_test.rb → cases/column_alias_test.rb} +3 -3
- data/test/{connection_test_firebird.rb → cases/connection_test_firebird.rb} +2 -2
- data/test/{connection_test_mysql.rb → cases/connection_test_mysql.rb} +2 -2
- data/test/{copy_table_test_sqlite.rb → cases/copy_table_test_sqlite.rb} +13 -13
- data/test/{datatype_test_postgresql.rb → cases/datatype_test_postgresql.rb} +8 -8
- data/test/{date_time_test.rb → cases/date_time_test.rb} +5 -5
- data/test/{default_test_firebird.rb → cases/default_test_firebird.rb} +3 -3
- data/test/{defaults_test.rb → cases/defaults_test.rb} +8 -6
- data/test/{deprecated_finder_test.rb → cases/deprecated_finder_test.rb} +3 -3
- data/test/cases/dirty_test.rb +163 -0
- data/test/cases/finder_respond_to_test.rb +76 -0
- data/test/{finder_test.rb → cases/finder_test.rb} +266 -33
- data/test/{fixtures_test.rb → cases/fixtures_test.rb} +88 -72
- data/test/cases/helper.rb +47 -0
- data/test/{inheritance_test.rb → cases/inheritance_test.rb} +61 -17
- data/test/cases/invalid_date_test.rb +24 -0
- data/test/{json_serialization_test.rb → cases/json_serialization_test.rb} +36 -11
- data/test/{lifecycle_test.rb → cases/lifecycle_test.rb} +16 -13
- data/test/{locking_test.rb → cases/locking_test.rb} +17 -10
- data/test/{method_scoping_test.rb → cases/method_scoping_test.rb} +75 -39
- data/test/{migration_test.rb → cases/migration_test.rb} +420 -80
- data/test/{migration_test_firebird.rb → cases/migration_test_firebird.rb} +3 -3
- data/test/{mixin_test.rb → cases/mixin_test.rb} +7 -6
- data/test/{modules_test.rb → cases/modules_test.rb} +11 -6
- data/test/{multiple_db_test.rb → cases/multiple_db_test.rb} +5 -5
- data/test/cases/named_scope_test.rb +157 -0
- data/test/{pk_test.rb → cases/pk_test.rb} +10 -10
- data/test/{query_cache_test.rb → cases/query_cache_test.rb} +12 -10
- data/test/{readonly_test.rb → cases/readonly_test.rb} +11 -11
- data/test/{reflection_test.rb → cases/reflection_test.rb} +15 -14
- data/test/{reserved_word_test_mysql.rb → cases/reserved_word_test_mysql.rb} +4 -5
- data/test/{schema_authorization_test_postgresql.rb → cases/schema_authorization_test_postgresql.rb} +5 -5
- data/test/cases/schema_dumper_test.rb +138 -0
- data/test/cases/schema_test_postgresql.rb +102 -0
- data/test/{serialization_test.rb → cases/serialization_test.rb} +7 -7
- data/test/{synonym_test_oracle.rb → cases/synonym_test_oracle.rb} +5 -5
- data/test/{table_name_test_sqlserver.rb → cases/table_name_test_sqlserver.rb} +3 -3
- data/test/{threaded_connections_test.rb → cases/threaded_connections_test.rb} +7 -7
- data/test/{transactions_test.rb → cases/transactions_test.rb} +31 -5
- data/test/{unconnected_test.rb → cases/unconnected_test.rb} +2 -2
- data/test/{validations_test.rb → cases/validations_test.rb} +141 -39
- data/test/{xml_serialization_test.rb → cases/xml_serialization_test.rb} +12 -12
- data/test/config.rb +5 -0
- data/test/connections/native_db2/connection.rb +1 -1
- data/test/connections/native_firebird/connection.rb +1 -1
- data/test/connections/native_frontbase/connection.rb +1 -1
- data/test/connections/native_mysql/connection.rb +1 -1
- data/test/connections/native_openbase/connection.rb +1 -1
- data/test/connections/native_oracle/connection.rb +1 -1
- data/test/connections/native_postgresql/connection.rb +1 -3
- data/test/connections/native_sqlite/connection.rb +2 -2
- data/test/connections/native_sqlite3/connection.rb +2 -2
- data/test/connections/native_sqlite3/in_memory_connection.rb +3 -3
- data/test/connections/native_sybase/connection.rb +1 -1
- data/test/fixtures/author_addresses.yml +5 -0
- data/test/fixtures/authors.yml +2 -0
- data/test/fixtures/clubs.yml +6 -0
- data/test/fixtures/jobs.yml +7 -0
- data/test/fixtures/members.yml +4 -0
- data/test/fixtures/memberships.yml +20 -0
- data/test/fixtures/owners.yml +7 -0
- data/test/fixtures/people.yml +4 -1
- data/test/fixtures/pets.yml +14 -0
- data/test/fixtures/posts.yml +1 -0
- data/test/fixtures/price_estimates.yml +7 -0
- data/test/fixtures/readers.yml +5 -0
- data/test/fixtures/references.yml +17 -0
- data/test/fixtures/sponsors.yml +9 -0
- data/test/fixtures/subscribers.yml +7 -0
- data/test/fixtures/subscriptions.yml +12 -0
- data/test/fixtures/taggings.yml +4 -1
- data/test/fixtures/topics.yml +22 -2
- data/test/fixtures/warehouse-things.yml +3 -0
- data/test/{fixtures/migrations_with_decimal → migrations/decimal}/1_give_me_big_numbers.rb +0 -0
- data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/1_people_have_last_names.rb +1 -1
- data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/2_we_need_reminders.rb +1 -1
- data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/3_foo.rb +0 -0
- data/test/{fixtures/migrations → migrations/duplicate}/3_innocent_jointable.rb +0 -0
- data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
- data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
- data/test/{fixtures/migrations_with_duplicate → migrations/interleaved/pass_1}/3_innocent_jointable.rb +0 -0
- data/test/{fixtures/migrations → migrations/interleaved/pass_2}/1_people_have_last_names.rb +1 -1
- data/test/{fixtures/migrations_with_missing_versions/4_innocent_jointable.rb → migrations/interleaved/pass_2/3_innocent_jointable.rb} +0 -0
- data/test/{fixtures/migrations_with_missing_versions → migrations/interleaved/pass_3}/1_people_have_last_names.rb +1 -1
- data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +8 -0
- data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +12 -0
- data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/1000_people_have_middle_names.rb +1 -1
- data/test/migrations/missing/1_people_have_last_names.rb +9 -0
- data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/3_we_need_reminders.rb +1 -1
- data/test/migrations/missing/4_innocent_jointable.rb +12 -0
- data/test/migrations/valid/1_people_have_last_names.rb +9 -0
- data/test/{fixtures/migrations → migrations/valid}/2_we_need_reminders.rb +1 -1
- data/test/migrations/valid/3_innocent_jointable.rb +12 -0
- data/test/{fixtures → models}/author.rb +28 -4
- data/test/{fixtures → models}/auto_id.rb +0 -0
- data/test/{fixtures → models}/binary.rb +0 -0
- data/test/{fixtures → models}/book.rb +0 -0
- data/test/{fixtures → models}/categorization.rb +0 -0
- data/test/{fixtures → models}/category.rb +8 -5
- data/test/{fixtures → models}/citation.rb +0 -0
- data/test/models/club.rb +7 -0
- data/test/{fixtures → models}/column_name.rb +0 -0
- data/test/{fixtures → models}/comment.rb +5 -3
- data/test/{fixtures → models}/company.rb +15 -6
- data/test/{fixtures → models}/company_in_module.rb +5 -3
- data/test/{fixtures → models}/computer.rb +0 -1
- data/test/{fixtures → models}/contact.rb +1 -1
- data/test/{fixtures → models}/course.rb +0 -0
- data/test/{fixtures → models}/customer.rb +8 -8
- data/test/{fixtures → models}/default.rb +0 -0
- data/test/{fixtures → models}/developer.rb +14 -10
- data/test/{fixtures → models}/edge.rb +0 -0
- data/test/{fixtures → models}/entrant.rb +0 -0
- data/test/models/guid.rb +2 -0
- data/test/{fixtures → models}/item.rb +0 -0
- data/test/models/job.rb +5 -0
- data/test/{fixtures → models}/joke.rb +0 -0
- data/test/{fixtures → models}/keyboard.rb +0 -0
- data/test/{fixtures → models}/legacy_thing.rb +0 -0
- data/test/{fixtures → models}/matey.rb +0 -0
- data/test/models/member.rb +9 -0
- data/test/models/membership.rb +9 -0
- data/test/{fixtures → models}/minimalistic.rb +0 -0
- data/test/{fixtures → models}/mixed_case_monkey.rb +0 -0
- data/test/{fixtures → models}/movie.rb +0 -0
- data/test/{fixtures → models}/order.rb +2 -2
- data/test/models/owner.rb +4 -0
- data/test/{fixtures → models}/parrot.rb +0 -0
- data/test/models/person.rb +10 -0
- data/test/models/pet.rb +4 -0
- data/test/models/pirate.rb +9 -0
- data/test/{fixtures → models}/post.rb +23 -2
- data/test/models/price_estimate.rb +3 -0
- data/test/{fixtures → models}/project.rb +1 -0
- data/test/{fixtures → models}/reader.rb +0 -0
- data/test/models/reference.rb +4 -0
- data/test/{fixtures → models}/reply.rb +7 -5
- data/test/{fixtures → models}/ship.rb +0 -0
- data/test/models/sponsor.rb +4 -0
- data/test/{fixtures → models}/subject.rb +0 -0
- data/test/{fixtures → models}/subscriber.rb +2 -0
- data/test/models/subscription.rb +4 -0
- data/test/{fixtures → models}/tag.rb +0 -0
- data/test/{fixtures → models}/tagging.rb +0 -0
- data/test/{fixtures → models}/task.rb +0 -0
- data/test/{fixtures → models}/topic.rb +32 -4
- data/test/{fixtures → models}/treasure.rb +2 -0
- data/test/{fixtures → models}/vertex.rb +0 -0
- data/test/models/warehouse_thing.rb +5 -0
- data/test/schema/mysql_specific_schema.rb +12 -0
- data/test/schema/postgresql_specific_schema.rb +103 -0
- data/test/schema/schema.rb +421 -0
- data/test/schema/schema2.rb +6 -0
- data/test/schema/sqlite_specific_schema.rb +25 -0
- data/test/schema/sqlserver_specific_schema.rb +5 -0
- metadata +192 -176
- data/test/aaa_create_tables_test.rb +0 -72
- data/test/abstract_unit.rb +0 -84
- data/test/active_schema_test_mysql.rb +0 -46
- data/test/all.sh +0 -8
- data/test/association_inheritance_reload.rb +0 -14
- data/test/associations_test.rb +0 -2177
- data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +0 -1
- data/test/fixtures/bad_fixtures/attr_with_spaces +0 -1
- data/test/fixtures/bad_fixtures/blank_line +0 -3
- data/test/fixtures/bad_fixtures/duplicate_attributes +0 -3
- data/test/fixtures/bad_fixtures/missing_value +0 -1
- data/test/fixtures/db_definitions/db2.drop.sql +0 -33
- data/test/fixtures/db_definitions/db2.sql +0 -235
- data/test/fixtures/db_definitions/db22.drop.sql +0 -2
- data/test/fixtures/db_definitions/db22.sql +0 -5
- data/test/fixtures/db_definitions/firebird.drop.sql +0 -65
- data/test/fixtures/db_definitions/firebird.sql +0 -310
- data/test/fixtures/db_definitions/firebird2.drop.sql +0 -2
- data/test/fixtures/db_definitions/firebird2.sql +0 -6
- data/test/fixtures/db_definitions/frontbase.drop.sql +0 -33
- data/test/fixtures/db_definitions/frontbase.sql +0 -273
- data/test/fixtures/db_definitions/frontbase2.drop.sql +0 -1
- data/test/fixtures/db_definitions/frontbase2.sql +0 -4
- data/test/fixtures/db_definitions/openbase.drop.sql +0 -2
- data/test/fixtures/db_definitions/openbase.sql +0 -318
- data/test/fixtures/db_definitions/openbase2.drop.sql +0 -2
- data/test/fixtures/db_definitions/openbase2.sql +0 -7
- data/test/fixtures/db_definitions/oracle.drop.sql +0 -67
- data/test/fixtures/db_definitions/oracle.sql +0 -330
- data/test/fixtures/db_definitions/oracle2.drop.sql +0 -2
- data/test/fixtures/db_definitions/oracle2.sql +0 -6
- data/test/fixtures/db_definitions/postgresql.drop.sql +0 -44
- data/test/fixtures/db_definitions/postgresql.sql +0 -292
- data/test/fixtures/db_definitions/postgresql2.drop.sql +0 -2
- data/test/fixtures/db_definitions/postgresql2.sql +0 -4
- data/test/fixtures/db_definitions/schema.rb +0 -354
- data/test/fixtures/db_definitions/schema2.rb +0 -11
- data/test/fixtures/db_definitions/sqlite.drop.sql +0 -33
- data/test/fixtures/db_definitions/sqlite.sql +0 -219
- data/test/fixtures/db_definitions/sqlite2.drop.sql +0 -2
- data/test/fixtures/db_definitions/sqlite2.sql +0 -5
- data/test/fixtures/db_definitions/sybase.drop.sql +0 -35
- data/test/fixtures/db_definitions/sybase.sql +0 -222
- data/test/fixtures/db_definitions/sybase2.drop.sql +0 -4
- data/test/fixtures/db_definitions/sybase2.sql +0 -5
- data/test/fixtures/developers_projects/david_action_controller +0 -3
- data/test/fixtures/developers_projects/david_active_record +0 -3
- data/test/fixtures/developers_projects/jamis_active_record +0 -2
- data/test/fixtures/person.rb +0 -4
- data/test/fixtures/pirate.rb +0 -5
- data/test/fixtures/subscribers/first +0 -2
- data/test/fixtures/subscribers/second +0 -2
- data/test/schema_dumper_test.rb +0 -131
- data/test/schema_test_postgresql.rb +0 -64
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'erb'
|
2
2
|
require 'yaml'
|
3
3
|
require 'csv'
|
4
|
+
require 'active_support/test_case'
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
if RUBY_VERSION < '1.9'
|
7
|
+
module YAML #:nodoc:
|
8
|
+
class Omap #:nodoc:
|
9
|
+
def keys; map { |k, v| k } end
|
10
|
+
def values; map { |k, v| v } end
|
11
|
+
end
|
9
12
|
end
|
10
13
|
end
|
11
14
|
|
@@ -29,9 +32,9 @@ end
|
|
29
32
|
# in a non-verbose, human-readable format. It ships with Ruby 1.8.1+.
|
30
33
|
#
|
31
34
|
# Unlike single-file fixtures, YAML fixtures are stored in a single file per model, which are placed in the directory appointed
|
32
|
-
# by <tt>
|
33
|
-
# put your files in <your-rails-app>/test/fixtures
|
34
|
-
#
|
35
|
+
# by <tt>ActiveSupport::TestCase.fixture_path=(path)</tt> (this is automatically configured for Rails, so you can just
|
36
|
+
# put your files in <tt><your-rails-app>/test/fixtures/</tt>). The fixture file ends with the <tt>.yml</tt> file extension (Rails example:
|
37
|
+
# <tt><your-rails-app>/test/fixtures/web_sites.yml</tt>). The format of a YAML fixture file looks like this:
|
35
38
|
#
|
36
39
|
# rubyonrails:
|
37
40
|
# id: 1
|
@@ -64,7 +67,8 @@ end
|
|
64
67
|
# = CSV fixtures
|
65
68
|
#
|
66
69
|
# Fixtures can also be kept in the Comma Separated Value format. Akin to YAML fixtures, CSV fixtures are stored
|
67
|
-
# in a single file, but instead end with the
|
70
|
+
# in a single file, but instead end with the <tt>.csv</tt> file extension
|
71
|
+
# (Rails example: <tt><your-rails-app>/test/fixtures/web_sites.csv</tt>).
|
68
72
|
#
|
69
73
|
# The format of this type of fixture file is much more compact than the others, but also a little harder to read by us
|
70
74
|
# humans. The first line of the CSV file is a comma-separated list of field names. The rest of the file is then comprised
|
@@ -89,12 +93,12 @@ end
|
|
89
93
|
#
|
90
94
|
# This type of fixture was the original format for Active Record that has since been deprecated in favor of the YAML and CSV formats.
|
91
95
|
# Fixtures for this format are created by placing text files in a sub-directory (with the name of the model) to the directory
|
92
|
-
# appointed by <tt>
|
93
|
-
# put your files in <your-rails-app>/test/fixtures/<your-model-name
|
94
|
-
# model).
|
96
|
+
# appointed by <tt>ActiveSupport::TestCase.fixture_path=(path)</tt> (this is automatically configured for Rails, so you can just
|
97
|
+
# put your files in <tt><your-rails-app>/test/fixtures/<your-model-name>/</tt> --
|
98
|
+
# like <tt><your-rails-app>/test/fixtures/web_sites/</tt> for the WebSite model).
|
95
99
|
#
|
96
100
|
# Each text file placed in this directory represents a "record". Usually these types of fixtures are named without
|
97
|
-
# extensions, but if you are on a Windows machine, you might consider adding
|
101
|
+
# extensions, but if you are on a Windows machine, you might consider adding <tt>.txt</tt> as the extension. Here's what the
|
98
102
|
# above example might look like:
|
99
103
|
#
|
100
104
|
# web_sites/google
|
@@ -115,7 +119,7 @@ end
|
|
115
119
|
#
|
116
120
|
# require 'web_site'
|
117
121
|
#
|
118
|
-
# class WebSiteTest <
|
122
|
+
# class WebSiteTest < ActiveSupport::TestCase
|
119
123
|
# def test_web_site_count
|
120
124
|
# assert_equal 2, WebSite.count
|
121
125
|
# end
|
@@ -125,7 +129,7 @@ end
|
|
125
129
|
# easiest way to add fixtures to the database:
|
126
130
|
#
|
127
131
|
# ...
|
128
|
-
# class WebSiteTest <
|
132
|
+
# class WebSiteTest < ActiveSupport::TestCase
|
129
133
|
# fixtures :web_sites # add more by separating the symbols with commas
|
130
134
|
# ...
|
131
135
|
#
|
@@ -135,20 +139,20 @@ end
|
|
135
139
|
#
|
136
140
|
# In addition to being available in the database, the fixtures are also loaded into a hash stored in an instance variable
|
137
141
|
# of the test case. It is named after the symbol... so, in our example, there would be a hash available called
|
138
|
-
#
|
142
|
+
# <tt>@web_sites</tt>. This is where the "fixture name" comes into play.
|
139
143
|
#
|
140
|
-
# On top of that, each record is automatically "found" (using Model.find(id)) and placed in the instance variable of its name.
|
141
|
-
# So for the YAML fixtures, we'd get
|
144
|
+
# On top of that, each record is automatically "found" (using <tt>Model.find(id)</tt>) and placed in the instance variable of its name.
|
145
|
+
# So for the YAML fixtures, we'd get <tt>@rubyonrails</tt> and <tt>@google</tt>, which could be interrogated using regular Active Record semantics:
|
142
146
|
#
|
143
147
|
# # test if the object created from the fixture data has the same attributes as the data itself
|
144
148
|
# def test_find
|
145
149
|
# assert_equal @web_sites["rubyonrails"]["name"], @rubyonrails.name
|
146
150
|
# end
|
147
151
|
#
|
148
|
-
# As seen above, the data hash created from the YAML fixtures would have
|
149
|
-
# "http://www.rubyonrails.org" and
|
150
|
-
# from a CSV fixture file, would be accessible via
|
151
|
-
# fixtures available as instance variables
|
152
|
+
# As seen above, the data hash created from the YAML fixtures would have <tt>@web_sites["rubyonrails"]["url"]</tt> return
|
153
|
+
# "http://www.rubyonrails.org" and <tt>@web_sites["google"]["name"]</tt> would return "Google". The same fixtures, but loaded
|
154
|
+
# from a CSV fixture file, would be accessible via <tt>@web_sites["web_site_1"]["name"] == "Ruby on Rails"</tt> and have the individual
|
155
|
+
# fixtures available as instance variables <tt>@web_site_1</tt> and <tt>@web_site_2</tt>.
|
152
156
|
#
|
153
157
|
# If you do not wish to use instantiated fixtures (usually for performance reasons) there are two options.
|
154
158
|
#
|
@@ -173,15 +177,15 @@ end
|
|
173
177
|
# Some times you don't care about the content of the fixtures as much as you care about the volume. In these cases, you can
|
174
178
|
# mix ERb in with your YAML or CSV fixtures to create a bunch of fixtures for load testing, like:
|
175
179
|
#
|
176
|
-
#
|
177
|
-
#
|
178
|
-
#
|
179
|
-
#
|
180
|
-
#
|
180
|
+
# <% for i in 1..1000 %>
|
181
|
+
# fix_<%= i %>:
|
182
|
+
# id: <%= i %>
|
183
|
+
# name: guy_<%= 1 %>
|
184
|
+
# <% end %>
|
181
185
|
#
|
182
186
|
# This will create 1000 very simple YAML fixtures.
|
183
187
|
#
|
184
|
-
# Using ERb, you can also inject dynamic values into your fixtures with inserts like
|
188
|
+
# Using ERb, you can also inject dynamic values into your fixtures with inserts like <tt><%= Date.today.strftime("%Y-%m-%d") %></tt>.
|
185
189
|
# This is however a feature to be used with some caution. The point of fixtures are that they're stable units of predictable
|
186
190
|
# sample data. If you feel that you need to inject dynamic values, then perhaps you should reexamine whether your application
|
187
191
|
# is properly testable. Hence, dynamic values in fixtures are to be considered a code smell.
|
@@ -191,23 +195,23 @@ end
|
|
191
195
|
# TestCases can use begin+rollback to isolate their changes to the database instead of having to delete+insert for every test case.
|
192
196
|
# They can also turn off auto-instantiation of fixture data since the feature is costly and often unused.
|
193
197
|
#
|
194
|
-
# class FooTest <
|
198
|
+
# class FooTest < ActiveSupport::TestCase
|
195
199
|
# self.use_transactional_fixtures = true
|
196
200
|
# self.use_instantiated_fixtures = false
|
197
|
-
#
|
201
|
+
#
|
198
202
|
# fixtures :foos
|
199
|
-
#
|
203
|
+
#
|
200
204
|
# def test_godzilla
|
201
205
|
# assert !Foo.find(:all).empty?
|
202
206
|
# Foo.destroy_all
|
203
207
|
# assert Foo.find(:all).empty?
|
204
208
|
# end
|
205
|
-
#
|
209
|
+
#
|
206
210
|
# def test_godzilla_aftermath
|
207
211
|
# assert !Foo.find(:all).empty?
|
208
212
|
# end
|
209
213
|
# end
|
210
|
-
#
|
214
|
+
#
|
211
215
|
# If you preload your test database with all fixture data (probably in the Rakefile task) and use transactional fixtures,
|
212
216
|
# then you may omit all fixtures declarations in your test cases since all the data's already there and every case rolls back its changes.
|
213
217
|
#
|
@@ -254,7 +258,7 @@ end
|
|
254
258
|
# reginald: # generated id: 324201669
|
255
259
|
# name: Reginald the Pirate
|
256
260
|
#
|
257
|
-
#
|
261
|
+
# Active Record looks at the fixture's model class, discovers the correct
|
258
262
|
# primary key, and generates it right before inserting the fixture
|
259
263
|
# into the database.
|
260
264
|
#
|
@@ -264,7 +268,7 @@ end
|
|
264
268
|
# == Label references for associations (belongs_to, has_one, has_many)
|
265
269
|
#
|
266
270
|
# Specifying foreign keys in fixtures can be very fragile, not to
|
267
|
-
# mention difficult to read. Since
|
271
|
+
# mention difficult to read. Since Active Record can figure out the ID of
|
268
272
|
# any fixture from its label, you can specify FK's by label instead of ID.
|
269
273
|
#
|
270
274
|
# === belongs_to
|
@@ -301,15 +305,15 @@ end
|
|
301
305
|
# name: George the Monkey
|
302
306
|
# pirate: reginald
|
303
307
|
#
|
304
|
-
# Pow! All is made clear.
|
308
|
+
# Pow! All is made clear. Active Record reflects on the fixture's model class,
|
305
309
|
# finds all the +belongs_to+ associations, and allows you to specify
|
306
310
|
# a target *label* for the *association* (monkey: george) rather than
|
307
|
-
# a target *id* for the *FK* (monkey_id: 1).
|
311
|
+
# a target *id* for the *FK* (<tt>monkey_id: 1</tt>).
|
308
312
|
#
|
309
313
|
# ==== Polymorphic belongs_to
|
310
314
|
#
|
311
315
|
# Supporting polymorphic relationships is a little bit more complicated, since
|
312
|
-
#
|
316
|
+
# Active Record needs to know what type your association is pointing at. Something
|
313
317
|
# like this should look familiar:
|
314
318
|
#
|
315
319
|
# ### in fruit.rb
|
@@ -329,7 +333,7 @@ end
|
|
329
333
|
# apple:
|
330
334
|
# eater: george (Monkey)
|
331
335
|
#
|
332
|
-
# Just provide the polymorphic target type and
|
336
|
+
# Just provide the polymorphic target type and Active Record will take care of the rest.
|
333
337
|
#
|
334
338
|
# === has_and_belongs_to_many
|
335
339
|
#
|
@@ -392,15 +396,15 @@ end
|
|
392
396
|
#
|
393
397
|
# Zap! No more fruits_monkeys.yml file. We've specified the list of fruits
|
394
398
|
# on George's fixture, but we could've just as easily specified a list
|
395
|
-
# of monkeys on each fruit. As with +belongs_to+,
|
399
|
+
# of monkeys on each fruit. As with +belongs_to+, Active Record reflects on
|
396
400
|
# the fixture's model class and discovers the +has_and_belongs_to_many+
|
397
401
|
# associations.
|
398
402
|
#
|
399
403
|
# == Autofilled timestamp columns
|
400
404
|
#
|
401
|
-
# If your table/model specifies any of
|
402
|
-
# standard timestamp columns (created_at
|
403
|
-
# they will automatically be set to Time.now
|
405
|
+
# If your table/model specifies any of Active Record's
|
406
|
+
# standard timestamp columns (+created_at+, +created_on+, +updated_at+, +updated_on+),
|
407
|
+
# they will automatically be set to <tt>Time.now</tt>.
|
404
408
|
#
|
405
409
|
# If you've set specific values, they'll be left alone.
|
406
410
|
#
|
@@ -423,7 +427,7 @@ end
|
|
423
427
|
# == Support for YAML defaults
|
424
428
|
#
|
425
429
|
# You probably already know how to use YAML to set and reuse defaults in
|
426
|
-
# your
|
430
|
+
# your <tt>database.yml</tt> file. You can use the same technique in your fixtures:
|
427
431
|
#
|
428
432
|
# DEFAULTS: &DEFAULTS
|
429
433
|
# created_on: <%= 3.weeks.ago.to_s(:db) %>
|
@@ -466,8 +470,8 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
|
|
466
470
|
fixtures.size > 1 ? fixtures : fixtures.first
|
467
471
|
end
|
468
472
|
|
469
|
-
def self.cache_fixtures(connection,
|
470
|
-
cache_for_connection(connection).update(
|
473
|
+
def self.cache_fixtures(connection, fixtures_map)
|
474
|
+
cache_for_connection(connection).update(fixtures_map)
|
471
475
|
end
|
472
476
|
|
473
477
|
def self.instantiate_fixtures(object, table_name, fixtures, load_instances = true)
|
@@ -523,7 +527,7 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
|
|
523
527
|
end
|
524
528
|
end
|
525
529
|
|
526
|
-
cache_fixtures(connection,
|
530
|
+
cache_fixtures(connection, fixtures_map)
|
527
531
|
end
|
528
532
|
end
|
529
533
|
end
|
@@ -558,7 +562,11 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
|
|
558
562
|
now = now.to_s(:db)
|
559
563
|
|
560
564
|
# allow a standard key to be used for doing defaults in YAML
|
561
|
-
|
565
|
+
if is_a?(Hash)
|
566
|
+
delete('DEFAULTS')
|
567
|
+
else
|
568
|
+
delete(assoc('DEFAULTS'))
|
569
|
+
end
|
562
570
|
|
563
571
|
# track any join tables we need to insert later
|
564
572
|
habtm_fixtures = Hash.new do |h, habtm|
|
@@ -684,14 +692,6 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
|
|
684
692
|
read_yaml_fixture_files
|
685
693
|
elsif File.file?(csv_file_path)
|
686
694
|
read_csv_fixture_files
|
687
|
-
else
|
688
|
-
# Standard fixtures
|
689
|
-
Dir.entries(@fixture_path).each do |file|
|
690
|
-
path = File.join(@fixture_path, file)
|
691
|
-
if File.file?(path) and file !~ @file_filter
|
692
|
-
self[file] = Fixture.new(path, model_class)
|
693
|
-
end
|
694
|
-
end
|
695
695
|
end
|
696
696
|
end
|
697
697
|
|
@@ -712,7 +712,8 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
|
|
712
712
|
end
|
713
713
|
|
714
714
|
yaml_value.each do |fixture|
|
715
|
-
fixture
|
715
|
+
raise Fixture::FormatError, "Bad data for #{@class_name} fixture named #{fixture}" unless fixture.respond_to?(:each)
|
716
|
+
fixture.each do |name, data|
|
716
717
|
unless data
|
717
718
|
raise Fixture::FormatError, "Bad data for #{@class_name} fixture named #{name} (nil)"
|
718
719
|
end
|
@@ -730,7 +731,7 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
|
|
730
731
|
reader.each do |row|
|
731
732
|
data = {}
|
732
733
|
row.each_with_index { |cell, j| data[header[j].to_s.strip] = cell.to_s.strip }
|
733
|
-
self["#{
|
734
|
+
self["#{@class_name.to_s.underscore}_#{i+=1}"] = Fixture.new(data, model_class)
|
734
735
|
end
|
735
736
|
end
|
736
737
|
|
@@ -769,15 +770,7 @@ class Fixture #:nodoc:
|
|
769
770
|
attr_reader :model_class
|
770
771
|
|
771
772
|
def initialize(fixture, model_class)
|
772
|
-
|
773
|
-
when Hash, YAML::Omap
|
774
|
-
@fixture = fixture
|
775
|
-
when String
|
776
|
-
@fixture = read_fixture_file(fixture)
|
777
|
-
else
|
778
|
-
raise ArgumentError, "Bad fixture argument #{fixture.inspect} during creation of #{class_name} fixture"
|
779
|
-
end
|
780
|
-
|
773
|
+
@fixture = fixture
|
781
774
|
@model_class = model_class.is_a?(Class) ? model_class : model_class.constantize rescue nil
|
782
775
|
end
|
783
776
|
|
@@ -817,30 +810,14 @@ class Fixture #:nodoc:
|
|
817
810
|
raise FixtureClassNotFound, "No class attached to find."
|
818
811
|
end
|
819
812
|
end
|
820
|
-
|
821
|
-
private
|
822
|
-
def read_fixture_file(fixture_file_path)
|
823
|
-
IO.readlines(fixture_file_path).inject({}) do |fixture, line|
|
824
|
-
# Mercifully skip empty lines.
|
825
|
-
next if line =~ /^\s*$/
|
826
|
-
|
827
|
-
# Use the same regular expression for attributes as Active Record.
|
828
|
-
unless md = /^\s*([a-zA-Z][-_\w]*)\s*=>\s*(.+)\s*$/.match(line)
|
829
|
-
raise FormatError, "#{fixture_file_path}: fixture format error at '#{line}'. Expecting 'key => value'."
|
830
|
-
end
|
831
|
-
key, value = md.captures
|
832
|
-
|
833
|
-
# Disallow duplicate keys to catch typos.
|
834
|
-
raise FormatError, "#{fixture_file_path}: duplicate '#{key}' in fixture." if fixture[key]
|
835
|
-
fixture[key] = value.strip
|
836
|
-
fixture
|
837
|
-
end
|
838
|
-
end
|
839
813
|
end
|
840
814
|
|
841
815
|
module Test #:nodoc:
|
842
816
|
module Unit #:nodoc:
|
843
817
|
class TestCase #:nodoc:
|
818
|
+
setup :setup_fixtures
|
819
|
+
teardown :teardown_fixtures
|
820
|
+
|
844
821
|
superclass_delegating_accessor :fixture_path
|
845
822
|
superclass_delegating_accessor :fixture_table_names
|
846
823
|
superclass_delegating_accessor :fixture_class_names
|
@@ -856,67 +833,78 @@ module Test #:nodoc:
|
|
856
833
|
@@already_loaded_fixtures = {}
|
857
834
|
self.fixture_class_names = {}
|
858
835
|
|
859
|
-
|
860
|
-
|
861
|
-
|
836
|
+
class << self
|
837
|
+
def set_fixture_class(class_names = {})
|
838
|
+
self.fixture_class_names = self.fixture_class_names.merge(class_names)
|
839
|
+
end
|
862
840
|
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
841
|
+
def fixtures(*table_names)
|
842
|
+
if table_names.first == :all
|
843
|
+
table_names = Dir["#{fixture_path}/*.yml"] + Dir["#{fixture_path}/*.csv"]
|
844
|
+
table_names.map! { |f| File.basename(f).split('.')[0..-2].join('.') }
|
845
|
+
else
|
846
|
+
table_names = table_names.flatten.map { |n| n.to_s }
|
847
|
+
end
|
848
|
+
|
849
|
+
self.fixture_table_names |= table_names
|
850
|
+
require_fixture_classes(table_names)
|
851
|
+
setup_fixture_accessors(table_names)
|
869
852
|
end
|
870
853
|
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
854
|
+
def try_to_load_dependency(file_name)
|
855
|
+
require_dependency file_name
|
856
|
+
rescue LoadError => e
|
857
|
+
# Let's hope the developer has included it himself
|
875
858
|
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
begin
|
881
|
-
require_dependency file_name
|
882
|
-
rescue LoadError
|
883
|
-
# Let's hope the developer has included it himself
|
859
|
+
# Let's warn in case this is a subdependency, otherwise
|
860
|
+
# subdependency error messages are totally cryptic
|
861
|
+
if ActiveRecord::Base.logger
|
862
|
+
ActiveRecord::Base.logger.warn("Unable to load #{file_name}, underlying cause #{e.message} \n\n #{e.backtrace.join("\n")}")
|
884
863
|
end
|
885
864
|
end
|
886
|
-
end
|
887
865
|
|
888
|
-
|
889
|
-
|
890
|
-
|
866
|
+
def require_fixture_classes(table_names = nil)
|
867
|
+
(table_names || fixture_table_names).each do |table_name|
|
868
|
+
file_name = table_name.to_s
|
869
|
+
file_name = file_name.singularize if ActiveRecord::Base.pluralize_table_names
|
870
|
+
try_to_load_dependency(file_name)
|
871
|
+
end
|
872
|
+
end
|
873
|
+
|
874
|
+
def setup_fixture_accessors(table_names = nil)
|
875
|
+
table_names = [table_names] if table_names && !table_names.respond_to?(:each)
|
876
|
+
(table_names || fixture_table_names).each do |table_name|
|
877
|
+
table_name = table_name.to_s.tr('.', '_')
|
891
878
|
|
892
|
-
|
893
|
-
|
879
|
+
define_method(table_name) do |*fixtures|
|
880
|
+
force_reload = fixtures.pop if fixtures.last == true || fixtures.last == :reload
|
894
881
|
|
895
|
-
|
882
|
+
@fixture_cache[table_name] ||= {}
|
896
883
|
|
897
|
-
|
898
|
-
|
884
|
+
instances = fixtures.map do |fixture|
|
885
|
+
@fixture_cache[table_name].delete(fixture) if force_reload
|
899
886
|
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
887
|
+
if @loaded_fixtures[table_name][fixture.to_s]
|
888
|
+
@fixture_cache[table_name][fixture] ||= @loaded_fixtures[table_name][fixture.to_s].find
|
889
|
+
else
|
890
|
+
raise StandardError, "No fixture with name '#{fixture}' found for table '#{table_name}'"
|
891
|
+
end
|
904
892
|
end
|
905
|
-
end
|
906
893
|
|
907
|
-
|
894
|
+
instances.size == 1 ? instances.first : instances
|
895
|
+
end
|
908
896
|
end
|
909
897
|
end
|
910
|
-
end
|
911
898
|
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
899
|
+
def uses_transaction(*methods)
|
900
|
+
@uses_transaction = [] unless defined?(@uses_transaction)
|
901
|
+
@uses_transaction.concat methods.map(&:to_s)
|
902
|
+
end
|
916
903
|
|
917
|
-
|
918
|
-
|
919
|
-
|
904
|
+
def uses_transaction?(method)
|
905
|
+
@uses_transaction = [] unless defined?(@uses_transaction)
|
906
|
+
@uses_transaction.include?(method.to_s)
|
907
|
+
end
|
920
908
|
end
|
921
909
|
|
922
910
|
def use_transactional_fixtures?
|
@@ -924,8 +912,8 @@ module Test #:nodoc:
|
|
924
912
|
!self.class.uses_transaction?(method_name)
|
925
913
|
end
|
926
914
|
|
927
|
-
def
|
928
|
-
return unless defined?(ActiveRecord
|
915
|
+
def setup_fixtures
|
916
|
+
return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
|
929
917
|
|
930
918
|
if pre_loaded_fixtures && !use_transactional_fixtures
|
931
919
|
raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
|
@@ -953,10 +941,9 @@ module Test #:nodoc:
|
|
953
941
|
# Instantiate fixtures for every test if requested.
|
954
942
|
instantiate_fixtures if use_instantiated_fixtures
|
955
943
|
end
|
956
|
-
alias_method :setup, :setup_with_fixtures
|
957
944
|
|
958
|
-
def
|
959
|
-
return unless defined?(ActiveRecord
|
945
|
+
def teardown_fixtures
|
946
|
+
return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
|
960
947
|
|
961
948
|
unless use_transactional_fixtures?
|
962
949
|
Fixtures.reset_cache
|
@@ -969,28 +956,6 @@ module Test #:nodoc:
|
|
969
956
|
end
|
970
957
|
ActiveRecord::Base.verify_active_connections!
|
971
958
|
end
|
972
|
-
alias_method :teardown, :teardown_with_fixtures
|
973
|
-
|
974
|
-
def self.method_added(method)
|
975
|
-
case method.to_s
|
976
|
-
when 'setup'
|
977
|
-
unless method_defined?(:setup_without_fixtures)
|
978
|
-
alias_method :setup_without_fixtures, :setup
|
979
|
-
define_method(:setup) do
|
980
|
-
setup_with_fixtures
|
981
|
-
setup_without_fixtures
|
982
|
-
end
|
983
|
-
end
|
984
|
-
when 'teardown'
|
985
|
-
unless method_defined?(:teardown_without_fixtures)
|
986
|
-
alias_method :teardown_without_fixtures, :teardown
|
987
|
-
define_method(:teardown) do
|
988
|
-
teardown_without_fixtures
|
989
|
-
teardown_with_fixtures
|
990
|
-
end
|
991
|
-
end
|
992
|
-
end
|
993
|
-
end
|
994
959
|
|
995
960
|
private
|
996
961
|
def load_fixtures
|