activerecord 2.3.18 → 3.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (378) hide show
  1. data/CHANGELOG +105 -34
  2. data/examples/performance.rb +3 -39
  3. data/examples/simple.rb +14 -0
  4. data/lib/active_record.rb +81 -47
  5. data/lib/active_record/aggregations.rb +1 -3
  6. data/lib/active_record/association_preload.rb +39 -54
  7. data/lib/active_record/associations.rb +262 -419
  8. data/lib/active_record/associations/association_collection.rb +85 -100
  9. data/lib/active_record/associations/association_proxy.rb +20 -18
  10. data/lib/active_record/associations/belongs_to_association.rb +8 -8
  11. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +13 -35
  12. data/lib/active_record/associations/has_many_association.rb +11 -19
  13. data/lib/active_record/associations/has_many_through_association.rb +30 -183
  14. data/lib/active_record/associations/has_one_association.rb +10 -10
  15. data/lib/active_record/associations/has_one_through_association.rb +13 -11
  16. data/lib/active_record/associations/through_association_scope.rb +153 -0
  17. data/lib/active_record/attribute_methods.rb +17 -370
  18. data/lib/active_record/attribute_methods/before_type_cast.rb +33 -0
  19. data/lib/active_record/attribute_methods/dirty.rb +87 -0
  20. data/lib/active_record/attribute_methods/primary_key.rb +44 -0
  21. data/lib/active_record/attribute_methods/query.rb +37 -0
  22. data/lib/active_record/attribute_methods/read.rb +116 -0
  23. data/lib/active_record/attribute_methods/time_zone_conversion.rb +60 -0
  24. data/lib/active_record/attribute_methods/write.rb +37 -0
  25. data/lib/active_record/autosave_association.rb +20 -41
  26. data/lib/active_record/base.rb +357 -1180
  27. data/lib/active_record/batches.rb +10 -16
  28. data/lib/active_record/callbacks.rb +66 -126
  29. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +17 -13
  30. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +5 -25
  31. data/lib/active_record/connection_adapters/abstract/database_statements.rb +4 -43
  32. data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -2
  33. data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -4
  34. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
  35. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +18 -72
  36. data/lib/active_record/connection_adapters/abstract_adapter.rb +16 -49
  37. data/lib/active_record/connection_adapters/mysql_adapter.rb +15 -27
  38. data/lib/active_record/connection_adapters/postgresql_adapter.rb +84 -46
  39. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +9 -3
  40. data/lib/active_record/connection_adapters/sqlite_adapter.rb +34 -65
  41. data/lib/active_record/fixtures.rb +21 -25
  42. data/lib/active_record/locale/en.yml +9 -27
  43. data/lib/active_record/locking/optimistic.rb +16 -48
  44. data/lib/active_record/migration.rb +59 -46
  45. data/lib/active_record/named_scope.rb +85 -92
  46. data/lib/active_record/nested_attributes.rb +18 -24
  47. data/lib/active_record/observer.rb +18 -94
  48. data/lib/active_record/railtie.rb +83 -0
  49. data/lib/active_record/railties/controller_runtime.rb +38 -0
  50. data/lib/active_record/railties/databases.rake +477 -0
  51. data/lib/active_record/railties/subscriber.rb +27 -0
  52. data/lib/active_record/reflection.rb +2 -15
  53. data/lib/active_record/relation.rb +339 -0
  54. data/lib/active_record/relation/calculations.rb +259 -0
  55. data/lib/active_record/relation/finder_methods.rb +315 -0
  56. data/lib/active_record/relation/predicate_builder.rb +46 -0
  57. data/lib/active_record/relation/query_methods.rb +218 -0
  58. data/lib/active_record/relation/spawn_methods.rb +102 -0
  59. data/lib/active_record/schema_dumper.rb +10 -6
  60. data/lib/active_record/serialization.rb +31 -74
  61. data/lib/active_record/serializers/xml_serializer.rb +33 -121
  62. data/lib/active_record/session_store.rb +1 -9
  63. data/lib/active_record/test_case.rb +1 -3
  64. data/lib/active_record/timestamp.rb +7 -5
  65. data/lib/active_record/transactions.rb +9 -9
  66. data/lib/active_record/validations.rb +51 -1100
  67. data/lib/active_record/validations/associated.rb +47 -0
  68. data/lib/active_record/validations/uniqueness.rb +181 -0
  69. data/lib/active_record/version.rb +3 -3
  70. data/lib/generators/active_record.rb +30 -0
  71. data/lib/generators/active_record/migration/migration_generator.rb +25 -0
  72. data/lib/generators/active_record/migration/templates/migration.rb +11 -0
  73. data/lib/generators/active_record/model/model_generator.rb +33 -0
  74. data/lib/generators/active_record/model/templates/migration.rb +16 -0
  75. data/lib/generators/active_record/model/templates/model.rb +5 -0
  76. data/lib/generators/active_record/observer/observer_generator.rb +15 -0
  77. data/lib/generators/active_record/observer/templates/observer.rb +2 -0
  78. data/lib/generators/active_record/session_migration/session_migration_generator.rb +24 -0
  79. data/lib/generators/active_record/session_migration/templates/migration.rb +16 -0
  80. metadata +67 -325
  81. data/RUNNING_UNIT_TESTS +0 -36
  82. data/Rakefile +0 -268
  83. data/install.rb +0 -30
  84. data/lib/active_record/calculations.rb +0 -321
  85. data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -57
  86. data/lib/active_record/dirty.rb +0 -183
  87. data/lib/active_record/serializers/json_serializer.rb +0 -91
  88. data/lib/activerecord.rb +0 -2
  89. data/test/assets/example.log +0 -1
  90. data/test/assets/flowers.jpg +0 -0
  91. data/test/cases/aaa_create_tables_test.rb +0 -24
  92. data/test/cases/active_schema_test_mysql.rb +0 -122
  93. data/test/cases/active_schema_test_postgresql.rb +0 -24
  94. data/test/cases/adapter_test.rb +0 -144
  95. data/test/cases/aggregations_test.rb +0 -167
  96. data/test/cases/ar_schema_test.rb +0 -32
  97. data/test/cases/associations/belongs_to_associations_test.rb +0 -438
  98. data/test/cases/associations/callbacks_test.rb +0 -161
  99. data/test/cases/associations/cascaded_eager_loading_test.rb +0 -131
  100. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +0 -36
  101. data/test/cases/associations/eager_load_nested_include_test.rb +0 -131
  102. data/test/cases/associations/eager_load_nested_polymorphic_include.rb +0 -19
  103. data/test/cases/associations/eager_singularization_test.rb +0 -145
  104. data/test/cases/associations/eager_test.rb +0 -852
  105. data/test/cases/associations/extension_test.rb +0 -62
  106. data/test/cases/associations/habtm_join_table_test.rb +0 -56
  107. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +0 -827
  108. data/test/cases/associations/has_many_associations_test.rb +0 -1273
  109. data/test/cases/associations/has_many_through_associations_test.rb +0 -360
  110. data/test/cases/associations/has_one_associations_test.rb +0 -330
  111. data/test/cases/associations/has_one_through_associations_test.rb +0 -209
  112. data/test/cases/associations/inner_join_association_test.rb +0 -93
  113. data/test/cases/associations/inverse_associations_test.rb +0 -566
  114. data/test/cases/associations/join_model_test.rb +0 -712
  115. data/test/cases/associations_test.rb +0 -282
  116. data/test/cases/attribute_methods_test.rb +0 -305
  117. data/test/cases/autosave_association_test.rb +0 -1218
  118. data/test/cases/base_test.rb +0 -2166
  119. data/test/cases/batches_test.rb +0 -81
  120. data/test/cases/binary_test.rb +0 -30
  121. data/test/cases/calculations_test.rb +0 -360
  122. data/test/cases/callbacks_observers_test.rb +0 -38
  123. data/test/cases/callbacks_test.rb +0 -438
  124. data/test/cases/class_inheritable_attributes_test.rb +0 -32
  125. data/test/cases/column_alias_test.rb +0 -17
  126. data/test/cases/column_definition_test.rb +0 -70
  127. data/test/cases/connection_pool_test.rb +0 -25
  128. data/test/cases/connection_test_firebird.rb +0 -8
  129. data/test/cases/connection_test_mysql.rb +0 -65
  130. data/test/cases/copy_table_test_sqlite.rb +0 -80
  131. data/test/cases/counter_cache_test.rb +0 -84
  132. data/test/cases/database_statements_test.rb +0 -12
  133. data/test/cases/datatype_test_postgresql.rb +0 -204
  134. data/test/cases/date_time_test.rb +0 -37
  135. data/test/cases/default_test_firebird.rb +0 -16
  136. data/test/cases/defaults_test.rb +0 -111
  137. data/test/cases/deprecated_finder_test.rb +0 -30
  138. data/test/cases/dirty_test.rb +0 -316
  139. data/test/cases/finder_respond_to_test.rb +0 -76
  140. data/test/cases/finder_test.rb +0 -1098
  141. data/test/cases/fixtures_test.rb +0 -661
  142. data/test/cases/helper.rb +0 -68
  143. data/test/cases/i18n_test.rb +0 -46
  144. data/test/cases/inheritance_test.rb +0 -262
  145. data/test/cases/invalid_date_test.rb +0 -24
  146. data/test/cases/json_serialization_test.rb +0 -219
  147. data/test/cases/lifecycle_test.rb +0 -193
  148. data/test/cases/locking_test.rb +0 -350
  149. data/test/cases/method_scoping_test.rb +0 -704
  150. data/test/cases/migration_test.rb +0 -1649
  151. data/test/cases/migration_test_firebird.rb +0 -124
  152. data/test/cases/mixin_test.rb +0 -96
  153. data/test/cases/modules_test.rb +0 -109
  154. data/test/cases/multiple_db_test.rb +0 -85
  155. data/test/cases/named_scope_test.rb +0 -372
  156. data/test/cases/nested_attributes_test.rb +0 -840
  157. data/test/cases/pk_test.rb +0 -119
  158. data/test/cases/pooled_connections_test.rb +0 -103
  159. data/test/cases/query_cache_test.rb +0 -129
  160. data/test/cases/readonly_test.rb +0 -107
  161. data/test/cases/reflection_test.rb +0 -234
  162. data/test/cases/reload_models_test.rb +0 -22
  163. data/test/cases/repair_helper.rb +0 -50
  164. data/test/cases/reserved_word_test_mysql.rb +0 -176
  165. data/test/cases/sanitize_test.rb +0 -25
  166. data/test/cases/schema_authorization_test_postgresql.rb +0 -75
  167. data/test/cases/schema_dumper_test.rb +0 -211
  168. data/test/cases/schema_test_postgresql.rb +0 -178
  169. data/test/cases/serialization_test.rb +0 -47
  170. data/test/cases/sp_test_mysql.rb +0 -16
  171. data/test/cases/synonym_test_oracle.rb +0 -17
  172. data/test/cases/timestamp_test.rb +0 -75
  173. data/test/cases/transactions_test.rb +0 -543
  174. data/test/cases/unconnected_test.rb +0 -32
  175. data/test/cases/validations_i18n_test.rb +0 -925
  176. data/test/cases/validations_test.rb +0 -1684
  177. data/test/cases/xml_serialization_test.rb +0 -240
  178. data/test/cases/yaml_serialization_test.rb +0 -11
  179. data/test/config.rb +0 -5
  180. data/test/connections/jdbc_jdbcderby/connection.rb +0 -18
  181. data/test/connections/jdbc_jdbch2/connection.rb +0 -18
  182. data/test/connections/jdbc_jdbchsqldb/connection.rb +0 -18
  183. data/test/connections/jdbc_jdbcmysql/connection.rb +0 -26
  184. data/test/connections/jdbc_jdbcpostgresql/connection.rb +0 -26
  185. data/test/connections/jdbc_jdbcsqlite3/connection.rb +0 -25
  186. data/test/connections/native_db2/connection.rb +0 -25
  187. data/test/connections/native_firebird/connection.rb +0 -26
  188. data/test/connections/native_frontbase/connection.rb +0 -27
  189. data/test/connections/native_mysql/connection.rb +0 -25
  190. data/test/connections/native_openbase/connection.rb +0 -21
  191. data/test/connections/native_oracle/connection.rb +0 -27
  192. data/test/connections/native_postgresql/connection.rb +0 -21
  193. data/test/connections/native_sqlite/connection.rb +0 -25
  194. data/test/connections/native_sqlite3/connection.rb +0 -25
  195. data/test/connections/native_sqlite3/in_memory_connection.rb +0 -18
  196. data/test/connections/native_sybase/connection.rb +0 -23
  197. data/test/fixtures/accounts.yml +0 -29
  198. data/test/fixtures/all/developers.yml +0 -0
  199. data/test/fixtures/all/people.csv +0 -0
  200. data/test/fixtures/all/tasks.yml +0 -0
  201. data/test/fixtures/author_addresses.yml +0 -5
  202. data/test/fixtures/author_favorites.yml +0 -4
  203. data/test/fixtures/authors.yml +0 -9
  204. data/test/fixtures/binaries.yml +0 -132
  205. data/test/fixtures/books.yml +0 -7
  206. data/test/fixtures/categories.yml +0 -14
  207. data/test/fixtures/categories/special_categories.yml +0 -9
  208. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +0 -4
  209. data/test/fixtures/categories_ordered.yml +0 -7
  210. data/test/fixtures/categories_posts.yml +0 -23
  211. data/test/fixtures/categorizations.yml +0 -17
  212. data/test/fixtures/clubs.yml +0 -6
  213. data/test/fixtures/comments.yml +0 -59
  214. data/test/fixtures/companies.yml +0 -56
  215. data/test/fixtures/computers.yml +0 -4
  216. data/test/fixtures/courses.yml +0 -7
  217. data/test/fixtures/customers.yml +0 -26
  218. data/test/fixtures/developers.yml +0 -21
  219. data/test/fixtures/developers_projects.yml +0 -17
  220. data/test/fixtures/edges.yml +0 -6
  221. data/test/fixtures/entrants.yml +0 -14
  222. data/test/fixtures/faces.yml +0 -11
  223. data/test/fixtures/fk_test_has_fk.yml +0 -3
  224. data/test/fixtures/fk_test_has_pk.yml +0 -2
  225. data/test/fixtures/funny_jokes.yml +0 -10
  226. data/test/fixtures/interests.yml +0 -33
  227. data/test/fixtures/items.yml +0 -4
  228. data/test/fixtures/jobs.yml +0 -7
  229. data/test/fixtures/legacy_things.yml +0 -3
  230. data/test/fixtures/mateys.yml +0 -4
  231. data/test/fixtures/member_types.yml +0 -6
  232. data/test/fixtures/members.yml +0 -6
  233. data/test/fixtures/memberships.yml +0 -20
  234. data/test/fixtures/men.yml +0 -5
  235. data/test/fixtures/minimalistics.yml +0 -2
  236. data/test/fixtures/mixed_case_monkeys.yml +0 -6
  237. data/test/fixtures/mixins.yml +0 -29
  238. data/test/fixtures/movies.yml +0 -7
  239. data/test/fixtures/naked/csv/accounts.csv +0 -1
  240. data/test/fixtures/naked/yml/accounts.yml +0 -1
  241. data/test/fixtures/naked/yml/companies.yml +0 -1
  242. data/test/fixtures/naked/yml/courses.yml +0 -1
  243. data/test/fixtures/organizations.yml +0 -5
  244. data/test/fixtures/owners.yml +0 -7
  245. data/test/fixtures/parrots.yml +0 -27
  246. data/test/fixtures/parrots_pirates.yml +0 -7
  247. data/test/fixtures/people.yml +0 -15
  248. data/test/fixtures/pets.yml +0 -14
  249. data/test/fixtures/pirates.yml +0 -9
  250. data/test/fixtures/polymorphic_designs.yml +0 -19
  251. data/test/fixtures/polymorphic_prices.yml +0 -19
  252. data/test/fixtures/posts.yml +0 -52
  253. data/test/fixtures/price_estimates.yml +0 -7
  254. data/test/fixtures/projects.yml +0 -7
  255. data/test/fixtures/readers.yml +0 -9
  256. data/test/fixtures/references.yml +0 -17
  257. data/test/fixtures/reserved_words/distinct.yml +0 -5
  258. data/test/fixtures/reserved_words/distincts_selects.yml +0 -11
  259. data/test/fixtures/reserved_words/group.yml +0 -14
  260. data/test/fixtures/reserved_words/select.yml +0 -8
  261. data/test/fixtures/reserved_words/values.yml +0 -7
  262. data/test/fixtures/ships.yml +0 -5
  263. data/test/fixtures/sponsors.yml +0 -9
  264. data/test/fixtures/subscribers.yml +0 -7
  265. data/test/fixtures/subscriptions.yml +0 -12
  266. data/test/fixtures/taggings.yml +0 -28
  267. data/test/fixtures/tags.yml +0 -7
  268. data/test/fixtures/tasks.yml +0 -7
  269. data/test/fixtures/tees.yml +0 -4
  270. data/test/fixtures/ties.yml +0 -4
  271. data/test/fixtures/topics.yml +0 -42
  272. data/test/fixtures/toys.yml +0 -4
  273. data/test/fixtures/treasures.yml +0 -10
  274. data/test/fixtures/vertices.yml +0 -4
  275. data/test/fixtures/warehouse-things.yml +0 -3
  276. data/test/fixtures/zines.yml +0 -5
  277. data/test/migrations/broken/100_migration_that_raises_exception.rb +0 -10
  278. data/test/migrations/decimal/1_give_me_big_numbers.rb +0 -15
  279. data/test/migrations/duplicate/1_people_have_last_names.rb +0 -9
  280. data/test/migrations/duplicate/2_we_need_reminders.rb +0 -12
  281. data/test/migrations/duplicate/3_foo.rb +0 -7
  282. data/test/migrations/duplicate/3_innocent_jointable.rb +0 -12
  283. data/test/migrations/duplicate_names/20080507052938_chunky.rb +0 -7
  284. data/test/migrations/duplicate_names/20080507053028_chunky.rb +0 -7
  285. data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +0 -12
  286. data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +0 -9
  287. data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +0 -12
  288. data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +0 -9
  289. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +0 -8
  290. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +0 -12
  291. data/test/migrations/missing/1000_people_have_middle_names.rb +0 -9
  292. data/test/migrations/missing/1_people_have_last_names.rb +0 -9
  293. data/test/migrations/missing/3_we_need_reminders.rb +0 -12
  294. data/test/migrations/missing/4_innocent_jointable.rb +0 -12
  295. data/test/migrations/valid/1_people_have_last_names.rb +0 -9
  296. data/test/migrations/valid/2_we_need_reminders.rb +0 -12
  297. data/test/migrations/valid/3_innocent_jointable.rb +0 -12
  298. data/test/models/author.rb +0 -151
  299. data/test/models/auto_id.rb +0 -4
  300. data/test/models/binary.rb +0 -2
  301. data/test/models/bird.rb +0 -9
  302. data/test/models/book.rb +0 -4
  303. data/test/models/categorization.rb +0 -5
  304. data/test/models/category.rb +0 -34
  305. data/test/models/citation.rb +0 -6
  306. data/test/models/club.rb +0 -13
  307. data/test/models/column_name.rb +0 -3
  308. data/test/models/comment.rb +0 -29
  309. data/test/models/company.rb +0 -173
  310. data/test/models/company_in_module.rb +0 -78
  311. data/test/models/computer.rb +0 -3
  312. data/test/models/contact.rb +0 -16
  313. data/test/models/contract.rb +0 -5
  314. data/test/models/course.rb +0 -3
  315. data/test/models/customer.rb +0 -73
  316. data/test/models/default.rb +0 -2
  317. data/test/models/developer.rb +0 -101
  318. data/test/models/edge.rb +0 -5
  319. data/test/models/entrant.rb +0 -3
  320. data/test/models/essay.rb +0 -3
  321. data/test/models/event.rb +0 -3
  322. data/test/models/event_author.rb +0 -8
  323. data/test/models/face.rb +0 -7
  324. data/test/models/guid.rb +0 -2
  325. data/test/models/interest.rb +0 -5
  326. data/test/models/invoice.rb +0 -4
  327. data/test/models/item.rb +0 -7
  328. data/test/models/job.rb +0 -5
  329. data/test/models/joke.rb +0 -3
  330. data/test/models/keyboard.rb +0 -3
  331. data/test/models/legacy_thing.rb +0 -3
  332. data/test/models/line_item.rb +0 -3
  333. data/test/models/man.rb +0 -9
  334. data/test/models/matey.rb +0 -4
  335. data/test/models/member.rb +0 -12
  336. data/test/models/member_detail.rb +0 -5
  337. data/test/models/member_type.rb +0 -3
  338. data/test/models/membership.rb +0 -9
  339. data/test/models/minimalistic.rb +0 -2
  340. data/test/models/mixed_case_monkey.rb +0 -3
  341. data/test/models/movie.rb +0 -5
  342. data/test/models/order.rb +0 -4
  343. data/test/models/organization.rb +0 -6
  344. data/test/models/owner.rb +0 -5
  345. data/test/models/parrot.rb +0 -22
  346. data/test/models/person.rb +0 -16
  347. data/test/models/pet.rb +0 -5
  348. data/test/models/pirate.rb +0 -80
  349. data/test/models/polymorphic_design.rb +0 -3
  350. data/test/models/polymorphic_price.rb +0 -3
  351. data/test/models/post.rb +0 -102
  352. data/test/models/price_estimate.rb +0 -3
  353. data/test/models/project.rb +0 -30
  354. data/test/models/reader.rb +0 -4
  355. data/test/models/reference.rb +0 -4
  356. data/test/models/reply.rb +0 -46
  357. data/test/models/ship.rb +0 -19
  358. data/test/models/ship_part.rb +0 -7
  359. data/test/models/sponsor.rb +0 -4
  360. data/test/models/subject.rb +0 -4
  361. data/test/models/subscriber.rb +0 -8
  362. data/test/models/subscription.rb +0 -4
  363. data/test/models/tag.rb +0 -7
  364. data/test/models/tagging.rb +0 -10
  365. data/test/models/task.rb +0 -3
  366. data/test/models/tee.rb +0 -4
  367. data/test/models/tie.rb +0 -4
  368. data/test/models/topic.rb +0 -80
  369. data/test/models/toy.rb +0 -6
  370. data/test/models/treasure.rb +0 -8
  371. data/test/models/vertex.rb +0 -9
  372. data/test/models/warehouse_thing.rb +0 -5
  373. data/test/models/zine.rb +0 -3
  374. data/test/schema/mysql_specific_schema.rb +0 -31
  375. data/test/schema/postgresql_specific_schema.rb +0 -114
  376. data/test/schema/schema.rb +0 -550
  377. data/test/schema/schema2.rb +0 -6
  378. data/test/schema/sqlite_specific_schema.rb +0 -25
@@ -3,7 +3,7 @@ require 'yaml'
3
3
  require 'csv'
4
4
  require 'zlib'
5
5
  require 'active_support/dependencies'
6
- require 'active_support/test_case'
6
+ require 'active_support/core_ext/logger'
7
7
 
8
8
  if RUBY_VERSION < '1.9'
9
9
  module YAML #:nodoc:
@@ -335,7 +335,6 @@ end
335
335
  # george:
336
336
  # id: 1
337
337
  # name: George the Monkey
338
- # pirate_id: 1
339
338
  #
340
339
  # ### in fruits.yml
341
340
  #
@@ -370,8 +369,8 @@ end
370
369
  # ### in monkeys.yml
371
370
  #
372
371
  # george:
372
+ # id: 1
373
373
  # name: George the Monkey
374
- # pirate: reginald
375
374
  # fruits: apple, orange, grape
376
375
  #
377
376
  # ### in fruits.yml
@@ -408,7 +407,7 @@ end
408
407
  # subdomain: $LABEL
409
408
  #
410
409
  # Also, sometimes (like when porting older join table fixtures) you'll need
411
- # to be able to get ahold of the identifier for a given label. ERB
410
+ # to be able to get a hold of the identifier for a given label. ERB
412
411
  # to the rescue:
413
412
  #
414
413
  # george_reginald:
@@ -808,27 +807,25 @@ end
808
807
 
809
808
  module ActiveRecord
810
809
  module TestFixtures
811
- def self.included(base)
812
- base.class_eval do
813
- setup :setup_fixtures
814
- teardown :teardown_fixtures
815
-
816
- superclass_delegating_accessor :fixture_path
817
- superclass_delegating_accessor :fixture_table_names
818
- superclass_delegating_accessor :fixture_class_names
819
- superclass_delegating_accessor :use_transactional_fixtures
820
- superclass_delegating_accessor :use_instantiated_fixtures # true, false, or :no_instances
821
- superclass_delegating_accessor :pre_loaded_fixtures
822
-
823
- self.fixture_table_names = []
824
- self.use_transactional_fixtures = false
825
- self.use_instantiated_fixtures = true
826
- self.pre_loaded_fixtures = false
827
-
828
- self.fixture_class_names = {}
829
- end
810
+ extend ActiveSupport::Concern
811
+
812
+ included do
813
+ setup :setup_fixtures
814
+ teardown :teardown_fixtures
815
+
816
+ superclass_delegating_accessor :fixture_path
817
+ superclass_delegating_accessor :fixture_table_names
818
+ superclass_delegating_accessor :fixture_class_names
819
+ superclass_delegating_accessor :use_transactional_fixtures
820
+ superclass_delegating_accessor :use_instantiated_fixtures # true, false, or :no_instances
821
+ superclass_delegating_accessor :pre_loaded_fixtures
822
+
823
+ self.fixture_table_names = []
824
+ self.use_transactional_fixtures = true
825
+ self.use_instantiated_fixtures = false
826
+ self.pre_loaded_fixtures = false
830
827
 
831
- base.extend ClassMethods
828
+ self.fixture_class_names = {}
832
829
  end
833
830
 
834
831
  module ClassMethods
@@ -891,7 +888,6 @@ module ActiveRecord
891
888
 
892
889
  instances.size == 1 ? instances.first : instances
893
890
  end
894
- private table_name
895
891
  end
896
892
  end
897
893
 
@@ -1,48 +1,31 @@
1
1
  en:
2
+ # Attributes names common to most models
3
+ #attributes:
4
+ #created_at: "Created at"
5
+ #updated_at: "Updated at"
6
+
7
+ # ActiveRecord models configuration
2
8
  activerecord:
3
9
  errors:
4
- # The values :model, :attribute and :value are always available for interpolation
5
- # The value :count is available when applicable. Can be used for pluralization.
6
10
  messages:
7
- inclusion: "is not included in the list"
8
- exclusion: "is reserved"
9
- invalid: "is invalid"
10
- confirmation: "doesn't match confirmation"
11
- accepted: "must be accepted"
12
- empty: "can't be empty"
13
- blank: "can't be blank"
14
- too_long: "is too long (maximum is %{count} characters)"
15
- too_short: "is too short (minimum is %{count} characters)"
16
- wrong_length: "is the wrong length (should be %{count} characters)"
17
11
  taken: "has already been taken"
18
- not_a_number: "is not a number"
19
- greater_than: "must be greater than %{count}"
20
- greater_than_or_equal_to: "must be greater than or equal to %{count}"
21
- equal_to: "must be equal to %{count}"
22
- less_than: "must be less than %{count}"
23
- less_than_or_equal_to: "must be less than or equal to %{count}"
24
- odd: "must be odd"
25
- even: "must be even"
26
- record_invalid: "Validation failed: %{errors}"
12
+ record_invalid: "Validation failed: {{errors}}"
27
13
  # Append your own errors here or at the model/attributes scope.
28
14
 
29
- full_messages:
30
- format: "%{attribute} %{message}"
31
-
32
15
  # You can define own errors for models or model attributes.
33
16
  # The values :model, :attribute and :value are always available for interpolation.
34
17
  #
35
18
  # For example,
36
19
  # models:
37
20
  # user:
38
- # blank: "This is a custom blank message for %{model}: %{attribute}"
21
+ # blank: "This is a custom blank message for {{model}}: {{attribute}}"
39
22
  # attributes:
40
23
  # login:
41
24
  # blank: "This is a custom blank message for User login"
42
25
  # Will define custom blank validation message for User model and
43
26
  # custom blank validation message for login attribute of User model.
44
27
  #models:
45
-
28
+
46
29
  # Translate model names. Used in Model.human_name().
47
30
  #models:
48
31
  # For example,
@@ -55,4 +38,3 @@ en:
55
38
  # user:
56
39
  # login: "Handle"
57
40
  # will translate User attribute "login" as "Handle"
58
-
@@ -23,16 +23,6 @@ module ActiveRecord
23
23
  # p2.first_name = "should fail"
24
24
  # p2.save # Raises a ActiveRecord::StaleObjectError
25
25
  #
26
- # Optimistic locking will also check for stale data when objects are destroyed. Example:
27
- #
28
- # p1 = Person.find(1)
29
- # p2 = Person.find(1)
30
- #
31
- # p1.first_name = "Michael"
32
- # p1.save
33
- #
34
- # p2.destroy # Raises a ActiveRecord::StaleObjectError
35
- #
36
26
  # You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging,
37
27
  # or otherwise apply the business logic needed to resolve the conflict.
38
28
  #
@@ -42,17 +32,16 @@ module ActiveRecord
42
32
  # To override the name of the lock_version column, invoke the <tt>set_locking_column</tt> method.
43
33
  # This method uses the same syntax as <tt>set_table_name</tt>
44
34
  module Optimistic
45
- def self.included(base) #:nodoc:
46
- base.extend ClassMethods
35
+ extend ActiveSupport::Concern
47
36
 
48
- base.cattr_accessor :lock_optimistically, :instance_writer => false
49
- base.lock_optimistically = true
37
+ included do
38
+ cattr_accessor :lock_optimistically, :instance_writer => false
39
+ self.lock_optimistically = true
50
40
 
51
- base.alias_method_chain :update, :lock
52
- base.alias_method_chain :destroy, :lock
53
- base.alias_method_chain :attributes_from_column_definition, :lock
41
+ alias_method_chain :update, :lock
42
+ alias_method_chain :attributes_from_column_definition, :lock
54
43
 
55
- class << base
44
+ class << self
56
45
  alias_method :locking_column=, :set_locking_column
57
46
  end
58
47
  end
@@ -89,15 +78,17 @@ module ActiveRecord
89
78
  attribute_names.uniq!
90
79
 
91
80
  begin
92
- affected_rows = connection.update(<<-end_sql, "#{self.class.name} Update with optimistic locking")
93
- UPDATE #{self.class.quoted_table_name}
94
- SET #{quoted_comma_pair_list(connection, attributes_with_quotes(false, false, attribute_names))}
95
- WHERE #{self.class.primary_key} = #{quote_value(id)}
96
- AND #{self.class.quoted_locking_column} = #{quote_value(previous_value)}
97
- end_sql
81
+ relation = self.class.unscoped
82
+
83
+ affected_rows = relation.where(
84
+ relation.table[self.class.primary_key].eq(quoted_id).and(
85
+ relation.table[self.class.locking_column].eq(quote_value(previous_value))
86
+ )
87
+ ).arel.update(arel_attributes_values(false, false, attribute_names))
88
+
98
89
 
99
90
  unless affected_rows == 1
100
- raise ActiveRecord::StaleObjectError, "Attempted to update a stale object: #{self.class.name}"
91
+ raise ActiveRecord::StaleObjectError, "Attempted to update a stale object"
101
92
  end
102
93
 
103
94
  affected_rows
@@ -109,29 +100,6 @@ module ActiveRecord
109
100
  end
110
101
  end
111
102
 
112
- def destroy_with_lock #:nodoc:
113
- return destroy_without_lock unless locking_enabled?
114
-
115
- unless new_record?
116
- lock_col = self.class.locking_column
117
- previous_value = send(lock_col).to_i
118
-
119
- affected_rows = connection.delete(
120
- "DELETE FROM #{self.class.quoted_table_name} " +
121
- "WHERE #{connection.quote_column_name(self.class.primary_key)} = #{quoted_id} " +
122
- "AND #{self.class.quoted_locking_column} = #{quote_value(previous_value)}",
123
- "#{self.class.name} Destroy"
124
- )
125
-
126
- unless affected_rows == 1
127
- raise ActiveRecord::StaleObjectError, "Attempted to delete a stale object: #{self.class.name}"
128
- end
129
- end
130
-
131
- @destroyed = true
132
- freeze
133
- end
134
-
135
103
  module ClassMethods
136
104
  DEFAULT_LOCKING_COLUMN = 'lock_version'
137
105
 
@@ -1,5 +1,8 @@
1
+ require 'active_support/core_ext/object/metaclass'
2
+
1
3
  module ActiveRecord
2
- class IrreversibleMigration < ActiveRecordError#:nodoc:
4
+ # Exception that can be raised to stop migrations from going backwards.
5
+ class IrreversibleMigration < ActiveRecordError
3
6
  end
4
7
 
5
8
  class DuplicateMigrationVersionError < ActiveRecordError#:nodoc:
@@ -103,12 +106,12 @@ module ActiveRecord
103
106
  #
104
107
  # The Rails package has several tools to help create and apply migrations.
105
108
  #
106
- # To generate a new migration, you can use
109
+ # To generate a new migration, you can use
107
110
  # script/generate migration MyNewMigration
108
111
  #
109
112
  # where MyNewMigration is the name of your migration. The generator will
110
- # create an empty migration file <tt>nnn_my_new_migration.rb</tt> in the <tt>db/migrate/</tt>
111
- # directory where <tt>nnn</tt> is the next largest migration number.
113
+ # create an empty migration file <tt>timestamp_my_new_migration.rb</tt> in the <tt>db/migrate/</tt>
114
+ # directory where <tt>timestamp</tt> is the UTC formatted date and time that the migration was generated.
112
115
  #
113
116
  # You may then edit the <tt>self.up</tt> and <tt>self.down</tt> methods of
114
117
  # MyNewMigration.
@@ -116,21 +119,21 @@ module ActiveRecord
116
119
  # There is a special syntactic shortcut to generate migrations that add fields to a table.
117
120
  # script/generate migration add_fieldname_to_tablename fieldname:string
118
121
  #
119
- # This will generate the file <tt>nnn_add_fieldname_to_tablename</tt>, which will look like this:
122
+ # This will generate the file <tt>timestamp_add_fieldname_to_tablename</tt>, which will look like this:
120
123
  # class AddFieldnameToTablename < ActiveRecord::Migration
121
124
  # def self.up
122
125
  # add_column :tablenames, :fieldname, :string
123
126
  # end
124
- #
127
+ #
125
128
  # def self.down
126
129
  # remove_column :tablenames, :fieldname
127
130
  # end
128
131
  # end
129
- #
132
+ #
130
133
  # To run migrations against the currently configured database, use
131
134
  # <tt>rake db:migrate</tt>. This will update the database by running all of the
132
135
  # pending migrations, creating the <tt>schema_migrations</tt> table
133
- # (see "About the schema_migrations table" section below) if missing. It will also
136
+ # (see "About the schema_migrations table" section below) if missing. It will also
134
137
  # invoke the db:schema:dump task, which will update your db/schema.rb file
135
138
  # to match the structure of your database.
136
139
  #
@@ -240,7 +243,7 @@ module ActiveRecord
240
243
  # lower than the current schema version: when migrating up, those
241
244
  # never-applied "interleaved" migrations will be automatically applied, and
242
245
  # when migrating down, never-applied "interleaved" migrations will be skipped.
243
- #
246
+ #
244
247
  # == Timestamped Migrations
245
248
  #
246
249
  # By default, Rails generates migrations that look like:
@@ -253,7 +256,7 @@ module ActiveRecord
253
256
  # off by setting:
254
257
  #
255
258
  # config.active_record.timestamped_migrations = false
256
- #
259
+ #
257
260
  # In environment.rb.
258
261
  #
259
262
  class Migration
@@ -300,8 +303,7 @@ module ActiveRecord
300
303
 
301
304
  case sym
302
305
  when :up, :down
303
- klass = (class << self; self; end)
304
- klass.send(:alias_method_chain, sym, "benchmarks")
306
+ metaclass.send(:alias_method_chain, sym, "benchmarks")
305
307
  end
306
308
  ensure
307
309
  @ignore_new_methods = false
@@ -381,20 +383,17 @@ module ActiveRecord
381
383
  def migrate(migrations_path, target_version = nil)
382
384
  case
383
385
  when target_version.nil? then up(migrations_path, target_version)
384
- when current_version == 0 && target_version == 0 then # noop
385
386
  when current_version > target_version then down(migrations_path, target_version)
386
387
  else up(migrations_path, target_version)
387
388
  end
388
389
  end
389
390
 
390
391
  def rollback(migrations_path, steps=1)
391
- migrator = self.new(:down, migrations_path)
392
- start_index = migrator.migrations.index(migrator.current_migration)
393
-
394
- return unless start_index
395
-
396
- finish = migrator.migrations[start_index + steps]
397
- down(migrations_path, finish ? finish.version : 0)
392
+ move(:down, migrations_path, steps)
393
+ end
394
+
395
+ def forward(migrations_path, steps=1)
396
+ move(:up, migrations_path, steps)
398
397
  end
399
398
 
400
399
  def up(migrations_path, target_version = nil)
@@ -404,7 +403,7 @@ module ActiveRecord
404
403
  def down(migrations_path, target_version = nil)
405
404
  self.new(:down, migrations_path, target_version).migrate
406
405
  end
407
-
406
+
408
407
  def run(direction, migrations_path, target_version)
409
408
  self.new(direction, migrations_path, target_version).run
410
409
  end
@@ -418,7 +417,8 @@ module ActiveRecord
418
417
  end
419
418
 
420
419
  def get_all_versions
421
- Base.connection.select_values("SELECT version FROM #{schema_migrations_table_name}").map(&:to_i).sort
420
+ table = Arel::Table.new(schema_migrations_table_name)
421
+ Base.connection.select_values(table.project(table['version']).to_sql).map(&:to_i).sort
422
422
  end
423
423
 
424
424
  def current_version
@@ -434,22 +434,35 @@ module ActiveRecord
434
434
  # Use the Active Record objects own table_name, or pre/suffix from ActiveRecord::Base if name is a symbol/string
435
435
  name.table_name rescue "#{ActiveRecord::Base.table_name_prefix}#{name}#{ActiveRecord::Base.table_name_suffix}"
436
436
  end
437
+
438
+ private
439
+
440
+ def move(direction, migrations_path, steps)
441
+ migrator = self.new(direction, migrations_path)
442
+ start_index = migrator.migrations.index(migrator.current_migration)
443
+
444
+ if start_index
445
+ finish = migrator.migrations[start_index + steps]
446
+ version = finish ? finish.version : 0
447
+ send(direction, migrations_path, version)
448
+ end
449
+ end
437
450
  end
438
451
 
439
452
  def initialize(direction, migrations_path, target_version = nil)
440
453
  raise StandardError.new("This database does not yet support migrations") unless Base.connection.supports_migrations?
441
454
  Base.connection.initialize_schema_migrations_table
442
- @direction, @migrations_path, @target_version = direction, migrations_path, target_version
455
+ @direction, @migrations_path, @target_version = direction, migrations_path, target_version
443
456
  end
444
457
 
445
458
  def current_version
446
459
  migrated.last || 0
447
460
  end
448
-
461
+
449
462
  def current_migration
450
463
  migrations.detect { |m| m.version == current_version }
451
464
  end
452
-
465
+
453
466
  def run
454
467
  target = migrations.detect { |m| m.version == @target_version }
455
468
  raise UnknownMigrationVersionError.new(@target_version) if target.nil?
@@ -466,16 +479,16 @@ module ActiveRecord
466
479
  if target.nil? && !@target_version.nil? && @target_version > 0
467
480
  raise UnknownMigrationVersionError.new(@target_version)
468
481
  end
469
-
482
+
470
483
  start = up? ? 0 : (migrations.index(current) || 0)
471
484
  finish = migrations.index(target) || migrations.size - 1
472
485
  runnable = migrations[start..finish]
473
-
486
+
474
487
  # skip the last migration if we're headed down, but not ALL the way down
475
488
  runnable.pop if down? && !target.nil?
476
-
489
+
477
490
  runnable.each do |migration|
478
- Base.logger.info "Migrating to #{migration.name} (#{migration.version})"
491
+ Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
479
492
 
480
493
  # On our way up, we skip migrating the ones we've already migrated
481
494
  next if up? && migrated.include?(migration.version.to_i)
@@ -501,28 +514,28 @@ module ActiveRecord
501
514
  def migrations
502
515
  @migrations ||= begin
503
516
  files = Dir["#{@migrations_path}/[0-9]*_*.rb"]
504
-
517
+
505
518
  migrations = files.inject([]) do |klasses, file|
506
519
  version, name = file.scan(/([0-9]+)_([_a-z0-9]*).rb/).first
507
-
520
+
508
521
  raise IllegalMigrationNameError.new(file) unless version
509
522
  version = version.to_i
510
-
523
+
511
524
  if klasses.detect { |m| m.version == version }
512
- raise DuplicateMigrationVersionError.new(version)
525
+ raise DuplicateMigrationVersionError.new(version)
513
526
  end
514
527
 
515
528
  if klasses.detect { |m| m.name == name.camelize }
516
- raise DuplicateMigrationNameError.new(name.camelize)
517
- end
518
-
519
- klasses << (MigrationProxy.new).tap do |migration|
520
- migration.name = name.camelize
521
- migration.version = version
522
- migration.filename = file
529
+ raise DuplicateMigrationNameError.new(name.camelize)
523
530
  end
531
+
532
+ migration = MigrationProxy.new
533
+ migration.name = name.camelize
534
+ migration.version = version
535
+ migration.filename = file
536
+ klasses << migration
524
537
  end
525
-
538
+
526
539
  migrations = migrations.sort_by(&:version)
527
540
  down? ? migrations.reverse : migrations
528
541
  end
@@ -539,15 +552,15 @@ module ActiveRecord
539
552
 
540
553
  private
541
554
  def record_version_state_after_migrating(version)
542
- sm_table = self.class.schema_migrations_table_name
555
+ table = Arel::Table.new(self.class.schema_migrations_table_name)
543
556
 
544
557
  @migrated_versions ||= []
545
558
  if down?
546
- @migrated_versions.delete(version.to_i)
547
- Base.connection.update("DELETE FROM #{sm_table} WHERE version = '#{version}'")
559
+ @migrated_versions.delete(version)
560
+ table.where(table["version"].eq(version.to_s)).delete
548
561
  else
549
- @migrated_versions.push(version.to_i).sort!
550
- Base.connection.insert("INSERT INTO #{sm_table} (version) VALUES ('#{version}')")
562
+ @migrated_versions.push(version).sort!
563
+ table.insert table["version"] => version.to_s
551
564
  end
552
565
  end
553
566