activerecord_authorails 1.0.0

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 (270) hide show
  1. data/CHANGELOG +3043 -0
  2. data/README +360 -0
  3. data/RUNNING_UNIT_TESTS +64 -0
  4. data/Rakefile +226 -0
  5. data/examples/associations.png +0 -0
  6. data/examples/associations.rb +87 -0
  7. data/examples/shared_setup.rb +15 -0
  8. data/examples/validation.rb +85 -0
  9. data/install.rb +30 -0
  10. data/lib/active_record.rb +85 -0
  11. data/lib/active_record/acts/list.rb +244 -0
  12. data/lib/active_record/acts/nested_set.rb +211 -0
  13. data/lib/active_record/acts/tree.rb +89 -0
  14. data/lib/active_record/aggregations.rb +191 -0
  15. data/lib/active_record/associations.rb +1637 -0
  16. data/lib/active_record/associations/association_collection.rb +190 -0
  17. data/lib/active_record/associations/association_proxy.rb +158 -0
  18. data/lib/active_record/associations/belongs_to_association.rb +56 -0
  19. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
  20. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +169 -0
  21. data/lib/active_record/associations/has_many_association.rb +210 -0
  22. data/lib/active_record/associations/has_many_through_association.rb +247 -0
  23. data/lib/active_record/associations/has_one_association.rb +80 -0
  24. data/lib/active_record/attribute_methods.rb +75 -0
  25. data/lib/active_record/base.rb +2164 -0
  26. data/lib/active_record/calculations.rb +270 -0
  27. data/lib/active_record/callbacks.rb +367 -0
  28. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +279 -0
  29. data/lib/active_record/connection_adapters/abstract/database_statements.rb +130 -0
  30. data/lib/active_record/connection_adapters/abstract/quoting.rb +58 -0
  31. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +343 -0
  32. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +310 -0
  33. data/lib/active_record/connection_adapters/abstract_adapter.rb +161 -0
  34. data/lib/active_record/connection_adapters/db2_adapter.rb +228 -0
  35. data/lib/active_record/connection_adapters/firebird_adapter.rb +728 -0
  36. data/lib/active_record/connection_adapters/frontbase_adapter.rb +861 -0
  37. data/lib/active_record/connection_adapters/mysql_adapter.rb +414 -0
  38. data/lib/active_record/connection_adapters/openbase_adapter.rb +350 -0
  39. data/lib/active_record/connection_adapters/oracle_adapter.rb +689 -0
  40. data/lib/active_record/connection_adapters/postgresql_adapter.rb +584 -0
  41. data/lib/active_record/connection_adapters/sqlite_adapter.rb +407 -0
  42. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +591 -0
  43. data/lib/active_record/connection_adapters/sybase_adapter.rb +662 -0
  44. data/lib/active_record/deprecated_associations.rb +104 -0
  45. data/lib/active_record/deprecated_finders.rb +44 -0
  46. data/lib/active_record/fixtures.rb +628 -0
  47. data/lib/active_record/locking/optimistic.rb +106 -0
  48. data/lib/active_record/locking/pessimistic.rb +77 -0
  49. data/lib/active_record/migration.rb +394 -0
  50. data/lib/active_record/observer.rb +178 -0
  51. data/lib/active_record/query_cache.rb +64 -0
  52. data/lib/active_record/reflection.rb +222 -0
  53. data/lib/active_record/schema.rb +58 -0
  54. data/lib/active_record/schema_dumper.rb +149 -0
  55. data/lib/active_record/timestamp.rb +51 -0
  56. data/lib/active_record/transactions.rb +136 -0
  57. data/lib/active_record/validations.rb +843 -0
  58. data/lib/active_record/vendor/db2.rb +362 -0
  59. data/lib/active_record/vendor/mysql.rb +1214 -0
  60. data/lib/active_record/vendor/simple.rb +693 -0
  61. data/lib/active_record/version.rb +9 -0
  62. data/lib/active_record/wrappers/yaml_wrapper.rb +15 -0
  63. data/lib/active_record/wrappings.rb +58 -0
  64. data/lib/active_record/xml_serialization.rb +308 -0
  65. data/test/aaa_create_tables_test.rb +59 -0
  66. data/test/abstract_unit.rb +77 -0
  67. data/test/active_schema_test_mysql.rb +31 -0
  68. data/test/adapter_test.rb +87 -0
  69. data/test/adapter_test_sqlserver.rb +81 -0
  70. data/test/aggregations_test.rb +95 -0
  71. data/test/all.sh +8 -0
  72. data/test/ar_schema_test.rb +33 -0
  73. data/test/association_inheritance_reload.rb +14 -0
  74. data/test/associations/callbacks_test.rb +126 -0
  75. data/test/associations/cascaded_eager_loading_test.rb +138 -0
  76. data/test/associations/eager_test.rb +393 -0
  77. data/test/associations/extension_test.rb +42 -0
  78. data/test/associations/join_model_test.rb +497 -0
  79. data/test/associations_test.rb +1809 -0
  80. data/test/attribute_methods_test.rb +49 -0
  81. data/test/base_test.rb +1586 -0
  82. data/test/binary_test.rb +37 -0
  83. data/test/calculations_test.rb +219 -0
  84. data/test/callbacks_test.rb +377 -0
  85. data/test/class_inheritable_attributes_test.rb +32 -0
  86. data/test/column_alias_test.rb +17 -0
  87. data/test/connection_test_firebird.rb +8 -0
  88. data/test/connections/native_db2/connection.rb +25 -0
  89. data/test/connections/native_firebird/connection.rb +26 -0
  90. data/test/connections/native_frontbase/connection.rb +27 -0
  91. data/test/connections/native_mysql/connection.rb +24 -0
  92. data/test/connections/native_openbase/connection.rb +21 -0
  93. data/test/connections/native_oracle/connection.rb +27 -0
  94. data/test/connections/native_postgresql/connection.rb +23 -0
  95. data/test/connections/native_sqlite/connection.rb +34 -0
  96. data/test/connections/native_sqlite3/connection.rb +34 -0
  97. data/test/connections/native_sqlite3/in_memory_connection.rb +18 -0
  98. data/test/connections/native_sqlserver/connection.rb +23 -0
  99. data/test/connections/native_sqlserver_odbc/connection.rb +25 -0
  100. data/test/connections/native_sybase/connection.rb +23 -0
  101. data/test/copy_table_sqlite.rb +64 -0
  102. data/test/datatype_test_postgresql.rb +52 -0
  103. data/test/default_test_firebird.rb +16 -0
  104. data/test/defaults_test.rb +60 -0
  105. data/test/deprecated_associations_test.rb +396 -0
  106. data/test/deprecated_finder_test.rb +151 -0
  107. data/test/empty_date_time_test.rb +25 -0
  108. data/test/finder_test.rb +504 -0
  109. data/test/fixtures/accounts.yml +28 -0
  110. data/test/fixtures/author.rb +99 -0
  111. data/test/fixtures/author_favorites.yml +4 -0
  112. data/test/fixtures/authors.yml +7 -0
  113. data/test/fixtures/auto_id.rb +4 -0
  114. data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +1 -0
  115. data/test/fixtures/bad_fixtures/attr_with_spaces +1 -0
  116. data/test/fixtures/bad_fixtures/blank_line +3 -0
  117. data/test/fixtures/bad_fixtures/duplicate_attributes +3 -0
  118. data/test/fixtures/bad_fixtures/missing_value +1 -0
  119. data/test/fixtures/binary.rb +2 -0
  120. data/test/fixtures/categories.yml +14 -0
  121. data/test/fixtures/categories/special_categories.yml +9 -0
  122. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  123. data/test/fixtures/categories_ordered.yml +7 -0
  124. data/test/fixtures/categories_posts.yml +23 -0
  125. data/test/fixtures/categorization.rb +5 -0
  126. data/test/fixtures/categorizations.yml +17 -0
  127. data/test/fixtures/category.rb +20 -0
  128. data/test/fixtures/column_name.rb +3 -0
  129. data/test/fixtures/comment.rb +23 -0
  130. data/test/fixtures/comments.yml +59 -0
  131. data/test/fixtures/companies.yml +55 -0
  132. data/test/fixtures/company.rb +107 -0
  133. data/test/fixtures/company_in_module.rb +59 -0
  134. data/test/fixtures/computer.rb +3 -0
  135. data/test/fixtures/computers.yml +4 -0
  136. data/test/fixtures/course.rb +3 -0
  137. data/test/fixtures/courses.yml +7 -0
  138. data/test/fixtures/customer.rb +55 -0
  139. data/test/fixtures/customers.yml +17 -0
  140. data/test/fixtures/db_definitions/db2.drop.sql +32 -0
  141. data/test/fixtures/db_definitions/db2.sql +231 -0
  142. data/test/fixtures/db_definitions/db22.drop.sql +2 -0
  143. data/test/fixtures/db_definitions/db22.sql +5 -0
  144. data/test/fixtures/db_definitions/firebird.drop.sql +63 -0
  145. data/test/fixtures/db_definitions/firebird.sql +304 -0
  146. data/test/fixtures/db_definitions/firebird2.drop.sql +2 -0
  147. data/test/fixtures/db_definitions/firebird2.sql +6 -0
  148. data/test/fixtures/db_definitions/frontbase.drop.sql +32 -0
  149. data/test/fixtures/db_definitions/frontbase.sql +268 -0
  150. data/test/fixtures/db_definitions/frontbase2.drop.sql +1 -0
  151. data/test/fixtures/db_definitions/frontbase2.sql +4 -0
  152. data/test/fixtures/db_definitions/mysql.drop.sql +32 -0
  153. data/test/fixtures/db_definitions/mysql.sql +234 -0
  154. data/test/fixtures/db_definitions/mysql2.drop.sql +2 -0
  155. data/test/fixtures/db_definitions/mysql2.sql +5 -0
  156. data/test/fixtures/db_definitions/openbase.drop.sql +2 -0
  157. data/test/fixtures/db_definitions/openbase.sql +302 -0
  158. data/test/fixtures/db_definitions/openbase2.drop.sql +2 -0
  159. data/test/fixtures/db_definitions/openbase2.sql +7 -0
  160. data/test/fixtures/db_definitions/oracle.drop.sql +65 -0
  161. data/test/fixtures/db_definitions/oracle.sql +325 -0
  162. data/test/fixtures/db_definitions/oracle2.drop.sql +2 -0
  163. data/test/fixtures/db_definitions/oracle2.sql +6 -0
  164. data/test/fixtures/db_definitions/postgresql.drop.sql +37 -0
  165. data/test/fixtures/db_definitions/postgresql.sql +263 -0
  166. data/test/fixtures/db_definitions/postgresql2.drop.sql +2 -0
  167. data/test/fixtures/db_definitions/postgresql2.sql +5 -0
  168. data/test/fixtures/db_definitions/schema.rb +60 -0
  169. data/test/fixtures/db_definitions/sqlite.drop.sql +32 -0
  170. data/test/fixtures/db_definitions/sqlite.sql +215 -0
  171. data/test/fixtures/db_definitions/sqlite2.drop.sql +2 -0
  172. data/test/fixtures/db_definitions/sqlite2.sql +5 -0
  173. data/test/fixtures/db_definitions/sqlserver.drop.sql +34 -0
  174. data/test/fixtures/db_definitions/sqlserver.sql +243 -0
  175. data/test/fixtures/db_definitions/sqlserver2.drop.sql +2 -0
  176. data/test/fixtures/db_definitions/sqlserver2.sql +5 -0
  177. data/test/fixtures/db_definitions/sybase.drop.sql +34 -0
  178. data/test/fixtures/db_definitions/sybase.sql +218 -0
  179. data/test/fixtures/db_definitions/sybase2.drop.sql +4 -0
  180. data/test/fixtures/db_definitions/sybase2.sql +5 -0
  181. data/test/fixtures/default.rb +2 -0
  182. data/test/fixtures/developer.rb +52 -0
  183. data/test/fixtures/developers.yml +21 -0
  184. data/test/fixtures/developers_projects.yml +17 -0
  185. data/test/fixtures/developers_projects/david_action_controller +3 -0
  186. data/test/fixtures/developers_projects/david_active_record +3 -0
  187. data/test/fixtures/developers_projects/jamis_active_record +2 -0
  188. data/test/fixtures/edge.rb +5 -0
  189. data/test/fixtures/edges.yml +6 -0
  190. data/test/fixtures/entrant.rb +3 -0
  191. data/test/fixtures/entrants.yml +14 -0
  192. data/test/fixtures/fk_test_has_fk.yml +3 -0
  193. data/test/fixtures/fk_test_has_pk.yml +2 -0
  194. data/test/fixtures/flowers.jpg +0 -0
  195. data/test/fixtures/funny_jokes.yml +10 -0
  196. data/test/fixtures/joke.rb +6 -0
  197. data/test/fixtures/keyboard.rb +3 -0
  198. data/test/fixtures/legacy_thing.rb +3 -0
  199. data/test/fixtures/legacy_things.yml +3 -0
  200. data/test/fixtures/migrations/1_people_have_last_names.rb +9 -0
  201. data/test/fixtures/migrations/2_we_need_reminders.rb +12 -0
  202. data/test/fixtures/migrations/3_innocent_jointable.rb +12 -0
  203. data/test/fixtures/migrations_with_decimal/1_give_me_big_numbers.rb +15 -0
  204. data/test/fixtures/migrations_with_duplicate/1_people_have_last_names.rb +9 -0
  205. data/test/fixtures/migrations_with_duplicate/2_we_need_reminders.rb +12 -0
  206. data/test/fixtures/migrations_with_duplicate/3_foo.rb +7 -0
  207. data/test/fixtures/migrations_with_duplicate/3_innocent_jointable.rb +12 -0
  208. data/test/fixtures/migrations_with_missing_versions/1000_people_have_middle_names.rb +9 -0
  209. data/test/fixtures/migrations_with_missing_versions/1_people_have_last_names.rb +9 -0
  210. data/test/fixtures/migrations_with_missing_versions/3_we_need_reminders.rb +12 -0
  211. data/test/fixtures/migrations_with_missing_versions/4_innocent_jointable.rb +12 -0
  212. data/test/fixtures/mixed_case_monkey.rb +3 -0
  213. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  214. data/test/fixtures/mixin.rb +63 -0
  215. data/test/fixtures/mixins.yml +127 -0
  216. data/test/fixtures/movie.rb +5 -0
  217. data/test/fixtures/movies.yml +7 -0
  218. data/test/fixtures/naked/csv/accounts.csv +1 -0
  219. data/test/fixtures/naked/yml/accounts.yml +1 -0
  220. data/test/fixtures/naked/yml/companies.yml +1 -0
  221. data/test/fixtures/naked/yml/courses.yml +1 -0
  222. data/test/fixtures/order.rb +4 -0
  223. data/test/fixtures/people.yml +3 -0
  224. data/test/fixtures/person.rb +4 -0
  225. data/test/fixtures/post.rb +58 -0
  226. data/test/fixtures/posts.yml +48 -0
  227. data/test/fixtures/project.rb +27 -0
  228. data/test/fixtures/projects.yml +7 -0
  229. data/test/fixtures/reader.rb +4 -0
  230. data/test/fixtures/readers.yml +4 -0
  231. data/test/fixtures/reply.rb +37 -0
  232. data/test/fixtures/subject.rb +4 -0
  233. data/test/fixtures/subscriber.rb +6 -0
  234. data/test/fixtures/subscribers/first +2 -0
  235. data/test/fixtures/subscribers/second +2 -0
  236. data/test/fixtures/tag.rb +7 -0
  237. data/test/fixtures/tagging.rb +6 -0
  238. data/test/fixtures/taggings.yml +18 -0
  239. data/test/fixtures/tags.yml +7 -0
  240. data/test/fixtures/task.rb +3 -0
  241. data/test/fixtures/tasks.yml +7 -0
  242. data/test/fixtures/topic.rb +25 -0
  243. data/test/fixtures/topics.yml +22 -0
  244. data/test/fixtures/vertex.rb +9 -0
  245. data/test/fixtures/vertices.yml +4 -0
  246. data/test/fixtures_test.rb +401 -0
  247. data/test/inheritance_test.rb +205 -0
  248. data/test/lifecycle_test.rb +137 -0
  249. data/test/locking_test.rb +190 -0
  250. data/test/method_scoping_test.rb +416 -0
  251. data/test/migration_test.rb +768 -0
  252. data/test/migration_test_firebird.rb +124 -0
  253. data/test/mixin_nested_set_test.rb +196 -0
  254. data/test/mixin_test.rb +550 -0
  255. data/test/modules_test.rb +34 -0
  256. data/test/multiple_db_test.rb +60 -0
  257. data/test/pk_test.rb +104 -0
  258. data/test/readonly_test.rb +107 -0
  259. data/test/reflection_test.rb +159 -0
  260. data/test/schema_authorization_test_postgresql.rb +75 -0
  261. data/test/schema_dumper_test.rb +96 -0
  262. data/test/schema_test_postgresql.rb +64 -0
  263. data/test/synonym_test_oracle.rb +17 -0
  264. data/test/table_name_test_sqlserver.rb +23 -0
  265. data/test/threaded_connections_test.rb +48 -0
  266. data/test/transactions_test.rb +230 -0
  267. data/test/unconnected_test.rb +32 -0
  268. data/test/validations_test.rb +1097 -0
  269. data/test/xml_serialization_test.rb +125 -0
  270. metadata +365 -0
@@ -0,0 +1,42 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/post'
3
+ require 'fixtures/comment'
4
+ require 'fixtures/project'
5
+ require 'fixtures/developer'
6
+
7
+ class AssociationsExtensionsTest < Test::Unit::TestCase
8
+ fixtures :projects, :developers, :developers_projects, :comments, :posts
9
+
10
+ def test_extension_on_has_many
11
+ assert_equal comments(:more_greetings), posts(:welcome).comments.find_most_recent
12
+ end
13
+
14
+ def test_extension_on_habtm
15
+ assert_equal projects(:action_controller), developers(:david).projects.find_most_recent
16
+ end
17
+
18
+ def test_named_extension_on_habtm
19
+ assert_equal projects(:action_controller), developers(:david).projects_extended_by_name.find_most_recent
20
+ end
21
+
22
+ def test_named_two_extensions_on_habtm
23
+ assert_equal projects(:action_controller), developers(:david).projects_extended_by_name_twice.find_most_recent
24
+ assert_equal projects(:active_record), developers(:david).projects_extended_by_name_twice.find_least_recent
25
+ end
26
+
27
+ def test_marshalling_extensions
28
+ david = developers(:david)
29
+ assert_equal projects(:action_controller), david.projects.find_most_recent
30
+
31
+ david = Marshal.load(Marshal.dump(david))
32
+ assert_equal projects(:action_controller), david.projects.find_most_recent
33
+ end
34
+
35
+ def test_marshalling_named_extensions
36
+ david = developers(:david)
37
+ assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
38
+
39
+ david = Marshal.load(Marshal.dump(david))
40
+ assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
41
+ end
42
+ end
@@ -0,0 +1,497 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/tag'
3
+ require 'fixtures/tagging'
4
+ require 'fixtures/post'
5
+ require 'fixtures/comment'
6
+ require 'fixtures/author'
7
+ require 'fixtures/category'
8
+ require 'fixtures/categorization'
9
+ require 'fixtures/vertex'
10
+ require 'fixtures/edge'
11
+
12
+ class AssociationsJoinModelTest < Test::Unit::TestCase
13
+ self.use_transactional_fixtures = false
14
+ fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites, :vertices
15
+
16
+ def test_has_many
17
+ assert authors(:david).categories.include?(categories(:general))
18
+ end
19
+
20
+ def test_has_many_inherited
21
+ assert authors(:mary).categories.include?(categories(:sti_test))
22
+ end
23
+
24
+ def test_inherited_has_many
25
+ assert categories(:sti_test).authors.include?(authors(:mary))
26
+ end
27
+
28
+ def test_has_many_uniq_through_join_model
29
+ assert_equal 2, authors(:mary).categorized_posts.size
30
+ assert_equal 1, authors(:mary).unique_categorized_posts.size
31
+ end
32
+
33
+ def test_polymorphic_has_many
34
+ assert posts(:welcome).taggings.include?(taggings(:welcome_general))
35
+ end
36
+
37
+ def test_polymorphic_has_one
38
+ assert_equal taggings(:welcome_general), posts(:welcome).tagging
39
+ end
40
+
41
+ def test_polymorphic_belongs_to
42
+ assert_equal posts(:welcome), posts(:welcome).taggings.first.taggable
43
+ end
44
+
45
+ def test_polymorphic_has_many_going_through_join_model
46
+ assert_equal tags(:general), tag = posts(:welcome).tags.first
47
+ assert_no_queries do
48
+ tag.tagging
49
+ end
50
+ end
51
+
52
+ def test_count_polymorphic_has_many
53
+ assert_equal 1, posts(:welcome).taggings.count
54
+ assert_equal 1, posts(:welcome).tags.count
55
+ end
56
+
57
+ def test_polymorphic_has_many_going_through_join_model_with_find
58
+ assert_equal tags(:general), tag = posts(:welcome).tags.find(:first)
59
+ assert_no_queries do
60
+ tag.tagging
61
+ end
62
+ end
63
+
64
+ def test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection
65
+ assert_equal tags(:general), tag = posts(:welcome).funky_tags.first
66
+ assert_no_queries do
67
+ tag.tagging
68
+ end
69
+ end
70
+
71
+ def test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection_with_find
72
+ assert_equal tags(:general), tag = posts(:welcome).funky_tags.find(:first)
73
+ assert_no_queries do
74
+ tag.tagging
75
+ end
76
+ end
77
+
78
+ def test_polymorphic_has_many_going_through_join_model_with_disabled_include
79
+ assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first
80
+ assert_queries 1 do
81
+ tag.tagging
82
+ end
83
+ end
84
+
85
+ def test_polymorphic_has_many_going_through_join_model_with_custom_select_and_joins
86
+ assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first
87
+ tag.author_id
88
+ end
89
+
90
+ def test_polymorphic_has_many_going_through_join_model_with_custom_foreign_key
91
+ assert_equal tags(:misc), taggings(:welcome_general).super_tag
92
+ assert_equal tags(:misc), posts(:welcome).super_tags.first
93
+ end
94
+
95
+ def test_polymorphic_has_many_create_model_with_inheritance_and_custom_base_class
96
+ post = SubStiPost.create :title => 'SubStiPost', :body => 'SubStiPost body'
97
+ assert_instance_of SubStiPost, post
98
+
99
+ tagging = tags(:misc).taggings.create(:taggable => post)
100
+ assert_equal "SubStiPost", tagging.taggable_type
101
+ end
102
+
103
+ def test_polymorphic_has_many_going_through_join_model_with_inheritance
104
+ assert_equal tags(:general), posts(:thinking).tags.first
105
+ end
106
+
107
+ def test_polymorphic_has_many_going_through_join_model_with_inheritance_with_custom_class_name
108
+ assert_equal tags(:general), posts(:thinking).funky_tags.first
109
+ end
110
+
111
+ def test_polymorphic_has_many_create_model_with_inheritance
112
+ post = posts(:thinking)
113
+ assert_instance_of SpecialPost, post
114
+
115
+ tagging = tags(:misc).taggings.create(:taggable => post)
116
+ assert_equal "Post", tagging.taggable_type
117
+ end
118
+
119
+ def test_polymorphic_has_one_create_model_with_inheritance
120
+ tagging = tags(:misc).create_tagging(:taggable => posts(:thinking))
121
+ assert_equal "Post", tagging.taggable_type
122
+ end
123
+
124
+ def test_set_polymorphic_has_many
125
+ tagging = tags(:misc).taggings.create
126
+ posts(:thinking).taggings << tagging
127
+ assert_equal "Post", tagging.taggable_type
128
+ end
129
+
130
+ def test_set_polymorphic_has_one
131
+ tagging = tags(:misc).taggings.create
132
+ posts(:thinking).tagging = tagging
133
+ assert_equal "Post", tagging.taggable_type
134
+ end
135
+
136
+ def test_create_polymorphic_has_many_with_scope
137
+ old_count = posts(:welcome).taggings.count
138
+ tagging = posts(:welcome).taggings.create(:tag => tags(:misc))
139
+ assert_equal "Post", tagging.taggable_type
140
+ assert_equal old_count+1, posts(:welcome).taggings.count
141
+ end
142
+
143
+ def test_create_bang_polymorphic_with_has_many_scope
144
+ old_count = posts(:welcome).taggings.count
145
+ tagging = posts(:welcome).taggings.create!(:tag => tags(:misc))
146
+ assert_equal "Post", tagging.taggable_type
147
+ assert_equal old_count+1, posts(:welcome).taggings.count
148
+ end
149
+
150
+ def test_create_polymorphic_has_one_with_scope
151
+ old_count = Tagging.count
152
+ tagging = posts(:welcome).tagging.create(:tag => tags(:misc))
153
+ assert_equal "Post", tagging.taggable_type
154
+ assert_equal old_count+1, Tagging.count
155
+ end
156
+
157
+ def test_delete_polymorphic_has_many_with_delete_all
158
+ assert_equal 1, posts(:welcome).taggings.count
159
+ posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyDeleteAll'
160
+ post = find_post_with_dependency(1, :has_many, :taggings, :delete_all)
161
+
162
+ old_count = Tagging.count
163
+ post.destroy
164
+ assert_equal old_count-1, Tagging.count
165
+ assert_equal 0, posts(:welcome).taggings.count
166
+ end
167
+
168
+ def test_delete_polymorphic_has_many_with_destroy
169
+ assert_equal 1, posts(:welcome).taggings.count
170
+ posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyDestroy'
171
+ post = find_post_with_dependency(1, :has_many, :taggings, :destroy)
172
+
173
+ old_count = Tagging.count
174
+ post.destroy
175
+ assert_equal old_count-1, Tagging.count
176
+ assert_equal 0, posts(:welcome).taggings.count
177
+ end
178
+
179
+ def test_delete_polymorphic_has_many_with_nullify
180
+ assert_equal 1, posts(:welcome).taggings.count
181
+ posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyNullify'
182
+ post = find_post_with_dependency(1, :has_many, :taggings, :nullify)
183
+
184
+ old_count = Tagging.count
185
+ post.destroy
186
+ assert_equal old_count, Tagging.count
187
+ assert_equal 0, posts(:welcome).taggings.count
188
+ end
189
+
190
+ def test_delete_polymorphic_has_one_with_destroy
191
+ assert posts(:welcome).tagging
192
+ posts(:welcome).tagging.update_attribute :taggable_type, 'PostWithHasOneDestroy'
193
+ post = find_post_with_dependency(1, :has_one, :tagging, :destroy)
194
+
195
+ old_count = Tagging.count
196
+ post.destroy
197
+ assert_equal old_count-1, Tagging.count
198
+ assert_nil posts(:welcome).tagging(true)
199
+ end
200
+
201
+ def test_delete_polymorphic_has_one_with_nullify
202
+ assert posts(:welcome).tagging
203
+ posts(:welcome).tagging.update_attribute :taggable_type, 'PostWithHasOneNullify'
204
+ post = find_post_with_dependency(1, :has_one, :tagging, :nullify)
205
+
206
+ old_count = Tagging.count
207
+ post.destroy
208
+ assert_equal old_count, Tagging.count
209
+ assert_nil posts(:welcome).tagging(true)
210
+ end
211
+
212
+ def test_has_many_with_piggyback
213
+ assert_equal "2", categories(:sti_test).authors.first.post_id.to_s
214
+ end
215
+
216
+ def test_include_has_many_through
217
+ posts = Post.find(:all, :order => 'posts.id')
218
+ posts_with_authors = Post.find(:all, :include => :authors, :order => 'posts.id')
219
+ assert_equal posts.length, posts_with_authors.length
220
+ posts.length.times do |i|
221
+ assert_equal posts[i].authors.length, assert_no_queries { posts_with_authors[i].authors.length }
222
+ end
223
+ end
224
+
225
+ def test_include_polymorphic_has_one
226
+ post = Post.find_by_id(posts(:welcome).id, :include => :tagging)
227
+ tagging = taggings(:welcome_general)
228
+ assert_no_queries do
229
+ assert_equal tagging, post.tagging
230
+ end
231
+ end
232
+
233
+ def test_include_polymorphic_has_many_through
234
+ posts = Post.find(:all, :order => 'posts.id')
235
+ posts_with_tags = Post.find(:all, :include => :tags, :order => 'posts.id')
236
+ assert_equal posts.length, posts_with_tags.length
237
+ posts.length.times do |i|
238
+ assert_equal posts[i].tags.length, assert_no_queries { posts_with_tags[i].tags.length }
239
+ end
240
+ end
241
+
242
+ def test_include_polymorphic_has_many
243
+ posts = Post.find(:all, :order => 'posts.id')
244
+ posts_with_taggings = Post.find(:all, :include => :taggings, :order => 'posts.id')
245
+ assert_equal posts.length, posts_with_taggings.length
246
+ posts.length.times do |i|
247
+ assert_equal posts[i].taggings.length, assert_no_queries { posts_with_taggings[i].taggings.length }
248
+ end
249
+ end
250
+
251
+ def test_has_many_find_all
252
+ assert_equal [categories(:general)], authors(:david).categories.find(:all)
253
+ end
254
+
255
+ def test_has_many_find_first
256
+ assert_equal categories(:general), authors(:david).categories.find(:first)
257
+ end
258
+
259
+ def test_has_many_with_hash_conditions
260
+ assert_equal categories(:general), authors(:david).categories_like_general.find(:first)
261
+ end
262
+
263
+ def test_has_many_find_conditions
264
+ assert_equal categories(:general), authors(:david).categories.find(:first, :conditions => "categories.name = 'General'")
265
+ assert_equal nil, authors(:david).categories.find(:first, :conditions => "categories.name = 'Technology'")
266
+ end
267
+
268
+ def test_has_many_class_methods_called_by_method_missing
269
+ assert_equal categories(:general), authors(:david).categories.find_all_by_name('General').first
270
+ # assert_equal nil, authors(:david).categories.find_by_name('Technology')
271
+ end
272
+
273
+ def test_has_many_going_through_join_model_with_custom_foreign_key
274
+ assert_equal [], posts(:thinking).authors
275
+ assert_equal [authors(:mary)], posts(:authorless).authors
276
+ end
277
+
278
+ def test_belongs_to_polymorphic_with_counter_cache
279
+ assert_equal 0, posts(:welcome)[:taggings_count]
280
+ tagging = posts(:welcome).taggings.create(:tag => tags(:general))
281
+ assert_equal 1, posts(:welcome, :reload)[:taggings_count]
282
+ tagging.destroy
283
+ assert posts(:welcome, :reload)[:taggings_count].zero?
284
+ end
285
+
286
+ def test_unavailable_through_reflection
287
+ assert_raises (ActiveRecord::HasManyThroughAssociationNotFoundError) { authors(:david).nothings }
288
+ end
289
+
290
+ def test_has_many_through_join_model_with_conditions
291
+ assert_equal [], posts(:welcome).invalid_taggings
292
+ assert_equal [], posts(:welcome).invalid_tags
293
+ end
294
+
295
+ def test_has_many_polymorphic
296
+ assert_raises ActiveRecord::HasManyThroughAssociationPolymorphicError do
297
+ assert_equal [posts(:welcome), posts(:thinking)], tags(:general).taggables
298
+ end
299
+ assert_raises ActiveRecord::EagerLoadPolymorphicError do
300
+ assert_equal [posts(:welcome), posts(:thinking)], tags(:general).taggings.find(:all, :include => :taggable)
301
+ end
302
+ end
303
+
304
+ def test_has_many_polymorphic_with_source_type
305
+ assert_equal [posts(:welcome), posts(:thinking)], tags(:general).tagged_posts
306
+ end
307
+
308
+ def test_eager_has_many_polymorphic_with_source_type
309
+ tag_with_include = Tag.find(tags(:general).id, :include => :tagged_posts)
310
+ desired = [posts(:welcome), posts(:thinking)]
311
+ assert_no_queries do
312
+ assert_equal desired, tag_with_include.tagged_posts
313
+ end
314
+ end
315
+
316
+ def test_has_many_through_has_many_find_all
317
+ assert_equal comments(:greetings), authors(:david).comments.find(:all, :order => 'comments.id').first
318
+ end
319
+
320
+ def test_has_many_through_has_many_find_all_with_custom_class
321
+ assert_equal comments(:greetings), authors(:david).funky_comments.find(:all, :order => 'comments.id').first
322
+ end
323
+
324
+ def test_has_many_through_has_many_find_first
325
+ assert_equal comments(:greetings), authors(:david).comments.find(:first, :order => 'comments.id')
326
+ end
327
+
328
+ def test_has_many_through_has_many_find_conditions
329
+ options = { :conditions => "comments.#{QUOTED_TYPE}='SpecialComment'", :order => 'comments.id' }
330
+ assert_equal comments(:does_it_hurt), authors(:david).comments.find(:first, options)
331
+ end
332
+
333
+ def test_has_many_through_has_many_find_by_id
334
+ assert_equal comments(:more_greetings), authors(:david).comments.find(2)
335
+ end
336
+
337
+ def test_has_many_through_polymorphic_has_one
338
+ assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).tagging }
339
+ end
340
+
341
+ def test_has_many_through_polymorphic_has_many
342
+ assert_equal [taggings(:welcome_general), taggings(:thinking_general)], authors(:david).taggings.uniq.sort_by { |t| t.id }
343
+ end
344
+
345
+ def test_include_has_many_through_polymorphic_has_many
346
+ author = Author.find_by_id(authors(:david).id, :include => :taggings)
347
+ expected_taggings = [taggings(:welcome_general), taggings(:thinking_general)]
348
+ assert_no_queries do
349
+ assert_equal expected_taggings, author.taggings.uniq.sort_by { |t| t.id }
350
+ end
351
+ end
352
+
353
+ def test_has_many_through_has_many_through
354
+ assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).tags }
355
+ end
356
+
357
+ def test_has_many_through_habtm
358
+ assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).post_categories }
359
+ end
360
+
361
+ def test_eager_load_has_many_through_has_many
362
+ author = Author.find :first, :conditions => ['name = ?', 'David'], :include => :comments, :order => 'comments.id'
363
+ SpecialComment.new; VerySpecialComment.new
364
+ assert_no_queries do
365
+ assert_equal [1,2,3,5,6,7,8,9,10], author.comments.collect(&:id)
366
+ end
367
+ end
368
+
369
+ def test_eager_load_has_many_through_has_many_with_conditions
370
+ post = Post.find(:first, :include => :invalid_tags)
371
+ assert_no_queries do
372
+ post.invalid_tags
373
+ end
374
+ end
375
+
376
+ def test_eager_belongs_to_and_has_one_not_singularized
377
+ assert_nothing_raised do
378
+ Author.find(:first, :include => :author_address)
379
+ AuthorAddress.find(:first, :include => :author)
380
+ end
381
+ end
382
+
383
+ def test_self_referential_has_many_through
384
+ assert_equal [authors(:mary)], authors(:david).favorite_authors
385
+ assert_equal [], authors(:mary).favorite_authors
386
+ end
387
+
388
+ def test_add_to_self_referential_has_many_through
389
+ new_author = Author.create(:name => "Bob")
390
+ authors(:david).author_favorites.create :favorite_author => new_author
391
+ assert_equal new_author, authors(:david).reload.favorite_authors.first
392
+ end
393
+
394
+ def test_has_many_through_uses_correct_attributes
395
+ assert_nil posts(:thinking).tags.find_by_name("General").attributes["tag_id"]
396
+ end
397
+
398
+ def test_raise_error_when_adding_new_record_to_has_many_through
399
+ assert_raise(ActiveRecord::HasManyThroughCantAssociateNewRecords) { posts(:thinking).tags << tags(:general).clone }
400
+ assert_raise(ActiveRecord::HasManyThroughCantAssociateNewRecords) { posts(:thinking).clone.tags << tags(:general) }
401
+ assert_raise(ActiveRecord::HasManyThroughCantAssociateNewRecords) { posts(:thinking).tags.build }
402
+ end
403
+
404
+ def test_create_associate_when_adding_to_has_many_through
405
+ count = posts(:thinking).tags.count
406
+ push = Tag.create!(:name => 'pushme')
407
+ post_thinking = posts(:thinking)
408
+ assert_nothing_raised { post_thinking.tags << push }
409
+ assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
410
+ message = "Expected a Tag in tags collection, got #{wrong.class}.")
411
+ assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
412
+ message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
413
+ assert_equal(count + 1, post_thinking.tags.size)
414
+ assert_equal(count + 1, post_thinking.tags(true).size)
415
+
416
+ assert_nothing_raised { post_thinking.tags.create!(:name => 'foo') }
417
+ assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
418
+ message = "Expected a Tag in tags collection, got #{wrong.class}.")
419
+ assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
420
+ message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
421
+ assert_equal(count + 2, post_thinking.tags.size)
422
+ assert_equal(count + 2, post_thinking.tags(true).size)
423
+
424
+ assert_nothing_raised { post_thinking.tags.concat(Tag.create!(:name => 'abc'), Tag.create!(:name => 'def')) }
425
+ assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
426
+ message = "Expected a Tag in tags collection, got #{wrong.class}.")
427
+ assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
428
+ message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
429
+ assert_equal(count + 4, post_thinking.tags.size)
430
+ assert_equal(count + 4, post_thinking.tags(true).size)
431
+
432
+ # Raises if the wrong reflection name is used to set the Edge belongs_to
433
+ assert_nothing_raised { vertices(:vertex_1).sinks << vertices(:vertex_5) }
434
+ end
435
+
436
+ def test_adding_junk_to_has_many_through_should_raise_type_mismatch
437
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:thinking).tags << "Uhh what now?" }
438
+ end
439
+
440
+ def test_adding_to_has_many_through_should_return_self
441
+ tags = posts(:thinking).tags
442
+ assert_equal tags, posts(:thinking).tags.push(tags(:general))
443
+ end
444
+
445
+ def test_delete_associate_when_deleting_from_has_many_through
446
+ count = posts(:thinking).tags.count
447
+ tags_before = posts(:thinking).tags
448
+ tag = Tag.create!(:name => 'doomed')
449
+ post_thinking = posts(:thinking)
450
+ post_thinking.tags << tag
451
+ assert_equal(count + 1, post_thinking.tags(true).size)
452
+
453
+ assert_nothing_raised { post_thinking.tags.delete(tag) }
454
+ assert_equal(count, post_thinking.tags.size)
455
+ assert_equal(count, post_thinking.tags(true).size)
456
+ assert_equal(tags_before.sort, post_thinking.tags.sort)
457
+ end
458
+
459
+ def test_delete_associate_when_deleting_from_has_many_through_with_multiple_tags
460
+ count = posts(:thinking).tags.count
461
+ tags_before = posts(:thinking).tags
462
+ doomed = Tag.create!(:name => 'doomed')
463
+ doomed2 = Tag.create!(:name => 'doomed2')
464
+ quaked = Tag.create!(:name => 'quaked')
465
+ post_thinking = posts(:thinking)
466
+ post_thinking.tags << doomed << doomed2
467
+ assert_equal(count + 2, post_thinking.tags(true).size)
468
+
469
+ assert_nothing_raised { post_thinking.tags.delete(doomed, doomed2, quaked) }
470
+ assert_equal(count, post_thinking.tags.size)
471
+ assert_equal(count, post_thinking.tags(true).size)
472
+ assert_equal(tags_before.sort, post_thinking.tags.sort)
473
+ end
474
+
475
+ def test_deleting_junk_from_has_many_through_should_raise_type_mismatch
476
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:thinking).tags.delete("Uhh what now?") }
477
+ end
478
+
479
+ def test_has_many_through_sum_uses_calculations
480
+ assert_nothing_raised { authors(:david).comments.sum(:post_id) }
481
+ end
482
+
483
+ def test_has_many_through_has_many_with_sti
484
+ assert_equal [comments(:does_it_hurt)], authors(:david).special_post_comments
485
+ end
486
+
487
+ private
488
+ # create dynamic Post models to allow different dependency options
489
+ def find_post_with_dependency(post_id, association, association_name, dependency)
490
+ class_name = "PostWith#{association.to_s.classify}#{dependency.to_s.classify}"
491
+ Post.find(post_id).update_attribute :type, class_name
492
+ klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
493
+ klass.set_table_name 'posts'
494
+ klass.send(association, association_name, :as => :taggable, :dependent => dependency)
495
+ klass.find(post_id)
496
+ end
497
+ end