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
@@ -0,0 +1,417 @@
1
+ require 'active_support/core_ext/array/wrap'
2
+ require 'active_support/core_ext/object/blank'
3
+
4
+ module ActiveRecord
5
+ module QueryMethods
6
+ extend ActiveSupport::Concern
7
+
8
+ attr_accessor :includes_values, :eager_load_values, :preload_values,
9
+ :select_values, :group_values, :order_values, :joins_values,
10
+ :where_values, :having_values, :bind_values,
11
+ :limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value,
12
+ :from_value, :reordering_value, :reverse_order_value,
13
+ :uniq_value
14
+
15
+ def includes(*args)
16
+ args.reject! {|a| a.blank? }
17
+
18
+ return self if args.empty?
19
+
20
+ relation = clone
21
+ relation.includes_values = (relation.includes_values + args).flatten.uniq
22
+ relation
23
+ end
24
+
25
+ def eager_load(*args)
26
+ return self if args.blank?
27
+
28
+ relation = clone
29
+ relation.eager_load_values += args
30
+ relation
31
+ end
32
+
33
+ def preload(*args)
34
+ return self if args.blank?
35
+
36
+ relation = clone
37
+ relation.preload_values += args
38
+ relation
39
+ end
40
+
41
+ # Works in two unique ways.
42
+ #
43
+ # First: takes a block so it can be used just like Array#select.
44
+ #
45
+ # Model.scoped.select { |m| m.field == value }
46
+ #
47
+ # This will build an array of objects from the database for the scope,
48
+ # converting them into an array and iterating through them using Array#select.
49
+ #
50
+ # Second: Modifies the SELECT statement for the query so that only certain
51
+ # fields are retrieved:
52
+ #
53
+ # >> Model.select(:field)
54
+ # => [#<Model field:value>]
55
+ #
56
+ # Although in the above example it looks as though this method returns an
57
+ # array, it actually returns a relation object and can have other query
58
+ # methods appended to it, such as the other methods in ActiveRecord::QueryMethods.
59
+ #
60
+ # The argument to the method can also be an array of fields.
61
+ #
62
+ # >> Model.select([:field, :other_field, :and_one_more])
63
+ # => [#<Model field: "value", other_field: "value", and_one_more: "value">]
64
+ #
65
+ # Any attributes that do not have fields retrieved by a select
66
+ # will raise a ActiveModel::MissingAttributeError when the getter method for that attribute is used:
67
+ #
68
+ # >> Model.select(:field).first.other_field
69
+ # => ActiveModel::MissingAttributeError: missing attribute: other_field
70
+ def select(value = Proc.new)
71
+ if block_given?
72
+ to_a.select {|*block_args| value.call(*block_args) }
73
+ else
74
+ relation = clone
75
+ relation.select_values += Array.wrap(value)
76
+ relation
77
+ end
78
+ end
79
+
80
+ def group(*args)
81
+ return self if args.blank?
82
+
83
+ relation = clone
84
+ relation.group_values += args.flatten
85
+ relation
86
+ end
87
+
88
+ def order(*args)
89
+ return self if args.blank?
90
+
91
+ relation = clone
92
+ relation.order_values += args.flatten
93
+ relation
94
+ end
95
+
96
+ # Replaces any existing order defined on the relation with the specified order.
97
+ #
98
+ # User.order('email DESC').reorder('id ASC') # generated SQL has 'ORDER BY id ASC'
99
+ #
100
+ # Subsequent calls to order on the same relation will be appended. For example:
101
+ #
102
+ # User.order('email DESC').reorder('id ASC').order('name ASC')
103
+ #
104
+ # generates a query with 'ORDER BY id ASC, name ASC'.
105
+ #
106
+ def reorder(*args)
107
+ return self if args.blank?
108
+
109
+ relation = clone
110
+ relation.reordering_value = true
111
+ relation.order_values = args.flatten
112
+ relation
113
+ end
114
+
115
+ def joins(*args)
116
+ return self if args.compact.blank?
117
+
118
+ relation = clone
119
+
120
+ args.flatten!
121
+ relation.joins_values += args
122
+
123
+ relation
124
+ end
125
+
126
+ def bind(value)
127
+ relation = clone
128
+ relation.bind_values += [value]
129
+ relation
130
+ end
131
+
132
+ def where(opts, *rest)
133
+ return self if opts.blank?
134
+
135
+ relation = clone
136
+ relation.where_values += build_where(opts, rest)
137
+ relation
138
+ end
139
+
140
+ def having(opts, *rest)
141
+ return self if opts.blank?
142
+
143
+ relation = clone
144
+ relation.having_values += build_where(opts, rest)
145
+ relation
146
+ end
147
+
148
+ def limit(value)
149
+ relation = clone
150
+ relation.limit_value = value
151
+ relation
152
+ end
153
+
154
+ def offset(value)
155
+ relation = clone
156
+ relation.offset_value = value
157
+ relation
158
+ end
159
+
160
+ def lock(locks = true)
161
+ relation = clone
162
+
163
+ case locks
164
+ when String, TrueClass, NilClass
165
+ relation.lock_value = locks || true
166
+ else
167
+ relation.lock_value = false
168
+ end
169
+
170
+ relation
171
+ end
172
+
173
+ def readonly(value = true)
174
+ relation = clone
175
+ relation.readonly_value = value
176
+ relation
177
+ end
178
+
179
+ def create_with(value)
180
+ relation = clone
181
+ relation.create_with_value = value ? create_with_value.merge(value) : {}
182
+ relation
183
+ end
184
+
185
+ def from(value)
186
+ relation = clone
187
+ relation.from_value = value
188
+ relation
189
+ end
190
+
191
+ # Specifies whether the records should be unique or not. For example:
192
+ #
193
+ # User.select(:name)
194
+ # # => Might return two records with the same name
195
+ #
196
+ # User.select(:name).uniq
197
+ # # => Returns 1 record per unique name
198
+ #
199
+ # User.select(:name).uniq.uniq(false)
200
+ # # => You can also remove the uniqueness
201
+ def uniq(value = true)
202
+ relation = clone
203
+ relation.uniq_value = value
204
+ relation
205
+ end
206
+
207
+ # Used to extend a scope with additional methods, either through
208
+ # a module or through a block provided.
209
+ #
210
+ # The object returned is a relation, which can be further extended.
211
+ #
212
+ # === Using a module
213
+ #
214
+ # module Pagination
215
+ # def page(number)
216
+ # # pagination code goes here
217
+ # end
218
+ # end
219
+ #
220
+ # scope = Model.scoped.extending(Pagination)
221
+ # scope.page(params[:page])
222
+ #
223
+ # You can also pass a list of modules:
224
+ #
225
+ # scope = Model.scoped.extending(Pagination, SomethingElse)
226
+ #
227
+ # === Using a block
228
+ #
229
+ # scope = Model.scoped.extending do
230
+ # def page(number)
231
+ # # pagination code goes here
232
+ # end
233
+ # end
234
+ # scope.page(params[:page])
235
+ #
236
+ # You can also use a block and a module list:
237
+ #
238
+ # scope = Model.scoped.extending(Pagination) do
239
+ # def per_page(number)
240
+ # # pagination code goes here
241
+ # end
242
+ # end
243
+ def extending(*modules)
244
+ modules << Module.new(&Proc.new) if block_given?
245
+
246
+ return self if modules.empty?
247
+
248
+ relation = clone
249
+ relation.send(:apply_modules, modules.flatten)
250
+ relation
251
+ end
252
+
253
+ def reverse_order
254
+ relation = clone
255
+ relation.reverse_order_value = !relation.reverse_order_value
256
+ relation
257
+ end
258
+
259
+ def arel
260
+ @arel ||= with_default_scope.build_arel
261
+ end
262
+
263
+ def build_arel
264
+ arel = table.from table
265
+
266
+ build_joins(arel, @joins_values) unless @joins_values.empty?
267
+
268
+ collapse_wheres(arel, (@where_values - ['']).uniq)
269
+
270
+ arel.having(*@having_values.uniq.reject{|h| h.blank?}) unless @having_values.empty?
271
+
272
+ arel.take(connection.sanitize_limit(@limit_value)) if @limit_value
273
+ arel.skip(@offset_value.to_i) if @offset_value
274
+
275
+ arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty?
276
+
277
+ order = @order_values
278
+ order = reverse_sql_order(order) if @reverse_order_value
279
+ arel.order(*order.uniq.reject{|o| o.blank?}) unless order.empty?
280
+
281
+ build_select(arel, @select_values.uniq)
282
+
283
+ arel.distinct(@uniq_value)
284
+ arel.from(@from_value) if @from_value
285
+ arel.lock(@lock_value) if @lock_value
286
+
287
+ arel
288
+ end
289
+
290
+ private
291
+
292
+ def custom_join_ast(table, joins)
293
+ joins = joins.reject { |join| join.blank? }
294
+
295
+ return [] if joins.empty?
296
+
297
+ @implicit_readonly = true
298
+
299
+ joins.map do |join|
300
+ case join
301
+ when Array
302
+ join = Arel.sql(join.join(' ')) if array_of_strings?(join)
303
+ when String
304
+ join = Arel.sql(join)
305
+ end
306
+ table.create_string_join(join)
307
+ end
308
+ end
309
+
310
+ def collapse_wheres(arel, wheres)
311
+ equalities = wheres.grep(Arel::Nodes::Equality)
312
+
313
+ arel.where(Arel::Nodes::And.new(equalities)) unless equalities.empty?
314
+
315
+ (wheres - equalities).each do |where|
316
+ where = Arel.sql(where) if String === where
317
+ arel.where(Arel::Nodes::Grouping.new(where))
318
+ end
319
+ end
320
+
321
+ def build_where(opts, other = [])
322
+ case opts
323
+ when String, Array
324
+ [@klass.send(:sanitize_sql, other.empty? ? opts : ([opts] + other))]
325
+ when Hash
326
+ attributes = @klass.send(:expand_hash_conditions_for_aggregates, opts)
327
+ PredicateBuilder.build_from_hash(table.engine, attributes, table)
328
+ else
329
+ [opts]
330
+ end
331
+ end
332
+
333
+ def build_joins(manager, joins)
334
+ buckets = joins.group_by do |join|
335
+ case join
336
+ when String
337
+ 'string_join'
338
+ when Hash, Symbol, Array
339
+ 'association_join'
340
+ when ActiveRecord::Associations::JoinDependency::JoinAssociation
341
+ 'stashed_join'
342
+ when Arel::Nodes::Join
343
+ 'join_node'
344
+ else
345
+ raise 'unknown class: %s' % join.class.name
346
+ end
347
+ end
348
+
349
+ association_joins = buckets['association_join'] || []
350
+ stashed_association_joins = buckets['stashed_join'] || []
351
+ join_nodes = (buckets['join_node'] || []).uniq
352
+ string_joins = (buckets['string_join'] || []).map { |x|
353
+ x.strip
354
+ }.uniq
355
+
356
+ join_list = join_nodes + custom_join_ast(manager, string_joins)
357
+
358
+ join_dependency = ActiveRecord::Associations::JoinDependency.new(
359
+ @klass,
360
+ association_joins,
361
+ join_list
362
+ )
363
+
364
+ join_dependency.graft(*stashed_association_joins)
365
+
366
+ @implicit_readonly = true unless association_joins.empty? && stashed_association_joins.empty?
367
+
368
+ # FIXME: refactor this to build an AST
369
+ join_dependency.join_associations.each do |association|
370
+ association.join_to(manager)
371
+ end
372
+
373
+ manager.join_sources.concat join_list
374
+
375
+ manager
376
+ end
377
+
378
+ def build_select(arel, selects)
379
+ unless selects.empty?
380
+ @implicit_readonly = false
381
+ arel.project(*selects)
382
+ else
383
+ arel.project(@klass.arel_table[Arel.star])
384
+ end
385
+ end
386
+
387
+ def apply_modules(modules)
388
+ unless modules.empty?
389
+ @extensions += modules
390
+ modules.each {|extension| extend(extension) }
391
+ end
392
+ end
393
+
394
+ def reverse_sql_order(order_query)
395
+ order_query = ["#{quoted_table_name}.#{quoted_primary_key} ASC"] if order_query.empty?
396
+
397
+ order_query.map do |o|
398
+ case o
399
+ when Arel::Nodes::Ordering
400
+ o.reverse
401
+ when String, Symbol
402
+ o.to_s.split(',').collect do |s|
403
+ s.strip!
404
+ s.gsub!(/\sasc\Z/i, ' DESC') || s.gsub!(/\sdesc\Z/i, ' ASC') || s.concat(' DESC')
405
+ end
406
+ else
407
+ o
408
+ end
409
+ end.flatten
410
+ end
411
+
412
+ def array_of_strings?(o)
413
+ o.is_a?(Array) && o.all?{|obj| obj.is_a?(String)}
414
+ end
415
+
416
+ end
417
+ end
@@ -0,0 +1,180 @@
1
+ require 'active_support/core_ext/object/blank'
2
+
3
+ module ActiveRecord
4
+ module SpawnMethods
5
+ def merge(r)
6
+ return self unless r
7
+ return to_a & r if r.is_a?(Array)
8
+
9
+ merged_relation = clone
10
+
11
+ r = r.with_default_scope if r.default_scoped? && r.klass != klass
12
+
13
+ Relation::ASSOCIATION_METHODS.each do |method|
14
+ value = r.send(:"#{method}_values")
15
+
16
+ unless value.empty?
17
+ if method == :includes
18
+ merged_relation = merged_relation.includes(value)
19
+ else
20
+ merge_relation_method(merged_relation, method, value)
21
+ end
22
+ end
23
+ end
24
+
25
+ (Relation::MULTI_VALUE_METHODS - [:joins, :where, :order]).each do |method|
26
+ value = r.send(:"#{method}_values")
27
+ merge_relation_method(merged_relation, method, value) if value.present?
28
+ end
29
+
30
+ merge_joins(merged_relation, r)
31
+
32
+ merged_wheres = @where_values + r.where_values
33
+
34
+ unless @where_values.empty?
35
+ # Remove duplicate ARel attributes. Last one wins.
36
+ seen = Hash.new { |h,table| h[table] = {} }
37
+ merged_wheres = merged_wheres.reverse.reject { |w|
38
+ nuke = false
39
+ if w.respond_to?(:operator) && w.operator == :== &&
40
+ w.left.respond_to?(:relation)
41
+ name = w.left.name
42
+ table = w.left.relation.name
43
+ nuke = seen[table][name]
44
+ seen[table][name] = true
45
+ end
46
+ nuke
47
+ }.reverse
48
+ end
49
+
50
+ merged_relation.where_values = merged_wheres
51
+
52
+ (Relation::SINGLE_VALUE_METHODS - [:lock, :create_with, :reordering]).each do |method|
53
+ value = r.send(:"#{method}_value")
54
+ merged_relation.send(:"#{method}_value=", value) unless value.nil?
55
+ end
56
+
57
+ merged_relation.lock_value = r.lock_value unless merged_relation.lock_value
58
+
59
+ merged_relation = merged_relation.create_with(r.create_with_value) unless r.create_with_value.empty?
60
+
61
+ if (r.reordering_value)
62
+ # override any order specified in the original relation
63
+ merged_relation.reordering_value = true
64
+ merged_relation.order_values = r.order_values
65
+ else
66
+ # merge in order_values from r
67
+ merged_relation.order_values += r.order_values
68
+ end
69
+
70
+ # Apply scope extension modules
71
+ merged_relation.send :apply_modules, r.extensions
72
+
73
+ merged_relation
74
+ end
75
+
76
+ # Removes from the query the condition(s) specified in +skips+.
77
+ #
78
+ # Example:
79
+ #
80
+ # Post.order('id asc').except(:order) # discards the order condition
81
+ # Post.where('id > 10').order('id asc').except(:where) # discards the where condition but keeps the order
82
+ #
83
+ def except(*skips)
84
+ result = self.class.new(@klass, table)
85
+ result.default_scoped = default_scoped
86
+
87
+ ((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) - skips).each do |method|
88
+ result.send(:"#{method}_values=", send(:"#{method}_values"))
89
+ end
90
+
91
+ (Relation::SINGLE_VALUE_METHODS - skips).each do |method|
92
+ result.send(:"#{method}_value=", send(:"#{method}_value"))
93
+ end
94
+
95
+ # Apply scope extension modules
96
+ result.send(:apply_modules, extensions)
97
+
98
+ result
99
+ end
100
+
101
+ # Removes any condition from the query other than the one(s) specified in +onlies+.
102
+ #
103
+ # Example:
104
+ #
105
+ # Post.order('id asc').only(:where) # discards the order condition
106
+ # Post.order('id asc').only(:where, :order) # uses the specified order
107
+ #
108
+ def only(*onlies)
109
+ result = self.class.new(@klass, table)
110
+ result.default_scoped = default_scoped
111
+
112
+ ((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) & onlies).each do |method|
113
+ result.send(:"#{method}_values=", send(:"#{method}_values"))
114
+ end
115
+
116
+ (Relation::SINGLE_VALUE_METHODS & onlies).each do |method|
117
+ result.send(:"#{method}_value=", send(:"#{method}_value"))
118
+ end
119
+
120
+ # Apply scope extension modules
121
+ result.send(:apply_modules, extensions)
122
+
123
+ result
124
+ end
125
+
126
+ VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :extend,
127
+ :order, :select, :readonly, :group, :having, :from, :lock ]
128
+
129
+ def apply_finder_options(options)
130
+ relation = clone
131
+ return relation unless options
132
+
133
+ options.assert_valid_keys(VALID_FIND_OPTIONS)
134
+ finders = options.dup
135
+ finders.delete_if { |key, value| value.nil? && key != :limit }
136
+
137
+ ([:joins, :select, :group, :order, :having, :limit, :offset, :from, :lock, :readonly] & finders.keys).each do |finder|
138
+ relation = relation.send(finder, finders[finder])
139
+ end
140
+
141
+ relation = relation.where(finders[:conditions]) if options.has_key?(:conditions)
142
+ relation = relation.includes(finders[:include]) if options.has_key?(:include)
143
+ relation = relation.extending(finders[:extend]) if options.has_key?(:extend)
144
+
145
+ relation
146
+ end
147
+
148
+ private
149
+
150
+ def merge_joins(relation, other)
151
+ values = other.joins_values
152
+ return if values.blank?
153
+
154
+ if other.klass >= relation.klass
155
+ relation.joins_values += values
156
+ else
157
+ joins_dependency, rest = values.partition do |join|
158
+ case join
159
+ when Hash, Symbol, Array
160
+ true
161
+ else
162
+ false
163
+ end
164
+ end
165
+
166
+ join_dependency = ActiveRecord::Associations::JoinDependency.new(
167
+ other.klass,
168
+ joins_dependency,
169
+ []
170
+ )
171
+
172
+ relation.joins_values += join_dependency.join_associations + rest
173
+ end
174
+ end
175
+
176
+ def merge_relation_method(relation, method, value)
177
+ relation.send(:"#{method}_values=", relation.send(:"#{method}_values") + value)
178
+ end
179
+ end
180
+ end