activerecord_csi 2.3.5.p6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. data/CHANGELOG +5858 -0
  2. data/README +351 -0
  3. data/RUNNING_UNIT_TESTS +36 -0
  4. data/Rakefile +270 -0
  5. data/examples/associations.png +0 -0
  6. data/examples/performance.rb +162 -0
  7. data/install.rb +30 -0
  8. data/lib/active_record/aggregations.rb +261 -0
  9. data/lib/active_record/association_preload.rb +389 -0
  10. data/lib/active_record/associations/association_collection.rb +475 -0
  11. data/lib/active_record/associations/association_proxy.rb +278 -0
  12. data/lib/active_record/associations/belongs_to_association.rb +76 -0
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +53 -0
  14. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +143 -0
  15. data/lib/active_record/associations/has_many_association.rb +122 -0
  16. data/lib/active_record/associations/has_many_through_association.rb +266 -0
  17. data/lib/active_record/associations/has_one_association.rb +133 -0
  18. data/lib/active_record/associations/has_one_through_association.rb +37 -0
  19. data/lib/active_record/associations.rb +2241 -0
  20. data/lib/active_record/attribute_methods.rb +388 -0
  21. data/lib/active_record/autosave_association.rb +364 -0
  22. data/lib/active_record/base.rb +3171 -0
  23. data/lib/active_record/batches.rb +81 -0
  24. data/lib/active_record/calculations.rb +311 -0
  25. data/lib/active_record/callbacks.rb +360 -0
  26. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +371 -0
  27. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +139 -0
  28. data/lib/active_record/connection_adapters/abstract/database_statements.rb +289 -0
  29. data/lib/active_record/connection_adapters/abstract/query_cache.rb +94 -0
  30. data/lib/active_record/connection_adapters/abstract/quoting.rb +69 -0
  31. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +722 -0
  32. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +434 -0
  33. data/lib/active_record/connection_adapters/abstract_adapter.rb +241 -0
  34. data/lib/active_record/connection_adapters/mysql_adapter.rb +630 -0
  35. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1113 -0
  36. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -0
  37. data/lib/active_record/connection_adapters/sqlite_adapter.rb +453 -0
  38. data/lib/active_record/dirty.rb +183 -0
  39. data/lib/active_record/dynamic_finder_match.rb +41 -0
  40. data/lib/active_record/dynamic_scope_match.rb +25 -0
  41. data/lib/active_record/fixtures.rb +996 -0
  42. data/lib/active_record/i18n_interpolation_deprecation.rb +26 -0
  43. data/lib/active_record/locale/en.yml +58 -0
  44. data/lib/active_record/locking/optimistic.rb +148 -0
  45. data/lib/active_record/locking/pessimistic.rb +55 -0
  46. data/lib/active_record/migration.rb +566 -0
  47. data/lib/active_record/named_scope.rb +192 -0
  48. data/lib/active_record/nested_attributes.rb +392 -0
  49. data/lib/active_record/observer.rb +197 -0
  50. data/lib/active_record/query_cache.rb +33 -0
  51. data/lib/active_record/reflection.rb +320 -0
  52. data/lib/active_record/schema.rb +51 -0
  53. data/lib/active_record/schema_dumper.rb +182 -0
  54. data/lib/active_record/serialization.rb +101 -0
  55. data/lib/active_record/serializers/json_serializer.rb +91 -0
  56. data/lib/active_record/serializers/xml_serializer.rb +357 -0
  57. data/lib/active_record/session_store.rb +326 -0
  58. data/lib/active_record/test_case.rb +66 -0
  59. data/lib/active_record/timestamp.rb +71 -0
  60. data/lib/active_record/transactions.rb +235 -0
  61. data/lib/active_record/validations.rb +1135 -0
  62. data/lib/active_record/version.rb +9 -0
  63. data/lib/active_record.rb +84 -0
  64. data/lib/activerecord.rb +2 -0
  65. data/test/assets/example.log +1 -0
  66. data/test/assets/flowers.jpg +0 -0
  67. data/test/cases/aaa_create_tables_test.rb +24 -0
  68. data/test/cases/active_schema_test_mysql.rb +100 -0
  69. data/test/cases/active_schema_test_postgresql.rb +24 -0
  70. data/test/cases/adapter_test.rb +145 -0
  71. data/test/cases/aggregations_test.rb +167 -0
  72. data/test/cases/ar_schema_test.rb +32 -0
  73. data/test/cases/associations/belongs_to_associations_test.rb +425 -0
  74. data/test/cases/associations/callbacks_test.rb +161 -0
  75. data/test/cases/associations/cascaded_eager_loading_test.rb +131 -0
  76. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -0
  77. data/test/cases/associations/eager_load_nested_include_test.rb +130 -0
  78. data/test/cases/associations/eager_singularization_test.rb +145 -0
  79. data/test/cases/associations/eager_test.rb +834 -0
  80. data/test/cases/associations/extension_test.rb +62 -0
  81. data/test/cases/associations/habtm_join_table_test.rb +56 -0
  82. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +822 -0
  83. data/test/cases/associations/has_many_associations_test.rb +1134 -0
  84. data/test/cases/associations/has_many_through_associations_test.rb +346 -0
  85. data/test/cases/associations/has_one_associations_test.rb +330 -0
  86. data/test/cases/associations/has_one_through_associations_test.rb +209 -0
  87. data/test/cases/associations/inner_join_association_test.rb +93 -0
  88. data/test/cases/associations/join_model_test.rb +712 -0
  89. data/test/cases/associations_test.rb +262 -0
  90. data/test/cases/attribute_methods_test.rb +305 -0
  91. data/test/cases/autosave_association_test.rb +1142 -0
  92. data/test/cases/base_test.rb +2154 -0
  93. data/test/cases/batches_test.rb +61 -0
  94. data/test/cases/binary_test.rb +30 -0
  95. data/test/cases/calculations_test.rb +348 -0
  96. data/test/cases/callbacks_observers_test.rb +38 -0
  97. data/test/cases/callbacks_test.rb +438 -0
  98. data/test/cases/class_inheritable_attributes_test.rb +32 -0
  99. data/test/cases/column_alias_test.rb +17 -0
  100. data/test/cases/column_definition_test.rb +70 -0
  101. data/test/cases/connection_pool_test.rb +25 -0
  102. data/test/cases/connection_test_firebird.rb +8 -0
  103. data/test/cases/connection_test_mysql.rb +64 -0
  104. data/test/cases/copy_table_test_sqlite.rb +80 -0
  105. data/test/cases/database_statements_test.rb +12 -0
  106. data/test/cases/datatype_test_postgresql.rb +204 -0
  107. data/test/cases/date_time_test.rb +37 -0
  108. data/test/cases/default_test_firebird.rb +16 -0
  109. data/test/cases/defaults_test.rb +111 -0
  110. data/test/cases/deprecated_finder_test.rb +30 -0
  111. data/test/cases/dirty_test.rb +316 -0
  112. data/test/cases/finder_respond_to_test.rb +76 -0
  113. data/test/cases/finder_test.rb +1066 -0
  114. data/test/cases/fixtures_test.rb +656 -0
  115. data/test/cases/helper.rb +68 -0
  116. data/test/cases/i18n_test.rb +46 -0
  117. data/test/cases/inheritance_test.rb +262 -0
  118. data/test/cases/invalid_date_test.rb +24 -0
  119. data/test/cases/json_serialization_test.rb +205 -0
  120. data/test/cases/lifecycle_test.rb +193 -0
  121. data/test/cases/locking_test.rb +304 -0
  122. data/test/cases/method_scoping_test.rb +704 -0
  123. data/test/cases/migration_test.rb +1523 -0
  124. data/test/cases/migration_test_firebird.rb +124 -0
  125. data/test/cases/mixin_test.rb +96 -0
  126. data/test/cases/modules_test.rb +81 -0
  127. data/test/cases/multiple_db_test.rb +85 -0
  128. data/test/cases/named_scope_test.rb +361 -0
  129. data/test/cases/nested_attributes_test.rb +581 -0
  130. data/test/cases/pk_test.rb +119 -0
  131. data/test/cases/pooled_connections_test.rb +103 -0
  132. data/test/cases/query_cache_test.rb +123 -0
  133. data/test/cases/readonly_test.rb +107 -0
  134. data/test/cases/reflection_test.rb +194 -0
  135. data/test/cases/reload_models_test.rb +22 -0
  136. data/test/cases/repair_helper.rb +50 -0
  137. data/test/cases/reserved_word_test_mysql.rb +176 -0
  138. data/test/cases/sanitize_test.rb +25 -0
  139. data/test/cases/schema_authorization_test_postgresql.rb +75 -0
  140. data/test/cases/schema_dumper_test.rb +211 -0
  141. data/test/cases/schema_test_postgresql.rb +178 -0
  142. data/test/cases/serialization_test.rb +47 -0
  143. data/test/cases/synonym_test_oracle.rb +17 -0
  144. data/test/cases/timestamp_test.rb +75 -0
  145. data/test/cases/transactions_test.rb +522 -0
  146. data/test/cases/unconnected_test.rb +32 -0
  147. data/test/cases/validations_i18n_test.rb +955 -0
  148. data/test/cases/validations_test.rb +1640 -0
  149. data/test/cases/xml_serialization_test.rb +240 -0
  150. data/test/config.rb +5 -0
  151. data/test/connections/jdbc_jdbcderby/connection.rb +18 -0
  152. data/test/connections/jdbc_jdbch2/connection.rb +18 -0
  153. data/test/connections/jdbc_jdbchsqldb/connection.rb +18 -0
  154. data/test/connections/jdbc_jdbcmysql/connection.rb +26 -0
  155. data/test/connections/jdbc_jdbcpostgresql/connection.rb +26 -0
  156. data/test/connections/jdbc_jdbcsqlite3/connection.rb +25 -0
  157. data/test/connections/native_db2/connection.rb +25 -0
  158. data/test/connections/native_firebird/connection.rb +26 -0
  159. data/test/connections/native_frontbase/connection.rb +27 -0
  160. data/test/connections/native_mysql/connection.rb +25 -0
  161. data/test/connections/native_openbase/connection.rb +21 -0
  162. data/test/connections/native_oracle/connection.rb +27 -0
  163. data/test/connections/native_postgresql/connection.rb +25 -0
  164. data/test/connections/native_sqlite/connection.rb +25 -0
  165. data/test/connections/native_sqlite3/connection.rb +25 -0
  166. data/test/connections/native_sqlite3/in_memory_connection.rb +18 -0
  167. data/test/connections/native_sybase/connection.rb +23 -0
  168. data/test/fixtures/accounts.yml +29 -0
  169. data/test/fixtures/all/developers.yml +0 -0
  170. data/test/fixtures/all/people.csv +0 -0
  171. data/test/fixtures/all/tasks.yml +0 -0
  172. data/test/fixtures/author_addresses.yml +5 -0
  173. data/test/fixtures/author_favorites.yml +4 -0
  174. data/test/fixtures/authors.yml +9 -0
  175. data/test/fixtures/binaries.yml +132 -0
  176. data/test/fixtures/books.yml +7 -0
  177. data/test/fixtures/categories/special_categories.yml +9 -0
  178. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  179. data/test/fixtures/categories.yml +14 -0
  180. data/test/fixtures/categories_ordered.yml +7 -0
  181. data/test/fixtures/categories_posts.yml +23 -0
  182. data/test/fixtures/categorizations.yml +17 -0
  183. data/test/fixtures/clubs.yml +6 -0
  184. data/test/fixtures/comments.yml +59 -0
  185. data/test/fixtures/companies.yml +56 -0
  186. data/test/fixtures/computers.yml +4 -0
  187. data/test/fixtures/courses.yml +7 -0
  188. data/test/fixtures/customers.yml +26 -0
  189. data/test/fixtures/developers.yml +21 -0
  190. data/test/fixtures/developers_projects.yml +17 -0
  191. data/test/fixtures/edges.yml +6 -0
  192. data/test/fixtures/entrants.yml +14 -0
  193. data/test/fixtures/fixture_database.sqlite3 +0 -0
  194. data/test/fixtures/fixture_database_2.sqlite3 +0 -0
  195. data/test/fixtures/fk_test_has_fk.yml +3 -0
  196. data/test/fixtures/fk_test_has_pk.yml +2 -0
  197. data/test/fixtures/funny_jokes.yml +10 -0
  198. data/test/fixtures/items.yml +4 -0
  199. data/test/fixtures/jobs.yml +7 -0
  200. data/test/fixtures/legacy_things.yml +3 -0
  201. data/test/fixtures/mateys.yml +4 -0
  202. data/test/fixtures/member_types.yml +6 -0
  203. data/test/fixtures/members.yml +6 -0
  204. data/test/fixtures/memberships.yml +20 -0
  205. data/test/fixtures/minimalistics.yml +2 -0
  206. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  207. data/test/fixtures/mixins.yml +29 -0
  208. data/test/fixtures/movies.yml +7 -0
  209. data/test/fixtures/naked/csv/accounts.csv +1 -0
  210. data/test/fixtures/naked/yml/accounts.yml +1 -0
  211. data/test/fixtures/naked/yml/companies.yml +1 -0
  212. data/test/fixtures/naked/yml/courses.yml +1 -0
  213. data/test/fixtures/organizations.yml +5 -0
  214. data/test/fixtures/owners.yml +7 -0
  215. data/test/fixtures/parrots.yml +27 -0
  216. data/test/fixtures/parrots_pirates.yml +7 -0
  217. data/test/fixtures/people.yml +15 -0
  218. data/test/fixtures/pets.yml +14 -0
  219. data/test/fixtures/pirates.yml +9 -0
  220. data/test/fixtures/posts.yml +52 -0
  221. data/test/fixtures/price_estimates.yml +7 -0
  222. data/test/fixtures/projects.yml +7 -0
  223. data/test/fixtures/readers.yml +9 -0
  224. data/test/fixtures/references.yml +17 -0
  225. data/test/fixtures/reserved_words/distinct.yml +5 -0
  226. data/test/fixtures/reserved_words/distincts_selects.yml +11 -0
  227. data/test/fixtures/reserved_words/group.yml +14 -0
  228. data/test/fixtures/reserved_words/select.yml +8 -0
  229. data/test/fixtures/reserved_words/values.yml +7 -0
  230. data/test/fixtures/ships.yml +5 -0
  231. data/test/fixtures/sponsors.yml +9 -0
  232. data/test/fixtures/subscribers.yml +7 -0
  233. data/test/fixtures/subscriptions.yml +12 -0
  234. data/test/fixtures/taggings.yml +28 -0
  235. data/test/fixtures/tags.yml +7 -0
  236. data/test/fixtures/tasks.yml +7 -0
  237. data/test/fixtures/topics.yml +42 -0
  238. data/test/fixtures/toys.yml +4 -0
  239. data/test/fixtures/treasures.yml +10 -0
  240. data/test/fixtures/vertices.yml +4 -0
  241. data/test/fixtures/warehouse-things.yml +3 -0
  242. data/test/migrations/broken/100_migration_that_raises_exception.rb +10 -0
  243. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -0
  244. data/test/migrations/duplicate/1_people_have_last_names.rb +9 -0
  245. data/test/migrations/duplicate/2_we_need_reminders.rb +12 -0
  246. data/test/migrations/duplicate/3_foo.rb +7 -0
  247. data/test/migrations/duplicate/3_innocent_jointable.rb +12 -0
  248. data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
  249. data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
  250. data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +12 -0
  251. data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +9 -0
  252. data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +12 -0
  253. data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +9 -0
  254. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +8 -0
  255. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +12 -0
  256. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -0
  257. data/test/migrations/missing/1_people_have_last_names.rb +9 -0
  258. data/test/migrations/missing/3_we_need_reminders.rb +12 -0
  259. data/test/migrations/missing/4_innocent_jointable.rb +12 -0
  260. data/test/migrations/valid/1_people_have_last_names.rb +9 -0
  261. data/test/migrations/valid/2_we_need_reminders.rb +12 -0
  262. data/test/migrations/valid/3_innocent_jointable.rb +12 -0
  263. data/test/models/author.rb +146 -0
  264. data/test/models/auto_id.rb +4 -0
  265. data/test/models/binary.rb +2 -0
  266. data/test/models/bird.rb +3 -0
  267. data/test/models/book.rb +4 -0
  268. data/test/models/categorization.rb +5 -0
  269. data/test/models/category.rb +34 -0
  270. data/test/models/citation.rb +6 -0
  271. data/test/models/club.rb +13 -0
  272. data/test/models/column_name.rb +3 -0
  273. data/test/models/comment.rb +29 -0
  274. data/test/models/company.rb +171 -0
  275. data/test/models/company_in_module.rb +61 -0
  276. data/test/models/computer.rb +3 -0
  277. data/test/models/contact.rb +16 -0
  278. data/test/models/contract.rb +5 -0
  279. data/test/models/course.rb +3 -0
  280. data/test/models/customer.rb +73 -0
  281. data/test/models/default.rb +2 -0
  282. data/test/models/developer.rb +101 -0
  283. data/test/models/edge.rb +5 -0
  284. data/test/models/entrant.rb +3 -0
  285. data/test/models/essay.rb +3 -0
  286. data/test/models/event.rb +3 -0
  287. data/test/models/guid.rb +2 -0
  288. data/test/models/item.rb +7 -0
  289. data/test/models/job.rb +5 -0
  290. data/test/models/joke.rb +3 -0
  291. data/test/models/keyboard.rb +3 -0
  292. data/test/models/legacy_thing.rb +3 -0
  293. data/test/models/matey.rb +4 -0
  294. data/test/models/member.rb +12 -0
  295. data/test/models/member_detail.rb +5 -0
  296. data/test/models/member_type.rb +3 -0
  297. data/test/models/membership.rb +9 -0
  298. data/test/models/minimalistic.rb +2 -0
  299. data/test/models/mixed_case_monkey.rb +3 -0
  300. data/test/models/movie.rb +5 -0
  301. data/test/models/order.rb +4 -0
  302. data/test/models/organization.rb +6 -0
  303. data/test/models/owner.rb +5 -0
  304. data/test/models/parrot.rb +16 -0
  305. data/test/models/person.rb +16 -0
  306. data/test/models/pet.rb +5 -0
  307. data/test/models/pirate.rb +70 -0
  308. data/test/models/post.rb +100 -0
  309. data/test/models/price_estimate.rb +3 -0
  310. data/test/models/project.rb +30 -0
  311. data/test/models/reader.rb +4 -0
  312. data/test/models/reference.rb +4 -0
  313. data/test/models/reply.rb +46 -0
  314. data/test/models/ship.rb +10 -0
  315. data/test/models/ship_part.rb +5 -0
  316. data/test/models/sponsor.rb +4 -0
  317. data/test/models/subject.rb +4 -0
  318. data/test/models/subscriber.rb +8 -0
  319. data/test/models/subscription.rb +4 -0
  320. data/test/models/tag.rb +7 -0
  321. data/test/models/tagging.rb +10 -0
  322. data/test/models/task.rb +3 -0
  323. data/test/models/topic.rb +80 -0
  324. data/test/models/toy.rb +6 -0
  325. data/test/models/treasure.rb +8 -0
  326. data/test/models/vertex.rb +9 -0
  327. data/test/models/warehouse_thing.rb +5 -0
  328. data/test/schema/mysql_specific_schema.rb +24 -0
  329. data/test/schema/postgresql_specific_schema.rb +114 -0
  330. data/test/schema/schema.rb +493 -0
  331. data/test/schema/schema2.rb +6 -0
  332. data/test/schema/sqlite_specific_schema.rb +25 -0
  333. metadata +420 -0
@@ -0,0 +1,103 @@
1
+ require "cases/helper"
2
+
3
+ class PooledConnectionsTest < ActiveRecord::TestCase
4
+ def setup
5
+ super
6
+ @connection = ActiveRecord::Base.remove_connection
7
+ end
8
+
9
+ def teardown
10
+ ActiveRecord::Base.clear_all_connections!
11
+ ActiveRecord::Base.establish_connection(@connection)
12
+ super
13
+ end
14
+
15
+ def checkout_connections
16
+ ActiveRecord::Base.establish_connection(@connection.merge({:pool => 2, :wait_timeout => 0.3}))
17
+ @connections = []
18
+ @timed_out = 0
19
+
20
+ 4.times do
21
+ Thread.new do
22
+ begin
23
+ @connections << ActiveRecord::Base.connection_pool.checkout
24
+ rescue ActiveRecord::ConnectionTimeoutError
25
+ @timed_out += 1
26
+ end
27
+ end.join
28
+ end
29
+ end
30
+
31
+ # Will deadlock due to lack of Monitor timeouts in 1.9
32
+ if RUBY_VERSION < '1.9'
33
+ def test_pooled_connection_checkout
34
+ checkout_connections
35
+ assert_equal @connections.length, 2
36
+ assert_equal @timed_out, 2
37
+ end
38
+ end
39
+
40
+ def checkout_checkin_connections(pool_size, threads)
41
+ ActiveRecord::Base.establish_connection(@connection.merge({:pool => pool_size, :wait_timeout => 0.5}))
42
+ @connection_count = 0
43
+ @timed_out = 0
44
+ threads.times do
45
+ Thread.new do
46
+ begin
47
+ conn = ActiveRecord::Base.connection_pool.checkout
48
+ sleep 0.1
49
+ ActiveRecord::Base.connection_pool.checkin conn
50
+ @connection_count += 1
51
+ rescue ActiveRecord::ConnectionTimeoutError
52
+ @timed_out += 1
53
+ end
54
+ end.join
55
+ end
56
+ end
57
+
58
+ def test_pooled_connection_checkin_one
59
+ checkout_checkin_connections 1, 2
60
+ assert_equal 2, @connection_count
61
+ assert_equal 0, @timed_out
62
+ end
63
+
64
+ def test_pooled_connection_checkin_two
65
+ checkout_checkin_connections 2, 3
66
+ assert_equal 3, @connection_count
67
+ assert_equal 0, @timed_out
68
+ end
69
+
70
+ def test_pooled_connection_checkout_existing_first
71
+ ActiveRecord::Base.establish_connection(@connection.merge({:pool => 1}))
72
+ conn_pool = ActiveRecord::Base.connection_pool
73
+ conn = conn_pool.checkout
74
+ conn_pool.checkin(conn)
75
+ conn = conn_pool.checkout
76
+ assert ActiveRecord::ConnectionAdapters::AbstractAdapter === conn
77
+ conn_pool.checkin(conn)
78
+ end
79
+
80
+ def test_not_connected_defined_connection_returns_false
81
+ ActiveRecord::Base.establish_connection(@connection)
82
+ assert ! ActiveRecord::Base.connected?
83
+ end
84
+
85
+ def test_undefined_connection_returns_false
86
+ old_handler = ActiveRecord::Base.connection_handler
87
+ ActiveRecord::Base.connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
88
+ assert_equal false, ActiveRecord::Base.connected?
89
+ ensure
90
+ ActiveRecord::Base.connection_handler = old_handler
91
+ end
92
+ end unless %w(FrontBase).include? ActiveRecord::Base.connection.adapter_name
93
+
94
+ class AllowConcurrencyDeprecatedTest < ActiveRecord::TestCase
95
+ def test_allow_concurrency_is_deprecated
96
+ assert_deprecated('ActiveRecord::Base.allow_concurrency') do
97
+ ActiveRecord::Base.allow_concurrency
98
+ end
99
+ assert_deprecated('ActiveRecord::Base.allow_concurrency=') do
100
+ ActiveRecord::Base.allow_concurrency = true
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,123 @@
1
+ require "cases/helper"
2
+ require 'models/topic'
3
+ require 'models/reply'
4
+ require 'models/task'
5
+ require 'models/course'
6
+ require 'models/category'
7
+ require 'models/post'
8
+
9
+
10
+ class QueryCacheTest < ActiveRecord::TestCase
11
+ fixtures :tasks, :topics, :categories, :posts, :categories_posts
12
+
13
+ def test_find_queries
14
+ assert_queries(2) { Task.find(1); Task.find(1) }
15
+ end
16
+
17
+ def test_find_queries_with_cache
18
+ Task.cache do
19
+ assert_queries(1) { Task.find(1); Task.find(1) }
20
+ end
21
+ end
22
+
23
+ def test_count_queries_with_cache
24
+ Task.cache do
25
+ assert_queries(1) { Task.count; Task.count }
26
+ end
27
+ end
28
+
29
+ def test_query_cache_dups_results_correctly
30
+ Task.cache do
31
+ now = Time.now.utc
32
+ task = Task.find 1
33
+ assert_not_equal now, task.starting
34
+ task.starting = now
35
+ task.reload
36
+ assert_not_equal now, task.starting
37
+ end
38
+ end
39
+
40
+ def test_cache_is_flat
41
+ Task.cache do
42
+ Topic.columns # don't count this query
43
+ assert_queries(1) { Topic.find(1); Topic.find(1); }
44
+ end
45
+
46
+ ActiveRecord::Base.cache do
47
+ assert_queries(1) { Task.find(1); Task.find(1) }
48
+ end
49
+ end
50
+
51
+ def test_cache_does_not_wrap_string_results_in_arrays
52
+ Task.cache do
53
+ assert_instance_of String, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
54
+ end
55
+ end
56
+ end
57
+
58
+ class QueryCacheExpiryTest < ActiveRecord::TestCase
59
+ fixtures :tasks, :posts, :categories, :categories_posts
60
+
61
+ def test_find
62
+ Task.connection.expects(:clear_query_cache).times(1)
63
+
64
+ assert !Task.connection.query_cache_enabled
65
+ Task.cache do
66
+ assert Task.connection.query_cache_enabled
67
+ Task.find(1)
68
+
69
+ Task.uncached do
70
+ assert !Task.connection.query_cache_enabled
71
+ Task.find(1)
72
+ end
73
+
74
+ assert Task.connection.query_cache_enabled
75
+ end
76
+ assert !Task.connection.query_cache_enabled
77
+ end
78
+
79
+ def test_update
80
+ Task.connection.expects(:clear_query_cache).times(2)
81
+
82
+ Task.cache do
83
+ task = Task.find(1)
84
+ task.starting = Time.now.utc
85
+ task.save!
86
+ end
87
+ end
88
+
89
+ def test_destroy
90
+ Task.connection.expects(:clear_query_cache).times(2)
91
+
92
+ Task.cache do
93
+ Task.find(1).destroy
94
+ end
95
+ end
96
+
97
+ def test_insert
98
+ ActiveRecord::Base.connection.expects(:clear_query_cache).times(2)
99
+
100
+ Task.cache do
101
+ Task.create!
102
+ end
103
+ end
104
+
105
+ def test_cache_is_expired_by_habtm_update
106
+ ActiveRecord::Base.connection.expects(:clear_query_cache).times(2)
107
+ ActiveRecord::Base.cache do
108
+ c = Category.find(:first)
109
+ p = Post.find(:first)
110
+ p.categories << c
111
+ end
112
+ end
113
+
114
+ def test_cache_is_expired_by_habtm_delete
115
+ ActiveRecord::Base.connection.expects(:clear_query_cache).times(2)
116
+ ActiveRecord::Base.cache do
117
+ c = Category.find(1)
118
+ p = Post.find(1)
119
+ assert p.categories.any?
120
+ p.categories.delete_all
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,107 @@
1
+ require "cases/helper"
2
+ require 'models/post'
3
+ require 'models/comment'
4
+ require 'models/developer'
5
+ require 'models/project'
6
+ require 'models/reader'
7
+ require 'models/person'
8
+
9
+ # Dummy class methods to test implicit association scoping.
10
+ def Comment.foo() find :first end
11
+ def Project.foo() find :first end
12
+
13
+
14
+ class ReadOnlyTest < ActiveRecord::TestCase
15
+ fixtures :posts, :comments, :developers, :projects, :developers_projects
16
+
17
+ def test_cant_save_readonly_record
18
+ dev = Developer.find(1)
19
+ assert !dev.readonly?
20
+
21
+ dev.readonly!
22
+ assert dev.readonly?
23
+
24
+ assert_nothing_raised do
25
+ dev.name = 'Luscious forbidden fruit.'
26
+ assert !dev.save
27
+ dev.name = 'Forbidden.'
28
+ end
29
+ assert_raise(ActiveRecord::ReadOnlyRecord) { dev.save }
30
+ assert_raise(ActiveRecord::ReadOnlyRecord) { dev.save! }
31
+ end
32
+
33
+
34
+ def test_find_with_readonly_option
35
+ Developer.find(:all).each { |d| assert !d.readonly? }
36
+ Developer.find(:all, :readonly => false).each { |d| assert !d.readonly? }
37
+ Developer.find(:all, :readonly => true).each { |d| assert d.readonly? }
38
+ end
39
+
40
+
41
+ def test_find_with_joins_option_implies_readonly
42
+ # Blank joins don't count.
43
+ Developer.find(:all, :joins => ' ').each { |d| assert !d.readonly? }
44
+ Developer.find(:all, :joins => ' ', :readonly => false).each { |d| assert !d.readonly? }
45
+
46
+ # Others do.
47
+ Developer.find(:all, :joins => ', projects').each { |d| assert d.readonly? }
48
+ Developer.find(:all, :joins => ', projects', :readonly => false).each { |d| assert !d.readonly? }
49
+ end
50
+
51
+
52
+ def test_habtm_find_readonly
53
+ dev = Developer.find(1)
54
+ assert !dev.projects.empty?
55
+ assert dev.projects.all?(&:readonly?)
56
+ assert dev.projects.find(:all).all?(&:readonly?)
57
+ assert dev.projects.find(:all, :readonly => true).all?(&:readonly?)
58
+ end
59
+
60
+ def test_has_many_find_readonly
61
+ post = Post.find(1)
62
+ assert !post.comments.empty?
63
+ assert !post.comments.any?(&:readonly?)
64
+ assert !post.comments.find(:all).any?(&:readonly?)
65
+ assert post.comments.find(:all, :readonly => true).all?(&:readonly?)
66
+ end
67
+
68
+ def test_has_many_with_through_is_not_implicitly_marked_readonly
69
+ assert people = Post.find(1).people
70
+ assert !people.any?(&:readonly?)
71
+ end
72
+
73
+ def test_readonly_scoping
74
+ Post.with_scope(:find => { :conditions => '1=1' }) do
75
+ assert !Post.find(1).readonly?
76
+ assert Post.find(1, :readonly => true).readonly?
77
+ assert !Post.find(1, :readonly => false).readonly?
78
+ end
79
+
80
+ Post.with_scope(:find => { :joins => ' ' }) do
81
+ assert !Post.find(1).readonly?
82
+ assert Post.find(1, :readonly => true).readonly?
83
+ assert !Post.find(1, :readonly => false).readonly?
84
+ end
85
+
86
+ # Oracle barfs on this because the join includes unqualified and
87
+ # conflicting column names
88
+ unless current_adapter?(:OracleAdapter)
89
+ Post.with_scope(:find => { :joins => ', developers' }) do
90
+ assert Post.find(1).readonly?
91
+ assert Post.find(1, :readonly => true).readonly?
92
+ assert !Post.find(1, :readonly => false).readonly?
93
+ end
94
+ end
95
+
96
+ Post.with_scope(:find => { :readonly => true }) do
97
+ assert Post.find(1).readonly?
98
+ assert Post.find(1, :readonly => true).readonly?
99
+ assert !Post.find(1, :readonly => false).readonly?
100
+ end
101
+ end
102
+
103
+ def test_association_collection_method_missing_scoping_not_readonly
104
+ assert !Developer.find(1).projects.foo.readonly?
105
+ assert !Post.find(1).comments.foo.readonly?
106
+ end
107
+ end
@@ -0,0 +1,194 @@
1
+ require "cases/helper"
2
+ require 'models/topic'
3
+ require 'models/customer'
4
+ require 'models/company'
5
+ require 'models/company_in_module'
6
+ require 'models/subscriber'
7
+ require 'models/pirate'
8
+
9
+ class ReflectionTest < ActiveRecord::TestCase
10
+ fixtures :topics, :customers, :companies, :subscribers
11
+
12
+ def setup
13
+ @first = Topic.find(1)
14
+ end
15
+
16
+ def test_column_null_not_null
17
+ subscriber = Subscriber.find(:first)
18
+ assert subscriber.column_for_attribute("name").null
19
+ assert !subscriber.column_for_attribute("nick").null
20
+ end
21
+
22
+ def test_read_attribute_names
23
+ assert_equal(
24
+ %w( id title author_name author_email_address bonus_time written_on last_read content approved replies_count parent_id parent_title type ).sort,
25
+ @first.attribute_names
26
+ )
27
+ end
28
+
29
+ def test_columns
30
+ assert_equal 13, Topic.columns.length
31
+ end
32
+
33
+ def test_columns_are_returned_in_the_order_they_were_declared
34
+ column_names = Topic.columns.map { |column| column.name }
35
+ assert_equal %w(id title author_name author_email_address written_on bonus_time last_read content approved replies_count parent_id parent_title type), column_names
36
+ end
37
+
38
+ def test_content_columns
39
+ content_columns = Topic.content_columns
40
+ content_column_names = content_columns.map {|column| column.name}
41
+ assert_equal 9, content_columns.length
42
+ assert_equal %w(title author_name author_email_address written_on bonus_time last_read content approved parent_title).sort, content_column_names.sort
43
+ end
44
+
45
+ def test_column_string_type_and_limit
46
+ assert_equal :string, @first.column_for_attribute("title").type
47
+ assert_equal 255, @first.column_for_attribute("title").limit
48
+ end
49
+
50
+ def test_column_null_not_null
51
+ subscriber = Subscriber.find(:first)
52
+ assert subscriber.column_for_attribute("name").null
53
+ assert !subscriber.column_for_attribute("nick").null
54
+ end
55
+
56
+ def test_human_name_for_column
57
+ assert_equal "Author name", @first.column_for_attribute("author_name").human_name
58
+ end
59
+
60
+ def test_integer_columns
61
+ assert_equal :integer, @first.column_for_attribute("id").type
62
+ end
63
+
64
+ def test_reflection_klass_for_nested_class_name
65
+ reflection = ActiveRecord::Reflection::MacroReflection.new(nil, nil, { :class_name => 'MyApplication::Business::Company' }, nil)
66
+ assert_nothing_raised do
67
+ assert_equal MyApplication::Business::Company, reflection.klass
68
+ end
69
+ end
70
+
71
+ def test_aggregation_reflection
72
+ reflection_for_address = ActiveRecord::Reflection::AggregateReflection.new(
73
+ :composed_of, :address, { :mapping => [ %w(address_street street), %w(address_city city), %w(address_country country) ] }, Customer
74
+ )
75
+
76
+ reflection_for_balance = ActiveRecord::Reflection::AggregateReflection.new(
77
+ :composed_of, :balance, { :class_name => "Money", :mapping => %w(balance amount) }, Customer
78
+ )
79
+
80
+ reflection_for_gps_location = ActiveRecord::Reflection::AggregateReflection.new(
81
+ :composed_of, :gps_location, { }, Customer
82
+ )
83
+
84
+ assert Customer.reflect_on_all_aggregations.include?(reflection_for_gps_location)
85
+ assert Customer.reflect_on_all_aggregations.include?(reflection_for_balance)
86
+ assert Customer.reflect_on_all_aggregations.include?(reflection_for_address)
87
+
88
+ assert_equal reflection_for_address, Customer.reflect_on_aggregation(:address)
89
+
90
+ assert_equal Address, Customer.reflect_on_aggregation(:address).klass
91
+
92
+ assert_equal Money, Customer.reflect_on_aggregation(:balance).klass
93
+ end
94
+
95
+ def test_reflect_on_all_autosave_associations
96
+ expected = Pirate.reflect_on_all_associations.select { |r| r.options[:autosave] }
97
+ received = Pirate.reflect_on_all_autosave_associations
98
+
99
+ assert !received.empty?
100
+ assert_not_equal Pirate.reflect_on_all_associations.length, received.length
101
+ assert_equal expected, received
102
+ end
103
+
104
+ def test_has_many_reflection
105
+ reflection_for_clients = ActiveRecord::Reflection::AssociationReflection.new(:has_many, :clients, { :order => "id", :dependent => :destroy }, Firm)
106
+
107
+ assert_equal reflection_for_clients, Firm.reflect_on_association(:clients)
108
+
109
+ assert_equal Client, Firm.reflect_on_association(:clients).klass
110
+ assert_equal 'companies', Firm.reflect_on_association(:clients).table_name
111
+
112
+ assert_equal Client, Firm.reflect_on_association(:clients_of_firm).klass
113
+ assert_equal 'companies', Firm.reflect_on_association(:clients_of_firm).table_name
114
+ end
115
+
116
+ def test_has_one_reflection
117
+ reflection_for_account = ActiveRecord::Reflection::AssociationReflection.new(:has_one, :account, { :foreign_key => "firm_id", :dependent => :destroy }, Firm)
118
+ assert_equal reflection_for_account, Firm.reflect_on_association(:account)
119
+
120
+ assert_equal Account, Firm.reflect_on_association(:account).klass
121
+ assert_equal 'accounts', Firm.reflect_on_association(:account).table_name
122
+ end
123
+
124
+ def test_belongs_to_inferred_foreign_key_from_assoc_name
125
+ Company.belongs_to :foo
126
+ assert_equal "foo_id", Company.reflect_on_association(:foo).primary_key_name
127
+ Company.belongs_to :bar, :class_name => "Xyzzy"
128
+ assert_equal "bar_id", Company.reflect_on_association(:bar).primary_key_name
129
+ Company.belongs_to :baz, :class_name => "Xyzzy", :foreign_key => "xyzzy_id"
130
+ assert_equal "xyzzy_id", Company.reflect_on_association(:baz).primary_key_name
131
+ end
132
+
133
+ def test_association_reflection_in_modules
134
+ assert_reflection MyApplication::Business::Firm,
135
+ :clients_of_firm,
136
+ :klass => MyApplication::Business::Client,
137
+ :class_name => 'Client',
138
+ :table_name => 'companies'
139
+
140
+ assert_reflection MyApplication::Billing::Account,
141
+ :firm,
142
+ :klass => MyApplication::Business::Firm,
143
+ :class_name => 'MyApplication::Business::Firm',
144
+ :table_name => 'companies'
145
+
146
+ assert_reflection MyApplication::Billing::Account,
147
+ :qualified_billing_firm,
148
+ :klass => MyApplication::Billing::Firm,
149
+ :class_name => 'MyApplication::Billing::Firm',
150
+ :table_name => 'companies'
151
+
152
+ assert_reflection MyApplication::Billing::Account,
153
+ :unqualified_billing_firm,
154
+ :klass => MyApplication::Billing::Firm,
155
+ :class_name => 'Firm',
156
+ :table_name => 'companies'
157
+
158
+ assert_reflection MyApplication::Billing::Account,
159
+ :nested_qualified_billing_firm,
160
+ :klass => MyApplication::Billing::Nested::Firm,
161
+ :class_name => 'MyApplication::Billing::Nested::Firm',
162
+ :table_name => 'companies'
163
+
164
+ assert_reflection MyApplication::Billing::Account,
165
+ :nested_unqualified_billing_firm,
166
+ :klass => MyApplication::Billing::Nested::Firm,
167
+ :class_name => 'Nested::Firm',
168
+ :table_name => 'companies'
169
+ end
170
+
171
+ def test_reflection_of_all_associations
172
+ # FIXME these assertions bust a lot
173
+ assert_equal 36, Firm.reflect_on_all_associations.size
174
+ assert_equal 26, Firm.reflect_on_all_associations(:has_many).size
175
+ assert_equal 10, Firm.reflect_on_all_associations(:has_one).size
176
+ assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size
177
+ end
178
+
179
+ def test_reflection_should_not_raise_error_when_compared_to_other_object
180
+ assert_nothing_raised { Firm.reflections[:clients] == Object.new }
181
+ end
182
+
183
+ def test_has_many_through_reflection
184
+ assert_kind_of ActiveRecord::Reflection::ThroughReflection, Subscriber.reflect_on_association(:books)
185
+ end
186
+
187
+ private
188
+ def assert_reflection(klass, association, options)
189
+ assert reflection = klass.reflect_on_association(association)
190
+ options.each do |method, value|
191
+ assert_equal(value, reflection.send(method))
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,22 @@
1
+ require "cases/helper"
2
+ require 'models/owner'
3
+ require 'models/pet'
4
+
5
+ class ReloadModelsTest < ActiveRecord::TestCase
6
+ fixtures :pets
7
+
8
+ def test_has_one_with_reload
9
+ pet = Pet.find_by_name('parrot')
10
+ pet.owner = Owner.find_by_name('ashley')
11
+
12
+ # Reload the class Owner, simulating auto-reloading of model classes in a
13
+ # development environment. Note that meanwhile the class Pet is not
14
+ # reloaded, simulating a class that is present in a plugin.
15
+ Object.class_eval { remove_const :Owner }
16
+ Kernel.load(File.expand_path(File.join(File.dirname(__FILE__), "../models/owner.rb")))
17
+
18
+ pet = Pet.find_by_name('parrot')
19
+ pet.owner = Owner.find_by_name('ashley')
20
+ assert_equal pet.owner, Owner.find_by_name('ashley')
21
+ end
22
+ end
@@ -0,0 +1,50 @@
1
+ module ActiveRecord
2
+ module Testing
3
+ module RepairHelper
4
+ def self.included(base)
5
+ base.class_eval do
6
+ extend ClassMethods
7
+ end
8
+ end
9
+
10
+ module Toolbox
11
+ def self.record_validations(*model_classes)
12
+ model_classes.inject({}) do |repair, klass|
13
+ repair[klass] ||= {}
14
+ [:validate, :validate_on_create, :validate_on_update].each do |callback|
15
+ the_callback = klass.instance_variable_get("@#{callback.to_s}_callbacks")
16
+ repair[klass][callback] = (the_callback.nil? ? nil : the_callback.dup)
17
+ end
18
+ repair
19
+ end
20
+ end
21
+
22
+ def self.reset_validations(recorded)
23
+ recorded.each do |klass, repairs|
24
+ [:validate, :validate_on_create, :validate_on_update].each do |callback|
25
+ klass.instance_variable_set("@#{callback.to_s}_callbacks", repairs[callback])
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ module ClassMethods
32
+ def repair_validations(*model_classes)
33
+ setup do
34
+ @validation_repairs = ActiveRecord::Testing::RepairHelper::Toolbox.record_validations(*model_classes)
35
+ end
36
+ teardown do
37
+ ActiveRecord::Testing::RepairHelper::Toolbox.reset_validations(@validation_repairs)
38
+ end
39
+ end
40
+ end
41
+
42
+ def repair_validations(*model_classes, &block)
43
+ validation_repairs = ActiveRecord::Testing::RepairHelper::Toolbox.record_validations(*model_classes)
44
+ return block.call
45
+ ensure
46
+ ActiveRecord::Testing::RepairHelper::Toolbox.reset_validations(validation_repairs)
47
+ end
48
+ end
49
+ end
50
+ end