activerecord 2.3.18 → 3.2.22

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 (454) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1014 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +222 -0
  5. data/examples/performance.rb +100 -126
  6. data/examples/simple.rb +14 -0
  7. data/lib/active_record/aggregations.rb +93 -99
  8. data/lib/active_record/associations/alias_tracker.rb +76 -0
  9. data/lib/active_record/associations/association.rb +247 -0
  10. data/lib/active_record/associations/association_scope.rb +134 -0
  11. data/lib/active_record/associations/belongs_to_association.rb +54 -61
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +17 -59
  13. data/lib/active_record/associations/builder/association.rb +55 -0
  14. data/lib/active_record/associations/builder/belongs_to.rb +88 -0
  15. data/lib/active_record/associations/builder/collection_association.rb +75 -0
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -0
  17. data/lib/active_record/associations/builder/has_many.rb +71 -0
  18. data/lib/active_record/associations/builder/has_one.rb +62 -0
  19. data/lib/active_record/associations/builder/singular_association.rb +32 -0
  20. data/lib/active_record/associations/collection_association.rb +580 -0
  21. data/lib/active_record/associations/collection_proxy.rb +133 -0
  22. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +39 -119
  23. data/lib/active_record/associations/has_many_association.rb +60 -79
  24. data/lib/active_record/associations/has_many_through_association.rb +127 -206
  25. data/lib/active_record/associations/has_one_association.rb +55 -114
  26. data/lib/active_record/associations/has_one_through_association.rb +25 -26
  27. data/lib/active_record/associations/join_dependency/join_association.rb +159 -0
  28. data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
  29. data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
  30. data/lib/active_record/associations/join_dependency.rb +214 -0
  31. data/lib/active_record/associations/join_helper.rb +55 -0
  32. data/lib/active_record/associations/preloader/association.rb +125 -0
  33. data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
  34. data/lib/active_record/associations/preloader/collection_association.rb +24 -0
  35. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
  36. data/lib/active_record/associations/preloader/has_many.rb +17 -0
  37. data/lib/active_record/associations/preloader/has_many_through.rb +15 -0
  38. data/lib/active_record/associations/preloader/has_one.rb +23 -0
  39. data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
  40. data/lib/active_record/associations/preloader/singular_association.rb +21 -0
  41. data/lib/active_record/associations/preloader/through_association.rb +67 -0
  42. data/lib/active_record/associations/preloader.rb +181 -0
  43. data/lib/active_record/associations/singular_association.rb +64 -0
  44. data/lib/active_record/associations/through_association.rb +87 -0
  45. data/lib/active_record/associations.rb +693 -1337
  46. data/lib/active_record/attribute_assignment.rb +221 -0
  47. data/lib/active_record/attribute_methods/before_type_cast.rb +31 -0
  48. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +32 -0
  49. data/lib/active_record/attribute_methods/dirty.rb +111 -0
  50. data/lib/active_record/attribute_methods/primary_key.rb +114 -0
  51. data/lib/active_record/attribute_methods/query.rb +39 -0
  52. data/lib/active_record/attribute_methods/read.rb +136 -0
  53. data/lib/active_record/attribute_methods/serialization.rb +120 -0
  54. data/lib/active_record/attribute_methods/time_zone_conversion.rb +65 -0
  55. data/lib/active_record/attribute_methods/write.rb +70 -0
  56. data/lib/active_record/attribute_methods.rb +211 -339
  57. data/lib/active_record/autosave_association.rb +179 -149
  58. data/lib/active_record/base.rb +401 -2907
  59. data/lib/active_record/callbacks.rb +91 -176
  60. data/lib/active_record/coders/yaml_column.rb +41 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +236 -119
  62. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +110 -58
  63. data/lib/active_record/connection_adapters/abstract/database_limits.rb +12 -11
  64. data/lib/active_record/connection_adapters/abstract/database_statements.rb +175 -74
  65. data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -35
  66. data/lib/active_record/connection_adapters/abstract/quoting.rb +71 -21
  67. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +81 -311
  68. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +194 -78
  69. data/lib/active_record/connection_adapters/abstract_adapter.rb +130 -83
  70. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +676 -0
  71. data/lib/active_record/connection_adapters/column.rb +296 -0
  72. data/lib/active_record/connection_adapters/mysql2_adapter.rb +280 -0
  73. data/lib/active_record/connection_adapters/mysql_adapter.rb +272 -493
  74. data/lib/active_record/connection_adapters/postgresql_adapter.rb +650 -405
  75. data/lib/active_record/connection_adapters/schema_cache.rb +69 -0
  76. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +30 -9
  77. data/lib/active_record/connection_adapters/sqlite_adapter.rb +276 -147
  78. data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
  79. data/lib/active_record/counter_cache.rb +123 -0
  80. data/lib/active_record/dynamic_finder_match.rb +41 -14
  81. data/lib/active_record/dynamic_matchers.rb +84 -0
  82. data/lib/active_record/dynamic_scope_match.rb +13 -15
  83. data/lib/active_record/errors.rb +195 -0
  84. data/lib/active_record/explain.rb +86 -0
  85. data/lib/active_record/explain_subscriber.rb +25 -0
  86. data/lib/active_record/fixtures/file.rb +65 -0
  87. data/lib/active_record/fixtures.rb +695 -770
  88. data/lib/active_record/identity_map.rb +162 -0
  89. data/lib/active_record/inheritance.rb +174 -0
  90. data/lib/active_record/integration.rb +60 -0
  91. data/lib/active_record/locale/en.yml +9 -27
  92. data/lib/active_record/locking/optimistic.rb +76 -73
  93. data/lib/active_record/locking/pessimistic.rb +32 -10
  94. data/lib/active_record/log_subscriber.rb +72 -0
  95. data/lib/active_record/migration/command_recorder.rb +105 -0
  96. data/lib/active_record/migration.rb +415 -205
  97. data/lib/active_record/model_schema.rb +368 -0
  98. data/lib/active_record/nested_attributes.rb +153 -63
  99. data/lib/active_record/observer.rb +27 -103
  100. data/lib/active_record/persistence.rb +376 -0
  101. data/lib/active_record/query_cache.rb +49 -8
  102. data/lib/active_record/querying.rb +58 -0
  103. data/lib/active_record/railtie.rb +131 -0
  104. data/lib/active_record/railties/console_sandbox.rb +6 -0
  105. data/lib/active_record/railties/controller_runtime.rb +49 -0
  106. data/lib/active_record/railties/databases.rake +659 -0
  107. data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
  108. data/lib/active_record/readonly_attributes.rb +26 -0
  109. data/lib/active_record/reflection.rb +269 -120
  110. data/lib/active_record/relation/batches.rb +90 -0
  111. data/lib/active_record/relation/calculations.rb +372 -0
  112. data/lib/active_record/relation/delegation.rb +49 -0
  113. data/lib/active_record/relation/finder_methods.rb +402 -0
  114. data/lib/active_record/relation/predicate_builder.rb +63 -0
  115. data/lib/active_record/relation/query_methods.rb +417 -0
  116. data/lib/active_record/relation/spawn_methods.rb +180 -0
  117. data/lib/active_record/relation.rb +537 -0
  118. data/lib/active_record/result.rb +40 -0
  119. data/lib/active_record/sanitization.rb +194 -0
  120. data/lib/active_record/schema.rb +9 -6
  121. data/lib/active_record/schema_dumper.rb +55 -32
  122. data/lib/active_record/scoping/default.rb +142 -0
  123. data/lib/active_record/scoping/named.rb +200 -0
  124. data/lib/active_record/scoping.rb +152 -0
  125. data/lib/active_record/serialization.rb +8 -91
  126. data/lib/active_record/serializers/xml_serializer.rb +43 -197
  127. data/lib/active_record/session_store.rb +129 -103
  128. data/lib/active_record/store.rb +52 -0
  129. data/lib/active_record/test_case.rb +30 -23
  130. data/lib/active_record/timestamp.rb +95 -52
  131. data/lib/active_record/transactions.rb +212 -66
  132. data/lib/active_record/translation.rb +22 -0
  133. data/lib/active_record/validations/associated.rb +43 -0
  134. data/lib/active_record/validations/uniqueness.rb +180 -0
  135. data/lib/active_record/validations.rb +43 -1106
  136. data/lib/active_record/version.rb +5 -4
  137. data/lib/active_record.rb +121 -48
  138. data/lib/rails/generators/active_record/migration/migration_generator.rb +25 -0
  139. data/lib/rails/generators/active_record/migration/templates/migration.rb +34 -0
  140. data/lib/rails/generators/active_record/migration.rb +15 -0
  141. data/lib/rails/generators/active_record/model/model_generator.rb +47 -0
  142. data/lib/rails/generators/active_record/model/templates/migration.rb +15 -0
  143. data/lib/rails/generators/active_record/model/templates/model.rb +12 -0
  144. data/lib/rails/generators/active_record/model/templates/module.rb +7 -0
  145. data/lib/rails/generators/active_record/observer/observer_generator.rb +15 -0
  146. data/lib/rails/generators/active_record/observer/templates/observer.rb +4 -0
  147. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +25 -0
  148. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +12 -0
  149. data/lib/rails/generators/active_record.rb +25 -0
  150. metadata +187 -363
  151. data/CHANGELOG +0 -5904
  152. data/README +0 -351
  153. data/RUNNING_UNIT_TESTS +0 -36
  154. data/Rakefile +0 -268
  155. data/install.rb +0 -30
  156. data/lib/active_record/association_preload.rb +0 -406
  157. data/lib/active_record/associations/association_collection.rb +0 -533
  158. data/lib/active_record/associations/association_proxy.rb +0 -288
  159. data/lib/active_record/batches.rb +0 -85
  160. data/lib/active_record/calculations.rb +0 -321
  161. data/lib/active_record/dirty.rb +0 -183
  162. data/lib/active_record/named_scope.rb +0 -197
  163. data/lib/active_record/serializers/json_serializer.rb +0 -91
  164. data/lib/activerecord.rb +0 -2
  165. data/test/assets/example.log +0 -1
  166. data/test/assets/flowers.jpg +0 -0
  167. data/test/cases/aaa_create_tables_test.rb +0 -24
  168. data/test/cases/active_schema_test_mysql.rb +0 -122
  169. data/test/cases/active_schema_test_postgresql.rb +0 -24
  170. data/test/cases/adapter_test.rb +0 -144
  171. data/test/cases/aggregations_test.rb +0 -167
  172. data/test/cases/ar_schema_test.rb +0 -32
  173. data/test/cases/associations/belongs_to_associations_test.rb +0 -438
  174. data/test/cases/associations/callbacks_test.rb +0 -161
  175. data/test/cases/associations/cascaded_eager_loading_test.rb +0 -131
  176. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +0 -36
  177. data/test/cases/associations/eager_load_nested_include_test.rb +0 -131
  178. data/test/cases/associations/eager_load_nested_polymorphic_include.rb +0 -19
  179. data/test/cases/associations/eager_singularization_test.rb +0 -145
  180. data/test/cases/associations/eager_test.rb +0 -852
  181. data/test/cases/associations/extension_test.rb +0 -62
  182. data/test/cases/associations/habtm_join_table_test.rb +0 -56
  183. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +0 -827
  184. data/test/cases/associations/has_many_associations_test.rb +0 -1273
  185. data/test/cases/associations/has_many_through_associations_test.rb +0 -360
  186. data/test/cases/associations/has_one_associations_test.rb +0 -330
  187. data/test/cases/associations/has_one_through_associations_test.rb +0 -209
  188. data/test/cases/associations/inner_join_association_test.rb +0 -93
  189. data/test/cases/associations/inverse_associations_test.rb +0 -566
  190. data/test/cases/associations/join_model_test.rb +0 -712
  191. data/test/cases/associations_test.rb +0 -282
  192. data/test/cases/attribute_methods_test.rb +0 -305
  193. data/test/cases/autosave_association_test.rb +0 -1218
  194. data/test/cases/base_test.rb +0 -2166
  195. data/test/cases/batches_test.rb +0 -81
  196. data/test/cases/binary_test.rb +0 -30
  197. data/test/cases/calculations_test.rb +0 -360
  198. data/test/cases/callbacks_observers_test.rb +0 -38
  199. data/test/cases/callbacks_test.rb +0 -438
  200. data/test/cases/class_inheritable_attributes_test.rb +0 -32
  201. data/test/cases/column_alias_test.rb +0 -17
  202. data/test/cases/column_definition_test.rb +0 -70
  203. data/test/cases/connection_pool_test.rb +0 -25
  204. data/test/cases/connection_test_firebird.rb +0 -8
  205. data/test/cases/connection_test_mysql.rb +0 -65
  206. data/test/cases/copy_table_test_sqlite.rb +0 -80
  207. data/test/cases/counter_cache_test.rb +0 -84
  208. data/test/cases/database_statements_test.rb +0 -12
  209. data/test/cases/datatype_test_postgresql.rb +0 -204
  210. data/test/cases/date_time_test.rb +0 -37
  211. data/test/cases/default_test_firebird.rb +0 -16
  212. data/test/cases/defaults_test.rb +0 -111
  213. data/test/cases/deprecated_finder_test.rb +0 -30
  214. data/test/cases/dirty_test.rb +0 -316
  215. data/test/cases/finder_respond_to_test.rb +0 -76
  216. data/test/cases/finder_test.rb +0 -1098
  217. data/test/cases/fixtures_test.rb +0 -661
  218. data/test/cases/helper.rb +0 -68
  219. data/test/cases/i18n_test.rb +0 -46
  220. data/test/cases/inheritance_test.rb +0 -262
  221. data/test/cases/invalid_date_test.rb +0 -24
  222. data/test/cases/json_serialization_test.rb +0 -219
  223. data/test/cases/lifecycle_test.rb +0 -193
  224. data/test/cases/locking_test.rb +0 -350
  225. data/test/cases/method_scoping_test.rb +0 -704
  226. data/test/cases/migration_test.rb +0 -1649
  227. data/test/cases/migration_test_firebird.rb +0 -124
  228. data/test/cases/mixin_test.rb +0 -96
  229. data/test/cases/modules_test.rb +0 -109
  230. data/test/cases/multiple_db_test.rb +0 -85
  231. data/test/cases/named_scope_test.rb +0 -372
  232. data/test/cases/nested_attributes_test.rb +0 -840
  233. data/test/cases/pk_test.rb +0 -119
  234. data/test/cases/pooled_connections_test.rb +0 -103
  235. data/test/cases/query_cache_test.rb +0 -129
  236. data/test/cases/readonly_test.rb +0 -107
  237. data/test/cases/reflection_test.rb +0 -234
  238. data/test/cases/reload_models_test.rb +0 -22
  239. data/test/cases/repair_helper.rb +0 -50
  240. data/test/cases/reserved_word_test_mysql.rb +0 -176
  241. data/test/cases/sanitize_test.rb +0 -25
  242. data/test/cases/schema_authorization_test_postgresql.rb +0 -75
  243. data/test/cases/schema_dumper_test.rb +0 -211
  244. data/test/cases/schema_test_postgresql.rb +0 -178
  245. data/test/cases/serialization_test.rb +0 -47
  246. data/test/cases/sp_test_mysql.rb +0 -16
  247. data/test/cases/synonym_test_oracle.rb +0 -17
  248. data/test/cases/timestamp_test.rb +0 -75
  249. data/test/cases/transactions_test.rb +0 -543
  250. data/test/cases/unconnected_test.rb +0 -32
  251. data/test/cases/validations_i18n_test.rb +0 -925
  252. data/test/cases/validations_test.rb +0 -1684
  253. data/test/cases/xml_serialization_test.rb +0 -240
  254. data/test/cases/yaml_serialization_test.rb +0 -11
  255. data/test/config.rb +0 -5
  256. data/test/connections/jdbc_jdbcderby/connection.rb +0 -18
  257. data/test/connections/jdbc_jdbch2/connection.rb +0 -18
  258. data/test/connections/jdbc_jdbchsqldb/connection.rb +0 -18
  259. data/test/connections/jdbc_jdbcmysql/connection.rb +0 -26
  260. data/test/connections/jdbc_jdbcpostgresql/connection.rb +0 -26
  261. data/test/connections/jdbc_jdbcsqlite3/connection.rb +0 -25
  262. data/test/connections/native_db2/connection.rb +0 -25
  263. data/test/connections/native_firebird/connection.rb +0 -26
  264. data/test/connections/native_frontbase/connection.rb +0 -27
  265. data/test/connections/native_mysql/connection.rb +0 -25
  266. data/test/connections/native_openbase/connection.rb +0 -21
  267. data/test/connections/native_oracle/connection.rb +0 -27
  268. data/test/connections/native_postgresql/connection.rb +0 -21
  269. data/test/connections/native_sqlite/connection.rb +0 -25
  270. data/test/connections/native_sqlite3/connection.rb +0 -25
  271. data/test/connections/native_sqlite3/in_memory_connection.rb +0 -18
  272. data/test/connections/native_sybase/connection.rb +0 -23
  273. data/test/fixtures/accounts.yml +0 -29
  274. data/test/fixtures/all/developers.yml +0 -0
  275. data/test/fixtures/all/people.csv +0 -0
  276. data/test/fixtures/all/tasks.yml +0 -0
  277. data/test/fixtures/author_addresses.yml +0 -5
  278. data/test/fixtures/author_favorites.yml +0 -4
  279. data/test/fixtures/authors.yml +0 -9
  280. data/test/fixtures/binaries.yml +0 -132
  281. data/test/fixtures/books.yml +0 -7
  282. data/test/fixtures/categories/special_categories.yml +0 -9
  283. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +0 -4
  284. data/test/fixtures/categories.yml +0 -14
  285. data/test/fixtures/categories_ordered.yml +0 -7
  286. data/test/fixtures/categories_posts.yml +0 -23
  287. data/test/fixtures/categorizations.yml +0 -17
  288. data/test/fixtures/clubs.yml +0 -6
  289. data/test/fixtures/comments.yml +0 -59
  290. data/test/fixtures/companies.yml +0 -56
  291. data/test/fixtures/computers.yml +0 -4
  292. data/test/fixtures/courses.yml +0 -7
  293. data/test/fixtures/customers.yml +0 -26
  294. data/test/fixtures/developers.yml +0 -21
  295. data/test/fixtures/developers_projects.yml +0 -17
  296. data/test/fixtures/edges.yml +0 -6
  297. data/test/fixtures/entrants.yml +0 -14
  298. data/test/fixtures/faces.yml +0 -11
  299. data/test/fixtures/fk_test_has_fk.yml +0 -3
  300. data/test/fixtures/fk_test_has_pk.yml +0 -2
  301. data/test/fixtures/funny_jokes.yml +0 -10
  302. data/test/fixtures/interests.yml +0 -33
  303. data/test/fixtures/items.yml +0 -4
  304. data/test/fixtures/jobs.yml +0 -7
  305. data/test/fixtures/legacy_things.yml +0 -3
  306. data/test/fixtures/mateys.yml +0 -4
  307. data/test/fixtures/member_types.yml +0 -6
  308. data/test/fixtures/members.yml +0 -6
  309. data/test/fixtures/memberships.yml +0 -20
  310. data/test/fixtures/men.yml +0 -5
  311. data/test/fixtures/minimalistics.yml +0 -2
  312. data/test/fixtures/mixed_case_monkeys.yml +0 -6
  313. data/test/fixtures/mixins.yml +0 -29
  314. data/test/fixtures/movies.yml +0 -7
  315. data/test/fixtures/naked/csv/accounts.csv +0 -1
  316. data/test/fixtures/naked/yml/accounts.yml +0 -1
  317. data/test/fixtures/naked/yml/companies.yml +0 -1
  318. data/test/fixtures/naked/yml/courses.yml +0 -1
  319. data/test/fixtures/organizations.yml +0 -5
  320. data/test/fixtures/owners.yml +0 -7
  321. data/test/fixtures/parrots.yml +0 -27
  322. data/test/fixtures/parrots_pirates.yml +0 -7
  323. data/test/fixtures/people.yml +0 -15
  324. data/test/fixtures/pets.yml +0 -14
  325. data/test/fixtures/pirates.yml +0 -9
  326. data/test/fixtures/polymorphic_designs.yml +0 -19
  327. data/test/fixtures/polymorphic_prices.yml +0 -19
  328. data/test/fixtures/posts.yml +0 -52
  329. data/test/fixtures/price_estimates.yml +0 -7
  330. data/test/fixtures/projects.yml +0 -7
  331. data/test/fixtures/readers.yml +0 -9
  332. data/test/fixtures/references.yml +0 -17
  333. data/test/fixtures/reserved_words/distinct.yml +0 -5
  334. data/test/fixtures/reserved_words/distincts_selects.yml +0 -11
  335. data/test/fixtures/reserved_words/group.yml +0 -14
  336. data/test/fixtures/reserved_words/select.yml +0 -8
  337. data/test/fixtures/reserved_words/values.yml +0 -7
  338. data/test/fixtures/ships.yml +0 -5
  339. data/test/fixtures/sponsors.yml +0 -9
  340. data/test/fixtures/subscribers.yml +0 -7
  341. data/test/fixtures/subscriptions.yml +0 -12
  342. data/test/fixtures/taggings.yml +0 -28
  343. data/test/fixtures/tags.yml +0 -7
  344. data/test/fixtures/tasks.yml +0 -7
  345. data/test/fixtures/tees.yml +0 -4
  346. data/test/fixtures/ties.yml +0 -4
  347. data/test/fixtures/topics.yml +0 -42
  348. data/test/fixtures/toys.yml +0 -4
  349. data/test/fixtures/treasures.yml +0 -10
  350. data/test/fixtures/vertices.yml +0 -4
  351. data/test/fixtures/warehouse-things.yml +0 -3
  352. data/test/fixtures/zines.yml +0 -5
  353. data/test/migrations/broken/100_migration_that_raises_exception.rb +0 -10
  354. data/test/migrations/decimal/1_give_me_big_numbers.rb +0 -15
  355. data/test/migrations/duplicate/1_people_have_last_names.rb +0 -9
  356. data/test/migrations/duplicate/2_we_need_reminders.rb +0 -12
  357. data/test/migrations/duplicate/3_foo.rb +0 -7
  358. data/test/migrations/duplicate/3_innocent_jointable.rb +0 -12
  359. data/test/migrations/duplicate_names/20080507052938_chunky.rb +0 -7
  360. data/test/migrations/duplicate_names/20080507053028_chunky.rb +0 -7
  361. data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +0 -12
  362. data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +0 -9
  363. data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +0 -12
  364. data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +0 -9
  365. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +0 -8
  366. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +0 -12
  367. data/test/migrations/missing/1000_people_have_middle_names.rb +0 -9
  368. data/test/migrations/missing/1_people_have_last_names.rb +0 -9
  369. data/test/migrations/missing/3_we_need_reminders.rb +0 -12
  370. data/test/migrations/missing/4_innocent_jointable.rb +0 -12
  371. data/test/migrations/valid/1_people_have_last_names.rb +0 -9
  372. data/test/migrations/valid/2_we_need_reminders.rb +0 -12
  373. data/test/migrations/valid/3_innocent_jointable.rb +0 -12
  374. data/test/models/author.rb +0 -151
  375. data/test/models/auto_id.rb +0 -4
  376. data/test/models/binary.rb +0 -2
  377. data/test/models/bird.rb +0 -9
  378. data/test/models/book.rb +0 -4
  379. data/test/models/categorization.rb +0 -5
  380. data/test/models/category.rb +0 -34
  381. data/test/models/citation.rb +0 -6
  382. data/test/models/club.rb +0 -13
  383. data/test/models/column_name.rb +0 -3
  384. data/test/models/comment.rb +0 -29
  385. data/test/models/company.rb +0 -173
  386. data/test/models/company_in_module.rb +0 -78
  387. data/test/models/computer.rb +0 -3
  388. data/test/models/contact.rb +0 -16
  389. data/test/models/contract.rb +0 -5
  390. data/test/models/course.rb +0 -3
  391. data/test/models/customer.rb +0 -73
  392. data/test/models/default.rb +0 -2
  393. data/test/models/developer.rb +0 -101
  394. data/test/models/edge.rb +0 -5
  395. data/test/models/entrant.rb +0 -3
  396. data/test/models/essay.rb +0 -3
  397. data/test/models/event.rb +0 -3
  398. data/test/models/event_author.rb +0 -8
  399. data/test/models/face.rb +0 -7
  400. data/test/models/guid.rb +0 -2
  401. data/test/models/interest.rb +0 -5
  402. data/test/models/invoice.rb +0 -4
  403. data/test/models/item.rb +0 -7
  404. data/test/models/job.rb +0 -5
  405. data/test/models/joke.rb +0 -3
  406. data/test/models/keyboard.rb +0 -3
  407. data/test/models/legacy_thing.rb +0 -3
  408. data/test/models/line_item.rb +0 -3
  409. data/test/models/man.rb +0 -9
  410. data/test/models/matey.rb +0 -4
  411. data/test/models/member.rb +0 -12
  412. data/test/models/member_detail.rb +0 -5
  413. data/test/models/member_type.rb +0 -3
  414. data/test/models/membership.rb +0 -9
  415. data/test/models/minimalistic.rb +0 -2
  416. data/test/models/mixed_case_monkey.rb +0 -3
  417. data/test/models/movie.rb +0 -5
  418. data/test/models/order.rb +0 -4
  419. data/test/models/organization.rb +0 -6
  420. data/test/models/owner.rb +0 -5
  421. data/test/models/parrot.rb +0 -22
  422. data/test/models/person.rb +0 -16
  423. data/test/models/pet.rb +0 -5
  424. data/test/models/pirate.rb +0 -80
  425. data/test/models/polymorphic_design.rb +0 -3
  426. data/test/models/polymorphic_price.rb +0 -3
  427. data/test/models/post.rb +0 -102
  428. data/test/models/price_estimate.rb +0 -3
  429. data/test/models/project.rb +0 -30
  430. data/test/models/reader.rb +0 -4
  431. data/test/models/reference.rb +0 -4
  432. data/test/models/reply.rb +0 -46
  433. data/test/models/ship.rb +0 -19
  434. data/test/models/ship_part.rb +0 -7
  435. data/test/models/sponsor.rb +0 -4
  436. data/test/models/subject.rb +0 -4
  437. data/test/models/subscriber.rb +0 -8
  438. data/test/models/subscription.rb +0 -4
  439. data/test/models/tag.rb +0 -7
  440. data/test/models/tagging.rb +0 -10
  441. data/test/models/task.rb +0 -3
  442. data/test/models/tee.rb +0 -4
  443. data/test/models/tie.rb +0 -4
  444. data/test/models/topic.rb +0 -80
  445. data/test/models/toy.rb +0 -6
  446. data/test/models/treasure.rb +0 -8
  447. data/test/models/vertex.rb +0 -9
  448. data/test/models/warehouse_thing.rb +0 -5
  449. data/test/models/zine.rb +0 -3
  450. data/test/schema/mysql_specific_schema.rb +0 -31
  451. data/test/schema/postgresql_specific_schema.rb +0 -114
  452. data/test/schema/schema.rb +0 -550
  453. data/test/schema/schema2.rb +0 -6
  454. data/test/schema/sqlite_specific_schema.rb +0 -25
@@ -1,533 +0,0 @@
1
- require 'set'
2
-
3
- module ActiveRecord
4
- module Associations
5
- # AssociationCollection is an abstract class that provides common stuff to
6
- # ease the implementation of association proxies that represent
7
- # collections. See the class hierarchy in AssociationProxy.
8
- #
9
- # You need to be careful with assumptions regarding the target: The proxy
10
- # does not fetch records from the database until it needs them, but new
11
- # ones created with +build+ are added to the target. So, the target may be
12
- # non-empty and still lack children waiting to be read from the database.
13
- # If you look directly to the database you cannot assume that's the entire
14
- # collection because new records may have beed added to the target, etc.
15
- #
16
- # If you need to work on all current children, new and existing records,
17
- # +load_target+ and the +loaded+ flag are your friends.
18
- class AssociationCollection < AssociationProxy #:nodoc:
19
- def initialize(owner, reflection)
20
- super
21
- construct_sql
22
- end
23
-
24
- def find(*args)
25
- options = args.extract_options!
26
-
27
- # If using a custom finder_sql, scan the entire collection.
28
- if @reflection.options[:finder_sql]
29
- expects_array = args.first.kind_of?(Array)
30
- ids = args.flatten.compact.uniq.map { |arg| arg.to_i }
31
-
32
- if ids.size == 1
33
- id = ids.first
34
- record = load_target.detect { |r| id == r.id }
35
- expects_array ? [ record ] : record
36
- else
37
- load_target.select { |r| ids.include?(r.id) }
38
- end
39
- else
40
- conditions = "#{@finder_sql}"
41
- if sanitized_conditions = sanitize_sql(options[:conditions])
42
- conditions << " AND (#{sanitized_conditions})"
43
- end
44
-
45
- options[:conditions] = conditions
46
-
47
- if options[:order] && @reflection.options[:order]
48
- options[:order] = "#{options[:order]}, #{@reflection.options[:order]}"
49
- elsif @reflection.options[:order]
50
- options[:order] = @reflection.options[:order]
51
- end
52
-
53
- # Build options specific to association
54
- construct_find_options!(options)
55
-
56
- merge_options_from_reflection!(options)
57
-
58
- # Pass through args exactly as we received them.
59
- args << options
60
- @reflection.klass.find(*args)
61
- end
62
- end
63
-
64
- # Fetches the first one using SQL if possible.
65
- def first(*args)
66
- if fetch_first_or_last_using_find?(args)
67
- find(:first, *args)
68
- else
69
- load_target unless loaded?
70
- @target.first(*args)
71
- end
72
- end
73
-
74
- # Fetches the last one using SQL if possible.
75
- def last(*args)
76
- if fetch_first_or_last_using_find?(args)
77
- find(:last, *args)
78
- else
79
- load_target unless loaded?
80
- @target.last(*args)
81
- end
82
- end
83
-
84
- def to_ary
85
- load_target
86
- if @target.is_a?(Array)
87
- @target.to_ary
88
- else
89
- Array(@target)
90
- end
91
- end
92
-
93
- def reset
94
- reset_target!
95
- @loaded = false
96
- end
97
-
98
- def build(attributes = {}, &block)
99
- if attributes.is_a?(Array)
100
- attributes.collect { |attr| build(attr, &block) }
101
- else
102
- build_record(attributes) do |record|
103
- block.call(record) if block_given?
104
- set_belongs_to_association_for(record)
105
- end
106
- end
107
- end
108
-
109
- # Add +records+ to this association. Returns +self+ so method calls may be chained.
110
- # Since << flattens its argument list and inserts each record, +push+ and +concat+ behave identically.
111
- def <<(*records)
112
- result = true
113
- load_target if @owner.new_record?
114
-
115
- transaction do
116
- flatten_deeper(records).each do |record|
117
- raise_on_type_mismatch(record)
118
- add_record_to_target_with_callbacks(record) do |r|
119
- result &&= insert_record(record) unless @owner.new_record?
120
- end
121
- end
122
- end
123
-
124
- result && self
125
- end
126
-
127
- alias_method :push, :<<
128
- alias_method :concat, :<<
129
-
130
- # Starts a transaction in the association class's database connection.
131
- #
132
- # class Author < ActiveRecord::Base
133
- # has_many :books
134
- # end
135
- #
136
- # Author.find(:first).books.transaction do
137
- # # same effect as calling Book.transaction
138
- # end
139
- def transaction(*args)
140
- @reflection.klass.transaction(*args) do
141
- yield
142
- end
143
- end
144
-
145
- # Remove all records from this association
146
- #
147
- # See delete for more info.
148
- def delete_all
149
- load_target
150
- delete(@target)
151
- reset_target!
152
- end
153
-
154
- # Calculate sum using SQL, not Enumerable
155
- def sum(*args)
156
- if block_given?
157
- calculate(:sum, *args) { |*block_args| yield(*block_args) }
158
- else
159
- calculate(:sum, *args)
160
- end
161
- end
162
-
163
- # Count all records using SQL. If the +:counter_sql+ option is set for the association, it will
164
- # be used for the query. If no +:counter_sql+ was supplied, but +:finder_sql+ was set, the
165
- # descendant's +construct_sql+ method will have set :counter_sql automatically.
166
- # Otherwise, construct options and pass them with scope to the target class's +count+.
167
- def count(*args)
168
- if @reflection.options[:counter_sql]
169
- @reflection.klass.count_by_sql(@counter_sql)
170
- else
171
- column_name, options = @reflection.klass.send(:construct_count_options_from_args, *args)
172
- if @reflection.options[:uniq]
173
- # This is needed because 'SELECT count(DISTINCT *)..' is not valid SQL.
174
- column_name = "#{@reflection.quoted_table_name}.#{@reflection.klass.primary_key}" if column_name == :all
175
- options.merge!(:distinct => true)
176
- end
177
-
178
- value = @reflection.klass.send(:with_scope, construct_scope) { @reflection.klass.count(column_name, options) }
179
-
180
- limit = @reflection.options[:limit]
181
- offset = @reflection.options[:offset]
182
-
183
- if limit || offset
184
- [ [value - offset.to_i, 0].max, limit.to_i ].min
185
- else
186
- value
187
- end
188
- end
189
- end
190
-
191
- # Removes +records+ from this association calling +before_remove+ and
192
- # +after_remove+ callbacks.
193
- #
194
- # This method is abstract in the sense that +delete_records+ has to be
195
- # provided by descendants. Note this method does not imply the records
196
- # are actually removed from the database, that depends precisely on
197
- # +delete_records+. They are in any case removed from the collection.
198
- def delete(*records)
199
- remove_records(records) do |records, old_records|
200
- delete_records(old_records) if old_records.any?
201
- records.each { |record| @target.delete(record) }
202
- end
203
- end
204
-
205
- # Destroy +records+ and remove them from this association calling
206
- # +before_remove+ and +after_remove+ callbacks.
207
- #
208
- # Note that this method will _always_ remove records from the database
209
- # ignoring the +:dependent+ option.
210
- def destroy(*records)
211
- records = find(records) if records.any? {|record| record.kind_of?(Fixnum) || record.kind_of?(String)}
212
- remove_records(records) do |records, old_records|
213
- old_records.each { |record| record.destroy }
214
- end
215
-
216
- load_target
217
- end
218
-
219
- # Removes all records from this association. Returns +self+ so method calls may be chained.
220
- def clear
221
- return self if length.zero? # forces load_target if it hasn't happened already
222
-
223
- if @reflection.options[:dependent] && @reflection.options[:dependent] == :destroy
224
- destroy_all
225
- else
226
- delete_all
227
- end
228
-
229
- self
230
- end
231
-
232
- # Destory all the records from this association.
233
- #
234
- # See destroy for more info.
235
- def destroy_all
236
- load_target
237
- destroy(@target).tap do
238
- reset_target!
239
- end
240
- end
241
-
242
- def create(attrs = {})
243
- if attrs.is_a?(Array)
244
- attrs.collect { |attr| create(attr) }
245
- else
246
- create_record(attrs) do |record|
247
- yield(record) if block_given?
248
- record.save
249
- end
250
- end
251
- end
252
-
253
- def create!(attrs = {})
254
- create_record(attrs) do |record|
255
- yield(record) if block_given?
256
- record.save!
257
- end
258
- end
259
-
260
- # Returns the size of the collection by executing a SELECT COUNT(*)
261
- # query if the collection hasn't been loaded, and calling
262
- # <tt>collection.size</tt> if it has.
263
- #
264
- # If the collection has been already loaded +size+ and +length+ are
265
- # equivalent. If not and you are going to need the records anyway
266
- # +length+ will take one less query. Otherwise +size+ is more efficient.
267
- #
268
- # This method is abstract in the sense that it relies on
269
- # +count_records+, which is a method descendants have to provide.
270
- def size
271
- if @owner.new_record? || (loaded? && !@reflection.options[:uniq])
272
- @target.size
273
- elsif !loaded? && @reflection.options[:group]
274
- load_target.size
275
- elsif !loaded? && !@reflection.options[:uniq] && @target.is_a?(Array)
276
- unsaved_records = @target.select { |r| r.new_record? }
277
- unsaved_records.size + count_records
278
- else
279
- count_records
280
- end
281
- end
282
-
283
- # Returns the size of the collection calling +size+ on the target.
284
- #
285
- # If the collection has been already loaded +length+ and +size+ are
286
- # equivalent. If not and you are going to need the records anyway this
287
- # method will take one less query. Otherwise +size+ is more efficient.
288
- def length
289
- load_target.size
290
- end
291
-
292
- # Equivalent to <tt>collection.size.zero?</tt>. If the collection has
293
- # not been already loaded and you are going to fetch the records anyway
294
- # it is better to check <tt>collection.length.zero?</tt>.
295
- def empty?
296
- size.zero?
297
- end
298
-
299
- def any?
300
- if block_given?
301
- method_missing(:any?) { |*block_args| yield(*block_args) }
302
- else
303
- !empty?
304
- end
305
- end
306
-
307
- def uniq(collection = self)
308
- seen = Set.new
309
- collection.inject([]) do |kept, record|
310
- unless seen.include?(record.id)
311
- kept << record
312
- seen << record.id
313
- end
314
- kept
315
- end
316
- end
317
-
318
- # Replace this collection with +other_array+
319
- # This will perform a diff and delete/add only records that have changed.
320
- def replace(other_array)
321
- other_array.each { |val| raise_on_type_mismatch(val) }
322
-
323
- load_target
324
- other = other_array.size < 100 ? other_array : other_array.to_set
325
- current = @target.size < 100 ? @target : @target.to_set
326
-
327
- transaction do
328
- delete(@target.select { |v| !other.include?(v) })
329
- concat(other_array.select { |v| !current.include?(v) })
330
- end
331
- end
332
-
333
- def include?(record)
334
- return false unless record.is_a?(@reflection.klass)
335
- return include_in_memory?(record) if record.new_record?
336
- load_target if @reflection.options[:finder_sql] && !loaded?
337
- return @target.include?(record) if loaded?
338
- exists?(record)
339
- end
340
-
341
- def proxy_respond_to?(method, include_private = false)
342
- super || @reflection.klass.respond_to?(method, include_private)
343
- end
344
-
345
- protected
346
- def construct_find_options!(options)
347
- end
348
-
349
- def load_target
350
- if !@owner.new_record? || foreign_key_present
351
- begin
352
- if !loaded?
353
- if @target.is_a?(Array) && @target.any?
354
- @target = find_target.map do |f|
355
- i = @target.index(f)
356
- t = @target.delete_at(i) if i
357
- if t && t.changed?
358
- t
359
- else
360
- f.mark_for_destruction if t && t.marked_for_destruction?
361
- f
362
- end
363
- end + @target.find_all {|t| t.new_record?}
364
- else
365
- @target = find_target
366
- end
367
- end
368
- rescue ActiveRecord::RecordNotFound
369
- reset
370
- end
371
- end
372
-
373
- loaded if target
374
- target
375
- end
376
-
377
- def method_missing(method, *args, &block)
378
- case method.to_s
379
- when 'find_or_create'
380
- return find(:first, :conditions => args.first) || create(args.first)
381
- when /^find_or_create_by_(.*)$/
382
- rest = $1
383
- find_args = pull_finder_args_from(DynamicFinderMatch.match(method).attribute_names, *args)
384
- return send("find_by_#{rest}", *find_args) ||
385
- method_missing("create_by_#{rest}", *args, &block)
386
- when /^create_by_(.*)$/
387
- return create($1.split('_and_').zip(args).inject({}) { |h,kv| k,v=kv ; h[k] = v ; h }, &block)
388
- end
389
-
390
- if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method))
391
- if block_given?
392
- super { |*block_args| yield(*block_args) }
393
- else
394
- super
395
- end
396
- elsif @reflection.klass.scopes.include?(method)
397
- @reflection.klass.scopes[method].call(self, *args)
398
- else
399
- with_scope(construct_scope) do
400
- if block_given?
401
- @reflection.klass.send(method, *args) { |*block_args| yield(*block_args) }
402
- else
403
- @reflection.klass.send(method, *args)
404
- end
405
- end
406
- end
407
- end
408
-
409
- # overloaded in derived Association classes to provide useful scoping depending on association type.
410
- def construct_scope
411
- {}
412
- end
413
-
414
- def reset_target!
415
- @target = Array.new
416
- end
417
-
418
- def find_target
419
- records =
420
- if @reflection.options[:finder_sql]
421
- @reflection.klass.find_by_sql(@finder_sql)
422
- else
423
- find(:all)
424
- end
425
-
426
- records = @reflection.options[:uniq] ? uniq(records) : records
427
- records.each do |record|
428
- set_inverse_instance(record, @owner)
429
- end
430
- records
431
- end
432
-
433
- def add_record_to_target_with_callbacks(record)
434
- callback(:before_add, record)
435
- yield(record) if block_given?
436
- @target ||= [] unless loaded?
437
- @target << record unless @reflection.options[:uniq] && @target.include?(record)
438
- callback(:after_add, record)
439
- set_inverse_instance(record, @owner)
440
- record
441
- end
442
-
443
- private
444
- # Separate the "finder" args from the "create" args given to a
445
- # find_or_create_by_ call. Returns an array with the
446
- # parameter values in the same order as the keys in the
447
- # "names" array. This code was based on code in base.rb's
448
- # method_missing method.
449
- def pull_finder_args_from(names, *args)
450
- attributes = names.collect { |name| name.intern }
451
- attribute_hash = {}
452
- args.each_with_index do |arg, i|
453
- if arg.is_a?(Hash)
454
- attribute_hash.merge! arg
455
- else
456
- attribute_hash[attributes[i]] = arg
457
- end
458
- end
459
- attribute_hash = attribute_hash.with_indifferent_access
460
- attributes.collect { |attr| attribute_hash[attr] }
461
- end
462
-
463
- def create_record(attrs)
464
- attrs.update(@reflection.options[:conditions]) if @reflection.options[:conditions].is_a?(Hash)
465
- ensure_owner_is_not_new
466
- record = @reflection.klass.send(:with_scope, :create => construct_scope[:create]) do
467
- @reflection.build_association(attrs)
468
- end
469
- if block_given?
470
- add_record_to_target_with_callbacks(record) { |*block_args| yield(*block_args) }
471
- else
472
- add_record_to_target_with_callbacks(record)
473
- end
474
- end
475
-
476
- def build_record(attrs)
477
- attrs.update(@reflection.options[:conditions]) if @reflection.options[:conditions].is_a?(Hash)
478
- record = @reflection.build_association(attrs)
479
- if block_given?
480
- add_record_to_target_with_callbacks(record) { |*block_args| yield(*block_args) }
481
- else
482
- add_record_to_target_with_callbacks(record)
483
- end
484
- end
485
-
486
- def remove_records(*records)
487
- records = flatten_deeper(records)
488
- records.each { |record| raise_on_type_mismatch(record) }
489
-
490
- transaction do
491
- records.each { |record| callback(:before_remove, record) }
492
- old_records = records.reject { |r| r.new_record? }
493
- yield(records, old_records)
494
- records.each { |record| callback(:after_remove, record) }
495
- end
496
- end
497
-
498
- def callback(method, record)
499
- callbacks_for(method).each do |callback|
500
- ActiveSupport::Callbacks::Callback.new(method, callback, record).call(@owner, record)
501
- end
502
- end
503
-
504
- def callbacks_for(callback_name)
505
- full_callback_name = "#{callback_name}_for_#{@reflection.name}"
506
- @owner.class.read_inheritable_attribute(full_callback_name.to_sym) || []
507
- end
508
-
509
- def ensure_owner_is_not_new
510
- if @owner.new_record?
511
- raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
512
- end
513
- end
514
-
515
- def fetch_first_or_last_using_find?(args)
516
- args.first.kind_of?(Hash) || !(loaded? || @owner.new_record? || @reflection.options[:finder_sql] ||
517
- @target.any? { |record| record.new_record? } || args.first.kind_of?(Integer))
518
- end
519
-
520
- def include_in_memory?(record)
521
- if @reflection.is_a?(ActiveRecord::Reflection::ThroughReflection)
522
- @owner.send(proxy_reflection.through_reflection.name.to_sym).each do |source|
523
- source_reflection_target = source.send(proxy_reflection.source_reflection.name)
524
- return true if source_reflection_target.respond_to?(:include?) ? source_reflection_target.include?(record) : source_reflection_target == record
525
- end
526
- false
527
- else
528
- @target.include?(record)
529
- end
530
- end
531
- end
532
- end
533
- end