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.

Files changed (289) hide show
  1. data/CHANGELOG +168 -6
  2. data/README +27 -22
  3. data/RUNNING_UNIT_TESTS +7 -4
  4. data/Rakefile +22 -25
  5. data/lib/active_record.rb +8 -2
  6. data/lib/active_record/aggregations.rb +21 -12
  7. data/lib/active_record/association_preload.rb +277 -0
  8. data/lib/active_record/associations.rb +481 -295
  9. data/lib/active_record/associations/association_collection.rb +162 -37
  10. data/lib/active_record/associations/association_proxy.rb +71 -7
  11. data/lib/active_record/associations/belongs_to_association.rb +5 -3
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +5 -6
  13. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +12 -64
  14. data/lib/active_record/associations/has_many_association.rb +8 -73
  15. data/lib/active_record/associations/has_many_through_association.rb +68 -117
  16. data/lib/active_record/associations/has_one_association.rb +7 -5
  17. data/lib/active_record/associations/has_one_through_association.rb +28 -0
  18. data/lib/active_record/attribute_methods.rb +69 -19
  19. data/lib/active_record/base.rb +496 -275
  20. data/lib/active_record/calculations.rb +28 -21
  21. data/lib/active_record/callbacks.rb +9 -38
  22. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -2
  23. data/lib/active_record/connection_adapters/abstract/database_statements.rb +2 -2
  24. data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -0
  25. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +232 -45
  26. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +141 -27
  27. data/lib/active_record/connection_adapters/abstract_adapter.rb +9 -13
  28. data/lib/active_record/connection_adapters/mysql_adapter.rb +57 -24
  29. data/lib/active_record/connection_adapters/postgresql_adapter.rb +143 -42
  30. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
  31. data/lib/active_record/connection_adapters/sqlite_adapter.rb +18 -10
  32. data/lib/active_record/dirty.rb +158 -0
  33. data/lib/active_record/fixtures.rb +121 -156
  34. data/lib/active_record/locking/optimistic.rb +14 -11
  35. data/lib/active_record/locking/pessimistic.rb +2 -2
  36. data/lib/active_record/migration.rb +157 -77
  37. data/lib/active_record/named_scope.rb +163 -0
  38. data/lib/active_record/observer.rb +19 -5
  39. data/lib/active_record/reflection.rb +34 -14
  40. data/lib/active_record/schema.rb +7 -14
  41. data/lib/active_record/schema_dumper.rb +4 -4
  42. data/lib/active_record/serialization.rb +5 -5
  43. data/lib/active_record/serializers/json_serializer.rb +37 -28
  44. data/lib/active_record/serializers/xml_serializer.rb +52 -29
  45. data/lib/active_record/test_case.rb +36 -0
  46. data/lib/active_record/timestamp.rb +4 -4
  47. data/lib/active_record/transactions.rb +3 -3
  48. data/lib/active_record/validations.rb +182 -248
  49. data/lib/active_record/version.rb +2 -2
  50. data/test/{fixtures → assets}/example.log +0 -0
  51. data/test/{fixtures → assets}/flowers.jpg +0 -0
  52. data/test/cases/aaa_create_tables_test.rb +24 -0
  53. data/test/cases/active_schema_test_mysql.rb +95 -0
  54. data/test/cases/active_schema_test_postgresql.rb +24 -0
  55. data/test/{adapter_test.rb → cases/adapter_test.rb} +15 -14
  56. data/test/{adapter_test_sqlserver.rb → cases/adapter_test_sqlserver.rb} +95 -95
  57. data/test/{aggregations_test.rb → cases/aggregations_test.rb} +20 -20
  58. data/test/{ar_schema_test.rb → cases/ar_schema_test.rb} +6 -6
  59. data/test/cases/associations/belongs_to_associations_test.rb +412 -0
  60. data/test/{associations → cases/associations}/callbacks_test.rb +24 -10
  61. data/test/{associations → cases/associations}/cascaded_eager_loading_test.rb +18 -17
  62. data/test/cases/associations/eager_load_nested_include_test.rb +83 -0
  63. data/test/{associations → cases/associations}/eager_singularization_test.rb +5 -5
  64. data/test/{associations → cases/associations}/eager_test.rb +216 -51
  65. data/test/{associations → cases/associations}/extension_test.rb +8 -8
  66. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +684 -0
  67. data/test/cases/associations/has_many_associations_test.rb +932 -0
  68. data/test/cases/associations/has_many_through_associations_test.rb +190 -0
  69. data/test/cases/associations/has_one_associations_test.rb +323 -0
  70. data/test/cases/associations/has_one_through_associations_test.rb +74 -0
  71. data/test/{associations → cases/associations}/inner_join_association_test.rb +20 -20
  72. data/test/{associations → cases/associations}/join_model_test.rb +175 -35
  73. data/test/cases/associations_test.rb +262 -0
  74. data/test/{attribute_methods_test.rb → cases/attribute_methods_test.rb} +103 -11
  75. data/test/{base_test.rb → cases/base_test.rb} +338 -191
  76. data/test/{binary_test.rb → cases/binary_test.rb} +6 -4
  77. data/test/{calculations_test.rb → cases/calculations_test.rb} +35 -23
  78. data/test/{callbacks_test.rb → cases/callbacks_test.rb} +7 -7
  79. data/test/{class_inheritable_attributes_test.rb → cases/class_inheritable_attributes_test.rb} +3 -3
  80. data/test/{column_alias_test.rb → cases/column_alias_test.rb} +3 -3
  81. data/test/{connection_test_firebird.rb → cases/connection_test_firebird.rb} +2 -2
  82. data/test/{connection_test_mysql.rb → cases/connection_test_mysql.rb} +2 -2
  83. data/test/{copy_table_test_sqlite.rb → cases/copy_table_test_sqlite.rb} +13 -13
  84. data/test/{datatype_test_postgresql.rb → cases/datatype_test_postgresql.rb} +8 -8
  85. data/test/{date_time_test.rb → cases/date_time_test.rb} +5 -5
  86. data/test/{default_test_firebird.rb → cases/default_test_firebird.rb} +3 -3
  87. data/test/{defaults_test.rb → cases/defaults_test.rb} +8 -6
  88. data/test/{deprecated_finder_test.rb → cases/deprecated_finder_test.rb} +3 -3
  89. data/test/cases/dirty_test.rb +163 -0
  90. data/test/cases/finder_respond_to_test.rb +76 -0
  91. data/test/{finder_test.rb → cases/finder_test.rb} +266 -33
  92. data/test/{fixtures_test.rb → cases/fixtures_test.rb} +88 -72
  93. data/test/cases/helper.rb +47 -0
  94. data/test/{inheritance_test.rb → cases/inheritance_test.rb} +61 -17
  95. data/test/cases/invalid_date_test.rb +24 -0
  96. data/test/{json_serialization_test.rb → cases/json_serialization_test.rb} +36 -11
  97. data/test/{lifecycle_test.rb → cases/lifecycle_test.rb} +16 -13
  98. data/test/{locking_test.rb → cases/locking_test.rb} +17 -10
  99. data/test/{method_scoping_test.rb → cases/method_scoping_test.rb} +75 -39
  100. data/test/{migration_test.rb → cases/migration_test.rb} +420 -80
  101. data/test/{migration_test_firebird.rb → cases/migration_test_firebird.rb} +3 -3
  102. data/test/{mixin_test.rb → cases/mixin_test.rb} +7 -6
  103. data/test/{modules_test.rb → cases/modules_test.rb} +11 -6
  104. data/test/{multiple_db_test.rb → cases/multiple_db_test.rb} +5 -5
  105. data/test/cases/named_scope_test.rb +157 -0
  106. data/test/{pk_test.rb → cases/pk_test.rb} +10 -10
  107. data/test/{query_cache_test.rb → cases/query_cache_test.rb} +12 -10
  108. data/test/{readonly_test.rb → cases/readonly_test.rb} +11 -11
  109. data/test/{reflection_test.rb → cases/reflection_test.rb} +15 -14
  110. data/test/{reserved_word_test_mysql.rb → cases/reserved_word_test_mysql.rb} +4 -5
  111. data/test/{schema_authorization_test_postgresql.rb → cases/schema_authorization_test_postgresql.rb} +5 -5
  112. data/test/cases/schema_dumper_test.rb +138 -0
  113. data/test/cases/schema_test_postgresql.rb +102 -0
  114. data/test/{serialization_test.rb → cases/serialization_test.rb} +7 -7
  115. data/test/{synonym_test_oracle.rb → cases/synonym_test_oracle.rb} +5 -5
  116. data/test/{table_name_test_sqlserver.rb → cases/table_name_test_sqlserver.rb} +3 -3
  117. data/test/{threaded_connections_test.rb → cases/threaded_connections_test.rb} +7 -7
  118. data/test/{transactions_test.rb → cases/transactions_test.rb} +31 -5
  119. data/test/{unconnected_test.rb → cases/unconnected_test.rb} +2 -2
  120. data/test/{validations_test.rb → cases/validations_test.rb} +141 -39
  121. data/test/{xml_serialization_test.rb → cases/xml_serialization_test.rb} +12 -12
  122. data/test/config.rb +5 -0
  123. data/test/connections/native_db2/connection.rb +1 -1
  124. data/test/connections/native_firebird/connection.rb +1 -1
  125. data/test/connections/native_frontbase/connection.rb +1 -1
  126. data/test/connections/native_mysql/connection.rb +1 -1
  127. data/test/connections/native_openbase/connection.rb +1 -1
  128. data/test/connections/native_oracle/connection.rb +1 -1
  129. data/test/connections/native_postgresql/connection.rb +1 -3
  130. data/test/connections/native_sqlite/connection.rb +2 -2
  131. data/test/connections/native_sqlite3/connection.rb +2 -2
  132. data/test/connections/native_sqlite3/in_memory_connection.rb +3 -3
  133. data/test/connections/native_sybase/connection.rb +1 -1
  134. data/test/fixtures/author_addresses.yml +5 -0
  135. data/test/fixtures/authors.yml +2 -0
  136. data/test/fixtures/clubs.yml +6 -0
  137. data/test/fixtures/jobs.yml +7 -0
  138. data/test/fixtures/members.yml +4 -0
  139. data/test/fixtures/memberships.yml +20 -0
  140. data/test/fixtures/owners.yml +7 -0
  141. data/test/fixtures/people.yml +4 -1
  142. data/test/fixtures/pets.yml +14 -0
  143. data/test/fixtures/posts.yml +1 -0
  144. data/test/fixtures/price_estimates.yml +7 -0
  145. data/test/fixtures/readers.yml +5 -0
  146. data/test/fixtures/references.yml +17 -0
  147. data/test/fixtures/sponsors.yml +9 -0
  148. data/test/fixtures/subscribers.yml +7 -0
  149. data/test/fixtures/subscriptions.yml +12 -0
  150. data/test/fixtures/taggings.yml +4 -1
  151. data/test/fixtures/topics.yml +22 -2
  152. data/test/fixtures/warehouse-things.yml +3 -0
  153. data/test/{fixtures/migrations_with_decimal → migrations/decimal}/1_give_me_big_numbers.rb +0 -0
  154. data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/1_people_have_last_names.rb +1 -1
  155. data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/2_we_need_reminders.rb +1 -1
  156. data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/3_foo.rb +0 -0
  157. data/test/{fixtures/migrations → migrations/duplicate}/3_innocent_jointable.rb +0 -0
  158. data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
  159. data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
  160. data/test/{fixtures/migrations_with_duplicate → migrations/interleaved/pass_1}/3_innocent_jointable.rb +0 -0
  161. data/test/{fixtures/migrations → migrations/interleaved/pass_2}/1_people_have_last_names.rb +1 -1
  162. data/test/{fixtures/migrations_with_missing_versions/4_innocent_jointable.rb → migrations/interleaved/pass_2/3_innocent_jointable.rb} +0 -0
  163. data/test/{fixtures/migrations_with_missing_versions → migrations/interleaved/pass_3}/1_people_have_last_names.rb +1 -1
  164. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +8 -0
  165. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +12 -0
  166. data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/1000_people_have_middle_names.rb +1 -1
  167. data/test/migrations/missing/1_people_have_last_names.rb +9 -0
  168. data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/3_we_need_reminders.rb +1 -1
  169. data/test/migrations/missing/4_innocent_jointable.rb +12 -0
  170. data/test/migrations/valid/1_people_have_last_names.rb +9 -0
  171. data/test/{fixtures/migrations → migrations/valid}/2_we_need_reminders.rb +1 -1
  172. data/test/migrations/valid/3_innocent_jointable.rb +12 -0
  173. data/test/{fixtures → models}/author.rb +28 -4
  174. data/test/{fixtures → models}/auto_id.rb +0 -0
  175. data/test/{fixtures → models}/binary.rb +0 -0
  176. data/test/{fixtures → models}/book.rb +0 -0
  177. data/test/{fixtures → models}/categorization.rb +0 -0
  178. data/test/{fixtures → models}/category.rb +8 -5
  179. data/test/{fixtures → models}/citation.rb +0 -0
  180. data/test/models/club.rb +7 -0
  181. data/test/{fixtures → models}/column_name.rb +0 -0
  182. data/test/{fixtures → models}/comment.rb +5 -3
  183. data/test/{fixtures → models}/company.rb +15 -6
  184. data/test/{fixtures → models}/company_in_module.rb +5 -3
  185. data/test/{fixtures → models}/computer.rb +0 -1
  186. data/test/{fixtures → models}/contact.rb +1 -1
  187. data/test/{fixtures → models}/course.rb +0 -0
  188. data/test/{fixtures → models}/customer.rb +8 -8
  189. data/test/{fixtures → models}/default.rb +0 -0
  190. data/test/{fixtures → models}/developer.rb +14 -10
  191. data/test/{fixtures → models}/edge.rb +0 -0
  192. data/test/{fixtures → models}/entrant.rb +0 -0
  193. data/test/models/guid.rb +2 -0
  194. data/test/{fixtures → models}/item.rb +0 -0
  195. data/test/models/job.rb +5 -0
  196. data/test/{fixtures → models}/joke.rb +0 -0
  197. data/test/{fixtures → models}/keyboard.rb +0 -0
  198. data/test/{fixtures → models}/legacy_thing.rb +0 -0
  199. data/test/{fixtures → models}/matey.rb +0 -0
  200. data/test/models/member.rb +9 -0
  201. data/test/models/membership.rb +9 -0
  202. data/test/{fixtures → models}/minimalistic.rb +0 -0
  203. data/test/{fixtures → models}/mixed_case_monkey.rb +0 -0
  204. data/test/{fixtures → models}/movie.rb +0 -0
  205. data/test/{fixtures → models}/order.rb +2 -2
  206. data/test/models/owner.rb +4 -0
  207. data/test/{fixtures → models}/parrot.rb +0 -0
  208. data/test/models/person.rb +10 -0
  209. data/test/models/pet.rb +4 -0
  210. data/test/models/pirate.rb +9 -0
  211. data/test/{fixtures → models}/post.rb +23 -2
  212. data/test/models/price_estimate.rb +3 -0
  213. data/test/{fixtures → models}/project.rb +1 -0
  214. data/test/{fixtures → models}/reader.rb +0 -0
  215. data/test/models/reference.rb +4 -0
  216. data/test/{fixtures → models}/reply.rb +7 -5
  217. data/test/{fixtures → models}/ship.rb +0 -0
  218. data/test/models/sponsor.rb +4 -0
  219. data/test/{fixtures → models}/subject.rb +0 -0
  220. data/test/{fixtures → models}/subscriber.rb +2 -0
  221. data/test/models/subscription.rb +4 -0
  222. data/test/{fixtures → models}/tag.rb +0 -0
  223. data/test/{fixtures → models}/tagging.rb +0 -0
  224. data/test/{fixtures → models}/task.rb +0 -0
  225. data/test/{fixtures → models}/topic.rb +32 -4
  226. data/test/{fixtures → models}/treasure.rb +2 -0
  227. data/test/{fixtures → models}/vertex.rb +0 -0
  228. data/test/models/warehouse_thing.rb +5 -0
  229. data/test/schema/mysql_specific_schema.rb +12 -0
  230. data/test/schema/postgresql_specific_schema.rb +103 -0
  231. data/test/schema/schema.rb +421 -0
  232. data/test/schema/schema2.rb +6 -0
  233. data/test/schema/sqlite_specific_schema.rb +25 -0
  234. data/test/schema/sqlserver_specific_schema.rb +5 -0
  235. metadata +192 -176
  236. data/test/aaa_create_tables_test.rb +0 -72
  237. data/test/abstract_unit.rb +0 -84
  238. data/test/active_schema_test_mysql.rb +0 -46
  239. data/test/all.sh +0 -8
  240. data/test/association_inheritance_reload.rb +0 -14
  241. data/test/associations_test.rb +0 -2177
  242. data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +0 -1
  243. data/test/fixtures/bad_fixtures/attr_with_spaces +0 -1
  244. data/test/fixtures/bad_fixtures/blank_line +0 -3
  245. data/test/fixtures/bad_fixtures/duplicate_attributes +0 -3
  246. data/test/fixtures/bad_fixtures/missing_value +0 -1
  247. data/test/fixtures/db_definitions/db2.drop.sql +0 -33
  248. data/test/fixtures/db_definitions/db2.sql +0 -235
  249. data/test/fixtures/db_definitions/db22.drop.sql +0 -2
  250. data/test/fixtures/db_definitions/db22.sql +0 -5
  251. data/test/fixtures/db_definitions/firebird.drop.sql +0 -65
  252. data/test/fixtures/db_definitions/firebird.sql +0 -310
  253. data/test/fixtures/db_definitions/firebird2.drop.sql +0 -2
  254. data/test/fixtures/db_definitions/firebird2.sql +0 -6
  255. data/test/fixtures/db_definitions/frontbase.drop.sql +0 -33
  256. data/test/fixtures/db_definitions/frontbase.sql +0 -273
  257. data/test/fixtures/db_definitions/frontbase2.drop.sql +0 -1
  258. data/test/fixtures/db_definitions/frontbase2.sql +0 -4
  259. data/test/fixtures/db_definitions/openbase.drop.sql +0 -2
  260. data/test/fixtures/db_definitions/openbase.sql +0 -318
  261. data/test/fixtures/db_definitions/openbase2.drop.sql +0 -2
  262. data/test/fixtures/db_definitions/openbase2.sql +0 -7
  263. data/test/fixtures/db_definitions/oracle.drop.sql +0 -67
  264. data/test/fixtures/db_definitions/oracle.sql +0 -330
  265. data/test/fixtures/db_definitions/oracle2.drop.sql +0 -2
  266. data/test/fixtures/db_definitions/oracle2.sql +0 -6
  267. data/test/fixtures/db_definitions/postgresql.drop.sql +0 -44
  268. data/test/fixtures/db_definitions/postgresql.sql +0 -292
  269. data/test/fixtures/db_definitions/postgresql2.drop.sql +0 -2
  270. data/test/fixtures/db_definitions/postgresql2.sql +0 -4
  271. data/test/fixtures/db_definitions/schema.rb +0 -354
  272. data/test/fixtures/db_definitions/schema2.rb +0 -11
  273. data/test/fixtures/db_definitions/sqlite.drop.sql +0 -33
  274. data/test/fixtures/db_definitions/sqlite.sql +0 -219
  275. data/test/fixtures/db_definitions/sqlite2.drop.sql +0 -2
  276. data/test/fixtures/db_definitions/sqlite2.sql +0 -5
  277. data/test/fixtures/db_definitions/sybase.drop.sql +0 -35
  278. data/test/fixtures/db_definitions/sybase.sql +0 -222
  279. data/test/fixtures/db_definitions/sybase2.drop.sql +0 -4
  280. data/test/fixtures/db_definitions/sybase2.sql +0 -5
  281. data/test/fixtures/developers_projects/david_action_controller +0 -3
  282. data/test/fixtures/developers_projects/david_active_record +0 -3
  283. data/test/fixtures/developers_projects/jamis_active_record +0 -2
  284. data/test/fixtures/person.rb +0 -4
  285. data/test/fixtures/pirate.rb +0 -5
  286. data/test/fixtures/subscribers/first +0 -2
  287. data/test/fixtures/subscribers/second +0 -2
  288. data/test/schema_dumper_test.rb +0 -131
  289. 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
- module YAML #:nodoc:
6
- class Omap #:nodoc:
7
- def keys; map { |k, v| k } end
8
- def values; map { |k, v| v } end
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>Test::Unit::TestCase.fixture_path=(path)</tt> (this is automatically configured for Rails, so you can just
33
- # put your files in <your-rails-app>/test/fixtures/). The fixture file ends with the .yml file extension (Rails example:
34
- # "<your-rails-app>/test/fixtures/web_sites.yml"). The format of a YAML fixture file looks like this:
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 .csv file extension (Rails example: "<your-rails-app>/test/fixtures/web_sites.csv")
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>Test::Unit::TestCase.fixture_path=(path)</tt> (this is automatically configured for Rails, so you can just
93
- # put your files in <your-rails-app>/test/fixtures/<your-model-name>/ -- like <your-rails-app>/test/fixtures/web_sites/ for the WebSite
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 .txt as the extension. Here's what the
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 < Test::Unit::TestCase
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 < Test::Unit::TestCase
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
- # @web_sites. This is where the "fixture name" comes into play.
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 @rubyonrails and @google, which could be interrogated using regular Active Record semantics:
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 @web_sites["rubyonrails"]["url"] return
149
- # "http://www.rubyonrails.org" and @web_sites["google"]["name"] would return "Google". The same fixtures, but loaded
150
- # from a CSV fixture file, would be accessible via @web_sites["web_site_1"]["name"] == "Ruby on Rails" and have the individual
151
- # fixtures available as instance variables @web_site_1 and @web_site_2.
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
- # <% for i in 1..1000 %>
177
- # fix_<%= i %>:
178
- # id: <%= i %>
179
- # name: guy_<%= 1 %>
180
- # <% end %>
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 <%= Date.today.strftime("%Y-%m-%d") %>.
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 < Test::Unit::TestCase
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
- # ActiveRecord looks at the fixture's model class, discovers the correct
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 ActiveRecord can figure out the ID of
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. ActiveRecord reflects on the fixture's model class,
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
- # ActiveRecord needs to know what type your association is pointing at. Something
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 ActiveRecord will take care of the rest.
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+, ActiveRecord reflects on
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 ActiveRecord's
402
- # standard timestamp columns (created_at, created_on, updated_at, updated_on),
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 +database.yml+ file,. You can use the same technique in your fixtures:
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, fixtures)
470
- cache_for_connection(connection).update(fixtures.index_by { |f| f.table_name })
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, fixtures)
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
- delete(assoc("DEFAULTS"))
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.each do |name, data|
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["#{Inflector::underscore(@class_name)}_#{i+=1}"] = Fixture.new(data, model_class)
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
- case fixture
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
- def self.set_fixture_class(class_names = {})
860
- self.fixture_class_names = self.fixture_class_names.merge(class_names)
861
- end
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
- def self.fixtures(*table_names)
864
- if table_names.first == :all
865
- table_names = Dir["#{fixture_path}/*.yml"] + Dir["#{fixture_path}/*.csv"]
866
- table_names.map! { |f| File.basename(f).split('.')[0..-2].join('.') }
867
- else
868
- table_names = table_names.flatten.map { |n| n.to_s }
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
- self.fixture_table_names |= table_names
872
- require_fixture_classes(table_names)
873
- setup_fixture_accessors(table_names)
874
- end
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
- def self.require_fixture_classes(table_names = nil)
877
- (table_names || fixture_table_names).each do |table_name|
878
- file_name = table_name.to_s
879
- file_name = file_name.singularize if ActiveRecord::Base.pluralize_table_names
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
- def self.setup_fixture_accessors(table_names = nil)
889
- (table_names || fixture_table_names).each do |table_name|
890
- table_name = table_name.to_s.tr('.', '_')
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
- define_method(table_name) do |*fixtures|
893
- force_reload = fixtures.pop if fixtures.last == true || fixtures.last == :reload
879
+ define_method(table_name) do |*fixtures|
880
+ force_reload = fixtures.pop if fixtures.last == true || fixtures.last == :reload
894
881
 
895
- @fixture_cache[table_name] ||= {}
882
+ @fixture_cache[table_name] ||= {}
896
883
 
897
- instances = fixtures.map do |fixture|
898
- @fixture_cache[table_name].delete(fixture) if force_reload
884
+ instances = fixtures.map do |fixture|
885
+ @fixture_cache[table_name].delete(fixture) if force_reload
899
886
 
900
- if @loaded_fixtures[table_name][fixture.to_s]
901
- @fixture_cache[table_name][fixture] ||= @loaded_fixtures[table_name][fixture.to_s].find
902
- else
903
- raise StandardError, "No fixture with name '#{fixture}' found for table '#{table_name}'"
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
- instances.size == 1 ? instances.first : instances
894
+ instances.size == 1 ? instances.first : instances
895
+ end
908
896
  end
909
897
  end
910
- end
911
898
 
912
- def self.uses_transaction(*methods)
913
- @uses_transaction = [] unless defined?(@uses_transaction)
914
- @uses_transaction.concat methods.map(&:to_s)
915
- end
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
- def self.uses_transaction?(method)
918
- @uses_transaction = [] unless defined?(@uses_transaction)
919
- @uses_transaction.include?(method.to_s)
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 setup_with_fixtures
928
- return unless defined?(ActiveRecord::Base) && !ActiveRecord::Base.configurations.blank?
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 teardown_with_fixtures
959
- return unless defined?(ActiveRecord::Base) && !ActiveRecord::Base.configurations.blank?
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