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,581 @@
1
+ require "cases/helper"
2
+ require "models/pirate"
3
+ require "models/ship"
4
+ require "models/bird"
5
+ require "models/parrot"
6
+ require "models/treasure"
7
+
8
+ module AssertRaiseWithMessage
9
+ def assert_raise_with_message(expected_exception, expected_message)
10
+ begin
11
+ error_raised = false
12
+ yield
13
+ rescue expected_exception => error
14
+ error_raised = true
15
+ actual_message = error.message
16
+ end
17
+ assert error_raised
18
+ assert_equal expected_message, actual_message
19
+ end
20
+ end
21
+
22
+ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
23
+ include AssertRaiseWithMessage
24
+
25
+ def teardown
26
+ Pirate.accepts_nested_attributes_for :ship, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
27
+ end
28
+
29
+ def test_base_should_have_an_empty_nested_attributes_options
30
+ assert_equal Hash.new, ActiveRecord::Base.nested_attributes_options
31
+ end
32
+
33
+ def test_should_add_a_proc_to_nested_attributes_options
34
+ [:parrots, :birds].each do |name|
35
+ assert_instance_of Proc, Pirate.nested_attributes_options[name][:reject_if]
36
+ end
37
+ end
38
+
39
+ def test_should_raise_an_ArgumentError_for_non_existing_associations
40
+ assert_raise_with_message ArgumentError, "No association found for name `honesty'. Has it been defined yet?" do
41
+ Pirate.accepts_nested_attributes_for :honesty
42
+ end
43
+ end
44
+
45
+ def test_should_disable_allow_destroy_by_default
46
+ Pirate.accepts_nested_attributes_for :ship
47
+
48
+ pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
49
+ ship = pirate.create_ship(:name => 'Nights Dirty Lightning')
50
+
51
+ assert_no_difference('Ship.count') do
52
+ pirate.update_attributes(:ship_attributes => { '_destroy' => true })
53
+ end
54
+ end
55
+
56
+ def test_a_model_should_respond_to_underscore_destroy_and_return_if_it_is_marked_for_destruction
57
+ ship = Ship.create!(:name => 'Nights Dirty Lightning')
58
+ assert !ship._destroy
59
+ ship.mark_for_destruction
60
+ assert ship._destroy
61
+ end
62
+
63
+ def test_underscore_delete_is_deprecated
64
+ ActiveSupport::Deprecation.expects(:warn)
65
+ ship = Ship.create!(:name => 'Nights Dirty Lightning')
66
+ ship._delete
67
+ end
68
+
69
+ def test_reject_if_method_without_arguments
70
+ Pirate.accepts_nested_attributes_for :ship, :reject_if => :new_record?
71
+
72
+ pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
73
+ pirate.ship_attributes = { :name => 'Black Pearl' }
74
+ assert_no_difference('Ship.count') { pirate.save! }
75
+ end
76
+
77
+ def test_reject_if_method_with_arguments
78
+ Pirate.accepts_nested_attributes_for :ship, :reject_if => :reject_empty_ships_on_create
79
+
80
+ pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
81
+ pirate.ship_attributes = { :name => 'Red Pearl', :_reject_me_if_new => true }
82
+ assert_no_difference('Ship.count') { pirate.save! }
83
+
84
+ # pirate.reject_empty_ships_on_create returns false for saved records
85
+ pirate.ship_attributes = { :name => 'Red Pearl', :_reject_me_if_new => true }
86
+ assert_difference('Ship.count') { pirate.save! }
87
+ end
88
+
89
+ def test_reject_if_with_indifferent_keys
90
+ Pirate.accepts_nested_attributes_for :ship, :reject_if => proc {|attributes| attributes[:name].blank? }
91
+
92
+ pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
93
+ pirate.ship_attributes = { :name => 'Hello Pearl' }
94
+ assert_difference('Ship.count') { pirate.save! }
95
+ end
96
+ end
97
+
98
+ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
99
+ include AssertRaiseWithMessage
100
+
101
+ def setup
102
+ @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
103
+ @ship = @pirate.create_ship(:name => 'Nights Dirty Lightning')
104
+ end
105
+
106
+ def test_should_raise_argument_error_if_trying_to_build_polymorphic_belongs_to
107
+ assert_raise_with_message ArgumentError, "Cannot build association looter. Are you trying to build a polymorphic one-to-one association?" do
108
+ Treasure.new(:name => 'pearl', :looter_attributes => {:catchphrase => "Arrr"})
109
+ end
110
+ end
111
+
112
+ def test_should_define_an_attribute_writer_method_for_the_association
113
+ assert_respond_to @pirate, :ship_attributes=
114
+ end
115
+
116
+ def test_should_build_a_new_record_if_there_is_no_id
117
+ @ship.destroy
118
+ @pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger' }
119
+
120
+ assert @pirate.ship.new_record?
121
+ assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
122
+ end
123
+
124
+ def test_should_not_build_a_new_record_if_there_is_no_id_and_destroy_is_truthy
125
+ @ship.destroy
126
+ @pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger', :_destroy => '1' }
127
+
128
+ assert_nil @pirate.ship
129
+ end
130
+
131
+ def test_should_not_build_a_new_record_if_a_reject_if_proc_returns_false
132
+ @ship.destroy
133
+ @pirate.reload.ship_attributes = {}
134
+
135
+ assert_nil @pirate.ship
136
+ end
137
+
138
+ def test_should_replace_an_existing_record_if_there_is_no_id
139
+ @pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger' }
140
+
141
+ assert @pirate.ship.new_record?
142
+ assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
143
+ assert_equal 'Nights Dirty Lightning', @ship.name
144
+ end
145
+
146
+ def test_should_not_replace_an_existing_record_if_there_is_no_id_and_destroy_is_truthy
147
+ @pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger', :_destroy => '1' }
148
+
149
+ assert_equal @ship, @pirate.ship
150
+ assert_equal 'Nights Dirty Lightning', @pirate.ship.name
151
+ end
152
+
153
+ def test_should_modify_an_existing_record_if_there_is_a_matching_id
154
+ @pirate.reload.ship_attributes = { :id => @ship.id, :name => 'Davy Jones Gold Dagger' }
155
+
156
+ assert_equal @ship, @pirate.ship
157
+ assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
158
+ end
159
+
160
+ def test_should_take_a_hash_with_string_keys_and_update_the_associated_model
161
+ @pirate.reload.ship_attributes = { 'id' => @ship.id, 'name' => 'Davy Jones Gold Dagger' }
162
+
163
+ assert_equal @ship, @pirate.ship
164
+ assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
165
+ end
166
+
167
+ def test_should_modify_an_existing_record_if_there_is_a_matching_composite_id
168
+ @ship.stubs(:id).returns('ABC1X')
169
+ @pirate.ship_attributes = { :id => @ship.id, :name => 'Davy Jones Gold Dagger' }
170
+
171
+ assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
172
+ end
173
+
174
+ def test_should_destroy_an_existing_record_if_there_is_a_matching_id_and_destroy_is_truthy
175
+ @pirate.ship.destroy
176
+ [1, '1', true, 'true'].each do |truth|
177
+ @pirate.reload.create_ship(:name => 'Mister Pablo')
178
+ assert_difference('Ship.count', -1) do
179
+ @pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_destroy => truth })
180
+ end
181
+ end
182
+ end
183
+
184
+ def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy
185
+ [nil, '0', 0, 'false', false].each do |not_truth|
186
+ assert_no_difference('Ship.count') do
187
+ @pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_destroy => not_truth })
188
+ end
189
+ end
190
+ end
191
+
192
+ def test_should_not_destroy_an_existing_record_if_allow_destroy_is_false
193
+ Pirate.accepts_nested_attributes_for :ship, :allow_destroy => false, :reject_if => proc { |attributes| attributes.empty? }
194
+
195
+ assert_no_difference('Ship.count') do
196
+ @pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_destroy => '1' })
197
+ end
198
+
199
+ Pirate.accepts_nested_attributes_for :ship, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
200
+ end
201
+
202
+ def test_should_also_work_with_a_HashWithIndifferentAccess
203
+ @pirate.ship_attributes = HashWithIndifferentAccess.new(:id => @ship.id, :name => 'Davy Jones Gold Dagger')
204
+
205
+ assert !@pirate.ship.new_record?
206
+ assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
207
+ end
208
+
209
+ def test_should_work_with_update_attributes_as_well
210
+ @pirate.update_attributes({ :catchphrase => 'Arr', :ship_attributes => { :id => @ship.id, :name => 'Mister Pablo' } })
211
+ @pirate.reload
212
+
213
+ assert_equal 'Arr', @pirate.catchphrase
214
+ assert_equal 'Mister Pablo', @pirate.ship.name
215
+ end
216
+
217
+ def test_should_not_destroy_the_associated_model_until_the_parent_is_saved
218
+ assert_no_difference('Ship.count') do
219
+ @pirate.attributes = { :ship_attributes => { :id => @ship.id, :_destroy => '1' } }
220
+ end
221
+ assert_difference('Ship.count', -1) do
222
+ @pirate.save
223
+ end
224
+ end
225
+
226
+ def test_should_automatically_enable_autosave_on_the_association
227
+ assert Pirate.reflect_on_association(:ship).options[:autosave]
228
+ end
229
+ end
230
+
231
+ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
232
+ def setup
233
+ @ship = Ship.new(:name => 'Nights Dirty Lightning')
234
+ @pirate = @ship.build_pirate(:catchphrase => 'Aye')
235
+ @ship.save!
236
+ end
237
+
238
+ def test_should_define_an_attribute_writer_method_for_the_association
239
+ assert_respond_to @ship, :pirate_attributes=
240
+ end
241
+
242
+ def test_should_build_a_new_record_if_there_is_no_id
243
+ @pirate.destroy
244
+ @ship.reload.pirate_attributes = { :catchphrase => 'Arr' }
245
+
246
+ assert @ship.pirate.new_record?
247
+ assert_equal 'Arr', @ship.pirate.catchphrase
248
+ end
249
+
250
+ def test_should_not_build_a_new_record_if_there_is_no_id_and_destroy_is_truthy
251
+ @pirate.destroy
252
+ @ship.reload.pirate_attributes = { :catchphrase => 'Arr', :_destroy => '1' }
253
+
254
+ assert_nil @ship.pirate
255
+ end
256
+
257
+ def test_should_not_build_a_new_record_if_a_reject_if_proc_returns_false
258
+ @pirate.destroy
259
+ @ship.reload.pirate_attributes = {}
260
+
261
+ assert_nil @ship.pirate
262
+ end
263
+
264
+ def test_should_replace_an_existing_record_if_there_is_no_id
265
+ @ship.reload.pirate_attributes = { :catchphrase => 'Arr' }
266
+
267
+ assert @ship.pirate.new_record?
268
+ assert_equal 'Arr', @ship.pirate.catchphrase
269
+ assert_equal 'Aye', @pirate.catchphrase
270
+ end
271
+
272
+ def test_should_not_replace_an_existing_record_if_there_is_no_id_and_destroy_is_truthy
273
+ @ship.reload.pirate_attributes = { :catchphrase => 'Arr', :_destroy => '1' }
274
+
275
+ assert_equal @pirate, @ship.pirate
276
+ assert_equal 'Aye', @ship.pirate.catchphrase
277
+ end
278
+
279
+ def test_should_modify_an_existing_record_if_there_is_a_matching_id
280
+ @ship.reload.pirate_attributes = { :id => @pirate.id, :catchphrase => 'Arr' }
281
+
282
+ assert_equal @pirate, @ship.pirate
283
+ assert_equal 'Arr', @ship.pirate.catchphrase
284
+ end
285
+
286
+ def test_should_take_a_hash_with_string_keys_and_update_the_associated_model
287
+ @ship.reload.pirate_attributes = { 'id' => @pirate.id, 'catchphrase' => 'Arr' }
288
+
289
+ assert_equal @pirate, @ship.pirate
290
+ assert_equal 'Arr', @ship.pirate.catchphrase
291
+ end
292
+
293
+ def test_should_modify_an_existing_record_if_there_is_a_matching_composite_id
294
+ @pirate.stubs(:id).returns('ABC1X')
295
+ @ship.pirate_attributes = { :id => @pirate.id, :catchphrase => 'Arr' }
296
+
297
+ assert_equal 'Arr', @ship.pirate.catchphrase
298
+ end
299
+
300
+ def test_should_destroy_an_existing_record_if_there_is_a_matching_id_and_destroy_is_truthy
301
+ @ship.pirate.destroy
302
+ [1, '1', true, 'true'].each do |truth|
303
+ @ship.reload.create_pirate(:catchphrase => 'Arr')
304
+ assert_difference('Pirate.count', -1) do
305
+ @ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_destroy => truth })
306
+ end
307
+ end
308
+ end
309
+
310
+ def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy
311
+ [nil, '0', 0, 'false', false].each do |not_truth|
312
+ assert_no_difference('Pirate.count') do
313
+ @ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_destroy => not_truth })
314
+ end
315
+ end
316
+ end
317
+
318
+ def test_should_not_destroy_an_existing_record_if_allow_destroy_is_false
319
+ Ship.accepts_nested_attributes_for :pirate, :allow_destroy => false, :reject_if => proc { |attributes| attributes.empty? }
320
+
321
+ assert_no_difference('Pirate.count') do
322
+ @ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_destroy => '1' })
323
+ end
324
+
325
+ Ship.accepts_nested_attributes_for :pirate, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
326
+ end
327
+
328
+ def test_should_work_with_update_attributes_as_well
329
+ @ship.update_attributes({ :name => 'Mister Pablo', :pirate_attributes => { :catchphrase => 'Arr' } })
330
+ @ship.reload
331
+
332
+ assert_equal 'Mister Pablo', @ship.name
333
+ assert_equal 'Arr', @ship.pirate.catchphrase
334
+ end
335
+
336
+ def test_should_not_destroy_the_associated_model_until_the_parent_is_saved
337
+ assert_no_difference('Pirate.count') do
338
+ @ship.attributes = { :pirate_attributes => { :id => @ship.pirate.id, '_destroy' => true } }
339
+ end
340
+ assert_difference('Pirate.count', -1) { @ship.save }
341
+ end
342
+
343
+ def test_should_automatically_enable_autosave_on_the_association
344
+ assert Ship.reflect_on_association(:pirate).options[:autosave]
345
+ end
346
+ end
347
+
348
+ module NestedAttributesOnACollectionAssociationTests
349
+ include AssertRaiseWithMessage
350
+
351
+ def test_should_define_an_attribute_writer_method_for_the_association
352
+ assert_respond_to @pirate, association_setter
353
+ end
354
+
355
+ def test_should_take_a_hash_with_string_keys_and_assign_the_attributes_to_the_associated_models
356
+ @alternate_params[association_getter].stringify_keys!
357
+ @pirate.update_attributes @alternate_params
358
+ assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.reload.name, @child_2.reload.name]
359
+ end
360
+
361
+ def test_should_take_an_array_and_assign_the_attributes_to_the_associated_models
362
+ @pirate.send(association_setter, @alternate_params[association_getter].values)
363
+ @pirate.save
364
+ assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.reload.name, @child_2.reload.name]
365
+ end
366
+
367
+ def test_should_also_work_with_a_HashWithIndifferentAccess
368
+ @pirate.send(association_setter, HashWithIndifferentAccess.new('foo' => HashWithIndifferentAccess.new(:id => @child_1.id, :name => 'Grace OMalley')))
369
+ @pirate.save
370
+ assert_equal 'Grace OMalley', @child_1.reload.name
371
+ end
372
+
373
+ def test_should_take_a_hash_and_assign_the_attributes_to_the_associated_models
374
+ @pirate.attributes = @alternate_params
375
+ assert_equal 'Grace OMalley', @pirate.send(@association_name).first.name
376
+ assert_equal 'Privateers Greed', @pirate.send(@association_name).last.name
377
+ end
378
+
379
+ def test_should_take_a_hash_with_composite_id_keys_and_assign_the_attributes_to_the_associated_models
380
+ @child_1.stubs(:id).returns('ABC1X')
381
+ @child_2.stubs(:id).returns('ABC2X')
382
+
383
+ @pirate.attributes = {
384
+ association_getter => [
385
+ { :id => @child_1.id, :name => 'Grace OMalley' },
386
+ { :id => @child_2.id, :name => 'Privateers Greed' }
387
+ ]
388
+ }
389
+
390
+ assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.name, @child_2.name]
391
+ end
392
+
393
+ def test_should_automatically_build_new_associated_models_for_each_entry_in_a_hash_where_the_id_is_missing
394
+ @pirate.send(@association_name).destroy_all
395
+ @pirate.reload.attributes = {
396
+ association_getter => { 'foo' => { :name => 'Grace OMalley' }, 'bar' => { :name => 'Privateers Greed' }}
397
+ }
398
+
399
+ assert @pirate.send(@association_name).first.new_record?
400
+ assert_equal 'Grace OMalley', @pirate.send(@association_name).first.name
401
+
402
+ assert @pirate.send(@association_name).last.new_record?
403
+ assert_equal 'Privateers Greed', @pirate.send(@association_name).last.name
404
+ end
405
+
406
+ def test_should_not_assign_destroy_key_to_a_record
407
+ assert_nothing_raised ActiveRecord::UnknownAttributeError do
408
+ @pirate.send(association_setter, { 'foo' => { '_destroy' => '0' }})
409
+ end
410
+ end
411
+
412
+ def test_should_ignore_new_associated_records_with_truthy_destroy_attribute
413
+ @pirate.send(@association_name).destroy_all
414
+ @pirate.reload.attributes = {
415
+ association_getter => {
416
+ 'foo' => { :name => 'Grace OMalley' },
417
+ 'bar' => { :name => 'Privateers Greed', '_destroy' => '1' }
418
+ }
419
+ }
420
+
421
+ assert_equal 1, @pirate.send(@association_name).length
422
+ assert_equal 'Grace OMalley', @pirate.send(@association_name).first.name
423
+ end
424
+
425
+ def test_should_ignore_new_associated_records_if_a_reject_if_proc_returns_false
426
+ @alternate_params[association_getter]['baz'] = {}
427
+ assert_no_difference("@pirate.send(@association_name).length") do
428
+ @pirate.attributes = @alternate_params
429
+ end
430
+ end
431
+
432
+ def test_should_sort_the_hash_by_the_keys_before_building_new_associated_models
433
+ attributes = ActiveSupport::OrderedHash.new
434
+ attributes['123726353'] = { :name => 'Grace OMalley' }
435
+ attributes['2'] = { :name => 'Privateers Greed' } # 2 is lower then 123726353
436
+ @pirate.send(association_setter, attributes)
437
+
438
+ assert_equal ['Posideons Killer', 'Killer bandita Dionne', 'Privateers Greed', 'Grace OMalley'].to_set, @pirate.send(@association_name).map(&:name).to_set
439
+ end
440
+
441
+ def test_should_raise_an_argument_error_if_something_else_than_a_hash_is_passed
442
+ assert_nothing_raised(ArgumentError) { @pirate.send(association_setter, {}) }
443
+ assert_nothing_raised(ArgumentError) { @pirate.send(association_setter, ActiveSupport::OrderedHash.new) }
444
+
445
+ assert_raise_with_message ArgumentError, 'Hash or Array expected, got String ("foo")' do
446
+ @pirate.send(association_setter, "foo")
447
+ end
448
+ end
449
+
450
+ def test_should_work_with_update_attributes_as_well
451
+ @pirate.update_attributes(:catchphrase => 'Arr',
452
+ association_getter => { 'foo' => { :id => @child_1.id, :name => 'Grace OMalley' }})
453
+
454
+ assert_equal 'Grace OMalley', @child_1.reload.name
455
+ end
456
+
457
+ def test_should_update_existing_records_and_add_new_ones_that_have_no_id
458
+ @alternate_params[association_getter]['baz'] = { :name => 'Buccaneers Servant' }
459
+ assert_difference('@pirate.send(@association_name).count', +1) do
460
+ @pirate.update_attributes @alternate_params
461
+ end
462
+ assert_equal ['Grace OMalley', 'Privateers Greed', 'Buccaneers Servant'].to_set, @pirate.reload.send(@association_name).map(&:name).to_set
463
+ end
464
+
465
+ def test_should_be_possible_to_destroy_a_record
466
+ ['1', 1, 'true', true].each do |true_variable|
467
+ record = @pirate.reload.send(@association_name).create!(:name => 'Grace OMalley')
468
+ @pirate.send(association_setter,
469
+ @alternate_params[association_getter].merge('baz' => { :id => record.id, '_destroy' => true_variable })
470
+ )
471
+
472
+ assert_difference('@pirate.send(@association_name).count', -1) do
473
+ @pirate.save
474
+ end
475
+ end
476
+ end
477
+
478
+ def test_should_not_destroy_the_associated_model_with_a_non_truthy_argument
479
+ [nil, '', '0', 0, 'false', false].each do |false_variable|
480
+ @alternate_params[association_getter]['foo']['_destroy'] = false_variable
481
+ assert_no_difference('@pirate.send(@association_name).count') do
482
+ @pirate.update_attributes(@alternate_params)
483
+ end
484
+ end
485
+ end
486
+
487
+ def test_should_not_destroy_the_associated_model_until_the_parent_is_saved
488
+ assert_no_difference('@pirate.send(@association_name).count') do
489
+ @pirate.send(association_setter, @alternate_params[association_getter].merge('baz' => { :id => @child_1.id, '_destroy' => true }))
490
+ end
491
+ assert_difference('@pirate.send(@association_name).count', -1) { @pirate.save }
492
+ end
493
+
494
+ def test_should_automatically_enable_autosave_on_the_association
495
+ assert Pirate.reflect_on_association(@association_name).options[:autosave]
496
+ end
497
+
498
+ private
499
+
500
+ def association_setter
501
+ @association_setter ||= "#{@association_name}_attributes=".to_sym
502
+ end
503
+
504
+ def association_getter
505
+ @association_getter ||= "#{@association_name}_attributes".to_sym
506
+ end
507
+ end
508
+
509
+ class TestNestedAttributesOnAHasManyAssociation < ActiveRecord::TestCase
510
+ def setup
511
+ @association_type = :has_many
512
+ @association_name = :birds
513
+
514
+ @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
515
+ @pirate.birds.create!(:name => 'Posideons Killer')
516
+ @pirate.birds.create!(:name => 'Killer bandita Dionne')
517
+
518
+ @child_1, @child_2 = @pirate.birds
519
+
520
+ @alternate_params = {
521
+ :birds_attributes => {
522
+ 'foo' => { :id => @child_1.id, :name => 'Grace OMalley' },
523
+ 'bar' => { :id => @child_2.id, :name => 'Privateers Greed' }
524
+ }
525
+ }
526
+ end
527
+
528
+ include NestedAttributesOnACollectionAssociationTests
529
+ end
530
+
531
+ class TestNestedAttributesOnAHasAndBelongsToManyAssociation < ActiveRecord::TestCase
532
+ def setup
533
+ @association_type = :has_and_belongs_to_many
534
+ @association_name = :parrots
535
+
536
+ @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
537
+ @pirate.parrots.create!(:name => 'Posideons Killer')
538
+ @pirate.parrots.create!(:name => 'Killer bandita Dionne')
539
+
540
+ @child_1, @child_2 = @pirate.parrots
541
+
542
+ @alternate_params = {
543
+ :parrots_attributes => {
544
+ 'foo' => { :id => @child_1.id, :name => 'Grace OMalley' },
545
+ 'bar' => { :id => @child_2.id, :name => 'Privateers Greed' }
546
+ }
547
+ }
548
+ end
549
+
550
+ include NestedAttributesOnACollectionAssociationTests
551
+ end
552
+
553
+ class TestNestedAttributesLimit < ActiveRecord::TestCase
554
+ def setup
555
+ Pirate.accepts_nested_attributes_for :parrots, :limit => 2
556
+
557
+ @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
558
+ end
559
+
560
+ def teardown
561
+ Pirate.accepts_nested_attributes_for :parrots, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
562
+ end
563
+
564
+ def test_limit_with_less_records
565
+ @pirate.attributes = { :parrots_attributes => { 'foo' => { :name => 'Big Big Love' } } }
566
+ assert_difference('Parrot.count') { @pirate.save! }
567
+ end
568
+
569
+ def test_limit_with_number_exact_records
570
+ @pirate.attributes = { :parrots_attributes => { 'foo' => { :name => 'Lovely Day' }, 'bar' => { :name => 'Blown Away' } } }
571
+ assert_difference('Parrot.count', 2) { @pirate.save! }
572
+ end
573
+
574
+ def test_limit_with_exceeding_records
575
+ assert_raises(ActiveRecord::NestedAttributes::TooManyRecords) do
576
+ @pirate.attributes = { :parrots_attributes => { 'foo' => { :name => 'Lovely Day' },
577
+ 'bar' => { :name => 'Blown Away' },
578
+ 'car' => { :name => 'The Happening' }} }
579
+ end
580
+ end
581
+ end
@@ -0,0 +1,119 @@
1
+ require "cases/helper"
2
+ require 'models/topic'
3
+ require 'models/reply'
4
+ require 'models/subscriber'
5
+ require 'models/movie'
6
+ require 'models/keyboard'
7
+ require 'models/mixed_case_monkey'
8
+
9
+ class PrimaryKeysTest < ActiveRecord::TestCase
10
+ fixtures :topics, :subscribers, :movies, :mixed_case_monkeys
11
+
12
+ def test_integer_key
13
+ topic = Topic.find(1)
14
+ assert_equal(topics(:first).author_name, topic.author_name)
15
+ topic = Topic.find(2)
16
+ assert_equal(topics(:second).author_name, topic.author_name)
17
+
18
+ topic = Topic.new
19
+ topic.title = "New Topic"
20
+ assert_equal(nil, topic.id)
21
+ assert_nothing_raised { topic.save! }
22
+ id = topic.id
23
+
24
+ topicReloaded = Topic.find(id)
25
+ assert_equal("New Topic", topicReloaded.title)
26
+ end
27
+
28
+ def test_customized_primary_key_auto_assigns_on_save
29
+ Keyboard.delete_all
30
+ keyboard = Keyboard.new(:name => 'HHKB')
31
+ assert_nothing_raised { keyboard.save! }
32
+ assert_equal keyboard.id, Keyboard.find_by_name('HHKB').id
33
+ end
34
+
35
+ def test_customized_primary_key_can_be_get_before_saving
36
+ keyboard = Keyboard.new
37
+ assert_nil keyboard.id
38
+ assert_nothing_raised { assert_nil keyboard.key_number }
39
+ end
40
+
41
+ def test_customized_string_primary_key_settable_before_save
42
+ subscriber = Subscriber.new
43
+ assert_nothing_raised { subscriber.id = 'webster123' }
44
+ assert_equal 'webster123', subscriber.id
45
+ assert_equal 'webster123', subscriber.nick
46
+ end
47
+
48
+ def test_string_key
49
+ subscriber = Subscriber.find(subscribers(:first).nick)
50
+ assert_equal(subscribers(:first).name, subscriber.name)
51
+ subscriber = Subscriber.find(subscribers(:second).nick)
52
+ assert_equal(subscribers(:second).name, subscriber.name)
53
+
54
+ subscriber = Subscriber.new
55
+ subscriber.id = "jdoe"
56
+ assert_equal("jdoe", subscriber.id)
57
+ subscriber.name = "John Doe"
58
+ assert_nothing_raised { subscriber.save! }
59
+ assert_equal("jdoe", subscriber.id)
60
+
61
+ subscriberReloaded = Subscriber.find("jdoe")
62
+ assert_equal("John Doe", subscriberReloaded.name)
63
+ end
64
+
65
+ def test_find_with_more_than_one_string_key
66
+ assert_equal 2, Subscriber.find(subscribers(:first).nick, subscribers(:second).nick).length
67
+ end
68
+
69
+ def test_primary_key_prefix
70
+ ActiveRecord::Base.primary_key_prefix_type = :table_name
71
+ Topic.reset_primary_key
72
+ assert_equal "topicid", Topic.primary_key
73
+
74
+ ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
75
+ Topic.reset_primary_key
76
+ assert_equal "topic_id", Topic.primary_key
77
+
78
+ ActiveRecord::Base.primary_key_prefix_type = nil
79
+ Topic.reset_primary_key
80
+ assert_equal "id", Topic.primary_key
81
+ end
82
+
83
+ def test_delete_should_quote_pkey
84
+ assert_nothing_raised { MixedCaseMonkey.delete(1) }
85
+ end
86
+ def test_update_counters_should_quote_pkey_and_quote_counter_columns
87
+ assert_nothing_raised { MixedCaseMonkey.update_counters(1, :fleaCount => 99) }
88
+ end
89
+ def test_find_with_one_id_should_quote_pkey
90
+ assert_nothing_raised { MixedCaseMonkey.find(1) }
91
+ end
92
+ def test_find_with_multiple_ids_should_quote_pkey
93
+ assert_nothing_raised { MixedCaseMonkey.find([1,2]) }
94
+ end
95
+ def test_instance_update_should_quote_pkey
96
+ assert_nothing_raised { MixedCaseMonkey.find(1).save }
97
+ end
98
+ def test_instance_destroy_should_quote_pkey
99
+ assert_nothing_raised { MixedCaseMonkey.find(1).destroy }
100
+ end
101
+
102
+ def test_supports_primary_key
103
+ assert_nothing_raised NoMethodError do
104
+ ActiveRecord::Base.connection.supports_primary_key?
105
+ end
106
+ end
107
+
108
+ def test_primary_key_returns_value_if_it_exists
109
+ if ActiveRecord::Base.connection.supports_primary_key?
110
+ assert_equal 'id', ActiveRecord::Base.connection.primary_key('developers')
111
+ end
112
+ end
113
+
114
+ def test_primary_key_returns_nil_if_it_does_not_exist
115
+ if ActiveRecord::Base.connection.supports_primary_key?
116
+ assert_nil ActiveRecord::Base.connection.primary_key('developers_projects')
117
+ end
118
+ end
119
+ end