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,146 @@
1
+ class Author < ActiveRecord::Base
2
+ has_many :posts
3
+ has_many :very_special_comments, :through => :posts
4
+ has_many :posts_with_comments, :include => :comments, :class_name => "Post"
5
+ has_many :popular_grouped_posts, :include => :comments, :class_name => "Post", :group => "type", :having => "SUM(comments_count) > 1", :select => "type"
6
+ has_many :posts_with_comments_sorted_by_comment_id, :include => :comments, :class_name => "Post", :order => 'comments.id'
7
+ has_many :posts_sorted_by_id_limited, :class_name => "Post", :order => 'posts.id', :limit => 1
8
+ has_many :posts_with_categories, :include => :categories, :class_name => "Post"
9
+ has_many :posts_with_comments_and_categories, :include => [ :comments, :categories ], :order => "posts.id", :class_name => "Post"
10
+ has_many :posts_containing_the_letter_a, :class_name => "Post"
11
+ has_many :posts_with_extension, :class_name => "Post" do #, :extend => ProxyTestExtension
12
+ def testing_proxy_owner
13
+ proxy_owner
14
+ end
15
+ def testing_proxy_reflection
16
+ proxy_reflection
17
+ end
18
+ def testing_proxy_target
19
+ proxy_target
20
+ end
21
+ end
22
+ has_one :post_about_thinking, :class_name => 'Post', :conditions => "posts.title like '%thinking%'"
23
+ has_one :post_about_thinking_with_last_comment, :class_name => 'Post', :conditions => "posts.title like '%thinking%'", :include => :last_comment
24
+ has_many :comments, :through => :posts
25
+ has_many :comments_containing_the_letter_e, :through => :posts, :source => :comments
26
+ has_many :comments_with_order_and_conditions, :through => :posts, :source => :comments, :order => 'comments.body', :conditions => "comments.body like 'Thank%'"
27
+ has_many :comments_with_include, :through => :posts, :source => :comments, :include => :post
28
+
29
+ has_many :thinking_posts, :class_name => 'Post', :conditions => { :title => 'So I was thinking' }, :dependent => :delete_all
30
+ has_many :welcome_posts, :class_name => 'Post', :conditions => { :title => 'Welcome to the weblog' }
31
+
32
+ has_many :comments_desc, :through => :posts, :source => :comments, :order => 'comments.id DESC'
33
+ has_many :limited_comments, :through => :posts, :source => :comments, :limit => 1
34
+ has_many :funky_comments, :through => :posts, :source => :comments
35
+ has_many :ordered_uniq_comments, :through => :posts, :source => :comments, :uniq => true, :order => 'comments.id'
36
+ has_many :ordered_uniq_comments_desc, :through => :posts, :source => :comments, :uniq => true, :order => 'comments.id DESC'
37
+ has_many :readonly_comments, :through => :posts, :source => :comments, :readonly => true
38
+
39
+ has_many :special_posts
40
+ has_many :special_post_comments, :through => :special_posts, :source => :comments
41
+
42
+ has_many :sti_posts, :class_name => 'StiPost'
43
+ has_many :sti_post_comments, :through => :sti_posts, :source => :comments
44
+
45
+ has_many :special_nonexistant_posts, :class_name => "SpecialPost", :conditions => "posts.body = 'nonexistant'"
46
+ has_many :special_nonexistant_post_comments, :through => :special_nonexistant_posts, :source => :comments, :conditions => "comments.post_id = 0"
47
+ has_many :nonexistant_comments, :through => :posts
48
+
49
+ has_many :hello_posts, :class_name => "Post", :conditions => "posts.body = 'hello'"
50
+ has_many :hello_post_comments, :through => :hello_posts, :source => :comments
51
+ has_many :posts_with_no_comments, :class_name => 'Post', :conditions => 'comments.id is null', :include => :comments
52
+
53
+ has_many :hello_posts_with_hash_conditions, :class_name => "Post",
54
+ :conditions => {:body => 'hello'}
55
+ has_many :hello_post_comments_with_hash_conditions, :through =>
56
+ :hello_posts_with_hash_conditions, :source => :comments
57
+
58
+ has_many :other_posts, :class_name => "Post"
59
+ has_many :posts_with_callbacks, :class_name => "Post", :before_add => :log_before_adding,
60
+ :after_add => :log_after_adding,
61
+ :before_remove => :log_before_removing,
62
+ :after_remove => :log_after_removing
63
+ has_many :posts_with_proc_callbacks, :class_name => "Post",
64
+ :before_add => Proc.new {|o, r| o.post_log << "before_adding#{r.id || '<new>'}"},
65
+ :after_add => Proc.new {|o, r| o.post_log << "after_adding#{r.id || '<new>'}"},
66
+ :before_remove => Proc.new {|o, r| o.post_log << "before_removing#{r.id}"},
67
+ :after_remove => Proc.new {|o, r| o.post_log << "after_removing#{r.id}"}
68
+ has_many :posts_with_multiple_callbacks, :class_name => "Post",
69
+ :before_add => [:log_before_adding, Proc.new {|o, r| o.post_log << "before_adding_proc#{r.id || '<new>'}"}],
70
+ :after_add => [:log_after_adding, Proc.new {|o, r| o.post_log << "after_adding_proc#{r.id || '<new>'}"}]
71
+ has_many :unchangable_posts, :class_name => "Post", :before_add => :raise_exception, :after_add => :log_after_adding
72
+
73
+ has_many :categorizations
74
+ has_many :categories, :through => :categorizations
75
+
76
+ has_many :categories_like_general, :through => :categorizations, :source => :category, :class_name => 'Category', :conditions => { :name => 'General' }
77
+
78
+ has_many :categorized_posts, :through => :categorizations, :source => :post
79
+ has_many :unique_categorized_posts, :through => :categorizations, :source => :post, :uniq => true
80
+
81
+ has_many :nothings, :through => :kateggorisatons, :class_name => 'Category'
82
+
83
+ has_many :author_favorites
84
+ has_many :favorite_authors, :through => :author_favorites, :order => 'name'
85
+
86
+ has_many :tagging, :through => :posts # through polymorphic has_one
87
+ has_many :taggings, :through => :posts, :source => :taggings # through polymorphic has_many
88
+ has_many :tags, :through => :posts # through has_many :through
89
+ has_many :post_categories, :through => :posts, :source => :categories
90
+
91
+ has_one :essay, :primary_key => :name, :as => :writer
92
+
93
+ belongs_to :author_address, :dependent => :destroy
94
+ belongs_to :author_address_extra, :dependent => :delete, :class_name => "AuthorAddress"
95
+
96
+ attr_accessor :post_log
97
+
98
+ def after_initialize
99
+ @post_log = []
100
+ end
101
+
102
+ def label
103
+ "#{id}-#{name}"
104
+ end
105
+
106
+ private
107
+ def log_before_adding(object)
108
+ @post_log << "before_adding#{object.id || '<new>'}"
109
+ end
110
+
111
+ def log_after_adding(object)
112
+ @post_log << "after_adding#{object.id}"
113
+ end
114
+
115
+ def log_before_removing(object)
116
+ @post_log << "before_removing#{object.id}"
117
+ end
118
+
119
+ def log_after_removing(object)
120
+ @post_log << "after_removing#{object.id}"
121
+ end
122
+
123
+ def raise_exception(object)
124
+ raise Exception.new("You can't add a post")
125
+ end
126
+ end
127
+
128
+ class AuthorAddress < ActiveRecord::Base
129
+ has_one :author
130
+
131
+ def self.destroyed_author_address_ids
132
+ @destroyed_author_address_ids ||= Hash.new { |h,k| h[k] = [] }
133
+ end
134
+
135
+ before_destroy do |author_address|
136
+ if author_address.author
137
+ AuthorAddress.destroyed_author_address_ids[author_address.author.id] << author_address.id
138
+ end
139
+ true
140
+ end
141
+ end
142
+
143
+ class AuthorFavorite < ActiveRecord::Base
144
+ belongs_to :author
145
+ belongs_to :favorite_author, :class_name => "Author"
146
+ end
@@ -0,0 +1,4 @@
1
+ class AutoId < ActiveRecord::Base
2
+ def self.table_name () "auto_id_tests" end
3
+ def self.primary_key () "auto_id" end
4
+ end
@@ -0,0 +1,2 @@
1
+ class Binary < ActiveRecord::Base
2
+ end
@@ -0,0 +1,3 @@
1
+ class Bird < ActiveRecord::Base
2
+ validates_presence_of :name
3
+ end
@@ -0,0 +1,4 @@
1
+ class Book < ActiveRecord::Base
2
+ has_many :citations, :foreign_key => 'book1_id'
3
+ has_many :references, :through => :citations, :source => :reference_of, :uniq => true
4
+ end
@@ -0,0 +1,5 @@
1
+ class Categorization < ActiveRecord::Base
2
+ belongs_to :post
3
+ belongs_to :category
4
+ belongs_to :author
5
+ end
@@ -0,0 +1,34 @@
1
+ class Category < ActiveRecord::Base
2
+ has_and_belongs_to_many :posts
3
+ has_and_belongs_to_many :special_posts, :class_name => "Post"
4
+ has_and_belongs_to_many :other_posts, :class_name => "Post"
5
+ has_and_belongs_to_many :posts_with_authors_sorted_by_author_id, :class_name => "Post", :include => :authors, :order => "authors.id"
6
+
7
+ has_and_belongs_to_many(:select_testing_posts,
8
+ :class_name => 'Post',
9
+ :foreign_key => 'category_id',
10
+ :association_foreign_key => 'post_id',
11
+ :select => 'posts.*, 1 as correctness_marker')
12
+
13
+ has_and_belongs_to_many :post_with_conditions,
14
+ :class_name => 'Post',
15
+ :conditions => { :title => 'Yet Another Testing Title' }
16
+
17
+ has_and_belongs_to_many :popular_grouped_posts, :class_name => "Post", :group => "posts.type", :having => "sum(comments.post_id) > 2", :include => :comments
18
+ has_and_belongs_to_many :posts_gruoped_by_title, :class_name => "Post", :group => "title", :select => "title"
19
+
20
+ def self.what_are_you
21
+ 'a category...'
22
+ end
23
+
24
+ has_many :categorizations
25
+ has_many :authors, :through => :categorizations, :select => 'authors.*, categorizations.post_id'
26
+ end
27
+
28
+ class SpecialCategory < Category
29
+
30
+ def self.what_are_you
31
+ 'a special category...'
32
+ end
33
+
34
+ end
@@ -0,0 +1,6 @@
1
+ class Citation < ActiveRecord::Base
2
+ belongs_to :reference_of, :class_name => "Book", :foreign_key => :book2_id
3
+
4
+ belongs_to :book1, :class_name => "Book", :foreign_key => :book1_id
5
+ belongs_to :book2, :class_name => "Book", :foreign_key => :book2_id
6
+ end
@@ -0,0 +1,13 @@
1
+ class Club < ActiveRecord::Base
2
+ has_many :memberships
3
+ has_many :members, :through => :memberships
4
+ has_many :current_memberships
5
+ has_one :sponsor
6
+ has_one :sponsored_member, :through => :sponsor, :source => :sponsorable, :source_type => "Member"
7
+
8
+ private
9
+
10
+ def private_method
11
+ "I'm sorry sir, this is a *private* club, not a *pirate* club"
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ class ColumnName < ActiveRecord::Base
2
+ def self.table_name () "colnametests" end
3
+ end
@@ -0,0 +1,29 @@
1
+ class Comment < ActiveRecord::Base
2
+ named_scope :containing_the_letter_e, :conditions => "comments.body LIKE '%e%'"
3
+ named_scope :for_first_post, :conditions => { :post_id => 1 }
4
+ named_scope :for_first_author,
5
+ :joins => :post,
6
+ :conditions => { "posts.author_id" => 1 }
7
+
8
+ belongs_to :post, :counter_cache => true
9
+
10
+ def self.what_are_you
11
+ 'a comment...'
12
+ end
13
+
14
+ def self.search_by_type(q)
15
+ self.find(:all, :conditions => ["#{QUOTED_TYPE} = ?", q])
16
+ end
17
+ end
18
+
19
+ class SpecialComment < Comment
20
+ def self.what_are_you
21
+ 'a special comment...'
22
+ end
23
+ end
24
+
25
+ class VerySpecialComment < Comment
26
+ def self.what_are_you
27
+ 'a very special comment...'
28
+ end
29
+ end
@@ -0,0 +1,171 @@
1
+ class AbstractCompany < ActiveRecord::Base
2
+ self.abstract_class = true
3
+ end
4
+
5
+ class Company < AbstractCompany
6
+ attr_protected :rating
7
+ set_sequence_name :companies_nonstd_seq
8
+
9
+ validates_presence_of :name
10
+
11
+ has_one :dummy_account, :foreign_key => "firm_id", :class_name => "Account"
12
+ has_many :contracts
13
+ has_many :developers, :through => :contracts
14
+
15
+ def arbitrary_method
16
+ "I am Jack's profound disappointment"
17
+ end
18
+
19
+ private
20
+
21
+ def private_method
22
+ "I am Jack's innermost fears and aspirations"
23
+ end
24
+ end
25
+
26
+ module Namespaced
27
+ class Company < ::Company
28
+ end
29
+
30
+ class Firm < ::Company
31
+ has_many :clients, :class_name => 'Namespaced::Client'
32
+ end
33
+
34
+ class Client < ::Company
35
+ end
36
+ end
37
+
38
+ class Firm < Company
39
+ has_many :clients, :order => "id", :dependent => :destroy, :counter_sql =>
40
+ "SELECT COUNT(*) FROM companies WHERE firm_id = 1 " +
41
+ "AND (#{QUOTED_TYPE} = 'Client' OR #{QUOTED_TYPE} = 'SpecialClient' OR #{QUOTED_TYPE} = 'VerySpecialClient' )"
42
+ has_many :unsorted_clients, :class_name => "Client"
43
+ has_many :clients_sorted_desc, :class_name => "Client", :order => "id DESC"
44
+ has_many :clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id"
45
+ has_many :unvalidated_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :validate => false
46
+ has_many :dependent_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id", :dependent => :destroy
47
+ has_many :exclusively_dependent_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id", :dependent => :delete_all
48
+ has_many :limited_clients, :class_name => "Client", :order => "id", :limit => 1
49
+ has_many :clients_like_ms, :conditions => "name = 'Microsoft'", :class_name => "Client", :order => "id"
50
+ has_many :clients_with_interpolated_conditions, :class_name => "Client", :conditions => 'rating > #{rating}'
51
+ has_many :clients_like_ms_with_hash_conditions, :conditions => { :name => 'Microsoft' }, :class_name => "Client", :order => "id"
52
+ has_many :clients_using_sql, :class_name => "Client", :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}'
53
+ has_many :clients_using_counter_sql, :class_name => "Client",
54
+ :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}',
55
+ :counter_sql => 'SELECT COUNT(*) FROM companies WHERE client_of = #{id}'
56
+ has_many :clients_using_zero_counter_sql, :class_name => "Client",
57
+ :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}',
58
+ :counter_sql => 'SELECT 0 FROM companies WHERE client_of = #{id}'
59
+ has_many :no_clients_using_counter_sql, :class_name => "Client",
60
+ :finder_sql => 'SELECT * FROM companies WHERE client_of = 1000',
61
+ :counter_sql => 'SELECT COUNT(*) FROM companies WHERE client_of = 1000'
62
+ has_many :clients_using_finder_sql, :class_name => "Client", :finder_sql => 'SELECT * FROM companies WHERE 1=1'
63
+ has_many :plain_clients, :class_name => 'Client'
64
+ has_many :readonly_clients, :class_name => 'Client', :readonly => true
65
+ has_many :clients_using_primary_key, :class_name => 'Client',
66
+ :primary_key => 'name', :foreign_key => 'firm_name'
67
+ has_many :clients_using_primary_key_with_delete_all, :class_name => 'Client',
68
+ :primary_key => 'name', :foreign_key => 'firm_name', :dependent => :delete_all
69
+ has_many :clients_grouped_by_firm_id, :class_name => "Client", :group => "firm_id", :select => "firm_id"
70
+ has_many :clients_grouped_by_name, :class_name => "Client", :group => "name", :select => "name"
71
+
72
+ has_one :account, :foreign_key => "firm_id", :dependent => :destroy, :validate => true
73
+ has_one :unvalidated_account, :foreign_key => "firm_id", :class_name => 'Account', :validate => false
74
+ has_one :account_with_select, :foreign_key => "firm_id", :select => "id, firm_id", :class_name=>'Account'
75
+ has_one :readonly_account, :foreign_key => "firm_id", :class_name => "Account", :readonly => true
76
+ has_one :account_using_primary_key, :primary_key => "firm_id", :class_name => "Account"
77
+ has_one :account_using_foreign_and_primary_keys, :foreign_key => "firm_name", :primary_key => "name", :class_name => "Account"
78
+ has_one :deletable_account, :foreign_key => "firm_id", :class_name => "Account", :dependent => :delete
79
+
80
+ has_one :account_limit_500_with_hash_conditions, :foreign_key => "firm_id", :class_name => "Account", :conditions => { :credit_limit => 500 }
81
+
82
+ has_one :unautosaved_account, :foreign_key => "firm_id", :class_name => 'Account', :autosave => false
83
+ has_many :accounts
84
+ has_many :unautosaved_accounts, :foreign_key => "firm_id", :class_name => 'Account', :autosave => false
85
+ end
86
+
87
+ class DependentFirm < Company
88
+ has_one :account, :foreign_key => "firm_id", :dependent => :nullify
89
+ has_many :companies, :foreign_key => 'client_of', :order => "id", :dependent => :nullify
90
+ end
91
+
92
+ class Client < Company
93
+ belongs_to :firm, :foreign_key => "client_of"
94
+ belongs_to :firm_with_basic_id, :class_name => "Firm", :foreign_key => "firm_id"
95
+ belongs_to :firm_with_select, :class_name => "Firm", :foreign_key => "firm_id", :select => "id"
96
+ belongs_to :firm_with_other_name, :class_name => "Firm", :foreign_key => "client_of"
97
+ belongs_to :firm_with_condition, :class_name => "Firm", :foreign_key => "client_of", :conditions => ["1 = ?", 1]
98
+ belongs_to :firm_with_primary_key, :class_name => "Firm", :primary_key => "name", :foreign_key => "firm_name"
99
+ belongs_to :readonly_firm, :class_name => "Firm", :foreign_key => "firm_id", :readonly => true
100
+
101
+ # Record destruction so we can test whether firm.clients.clear has
102
+ # is calling client.destroy, deleting from the database, or setting
103
+ # foreign keys to NULL.
104
+ def self.destroyed_client_ids
105
+ @destroyed_client_ids ||= Hash.new { |h,k| h[k] = [] }
106
+ end
107
+
108
+ before_destroy do |client|
109
+ if client.firm
110
+ Client.destroyed_client_ids[client.firm.id] << client.id
111
+ end
112
+ true
113
+ end
114
+
115
+ # Used to test that read and question methods are not generated for these attributes
116
+ def ruby_type
117
+ read_attribute :ruby_type
118
+ end
119
+
120
+ def rating?
121
+ query_attribute :rating
122
+ end
123
+
124
+ class << self
125
+ private
126
+
127
+ def private_method
128
+ "darkness"
129
+ end
130
+ end
131
+ end
132
+
133
+ class ExclusivelyDependentFirm < Company
134
+ has_one :account, :foreign_key => "firm_id", :dependent => :delete
135
+ has_many :dependent_sanitized_conditional_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id", :dependent => :delete_all, :conditions => "name = 'BigShot Inc.'"
136
+ has_many :dependent_conditional_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id", :dependent => :delete_all, :conditions => ["name = ?", 'BigShot Inc.']
137
+ has_many :dependent_hash_conditional_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id", :dependent => :delete_all, :conditions => {:name => 'BigShot Inc.'}
138
+ end
139
+
140
+ class SpecialClient < Client
141
+ end
142
+
143
+ class VerySpecialClient < SpecialClient
144
+ end
145
+
146
+ class Account < ActiveRecord::Base
147
+ belongs_to :firm
148
+ belongs_to :unautosaved_firm, :foreign_key => "firm_id", :class_name => "Firm", :autosave => false
149
+
150
+ def self.destroyed_account_ids
151
+ @destroyed_account_ids ||= Hash.new { |h,k| h[k] = [] }
152
+ end
153
+
154
+ before_destroy do |account|
155
+ if account.firm
156
+ Account.destroyed_account_ids[account.firm.id] << account.id
157
+ end
158
+ true
159
+ end
160
+
161
+ protected
162
+ def validate
163
+ errors.add_on_empty "credit_limit"
164
+ end
165
+
166
+ private
167
+
168
+ def private_method
169
+ "Sir, yes sir!"
170
+ end
171
+ end
@@ -0,0 +1,61 @@
1
+ module MyApplication
2
+ module Business
3
+ class Company < ActiveRecord::Base
4
+ attr_protected :rating
5
+ end
6
+
7
+ class Firm < Company
8
+ has_many :clients, :order => "id", :dependent => :destroy
9
+ has_many :clients_sorted_desc, :class_name => "Client", :order => "id DESC"
10
+ has_many :clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id"
11
+ has_many :clients_like_ms, :conditions => "name = 'Microsoft'", :class_name => "Client", :order => "id"
12
+ has_many :clients_using_sql, :class_name => "Client", :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}'
13
+
14
+ has_one :account, :class_name => 'MyApplication::Billing::Account', :dependent => :destroy
15
+ end
16
+
17
+ class Client < Company
18
+ belongs_to :firm, :foreign_key => "client_of"
19
+ belongs_to :firm_with_other_name, :class_name => "Firm", :foreign_key => "client_of"
20
+
21
+ class Contact < ActiveRecord::Base; end
22
+ end
23
+
24
+ class Developer < ActiveRecord::Base
25
+ has_and_belongs_to_many :projects
26
+ validates_length_of :name, :within => (3..20)
27
+ end
28
+
29
+ class Project < ActiveRecord::Base
30
+ has_and_belongs_to_many :developers
31
+ end
32
+
33
+ end
34
+
35
+ module Billing
36
+ class Firm < ActiveRecord::Base
37
+ self.table_name = 'companies'
38
+ end
39
+
40
+ module Nested
41
+ class Firm < ActiveRecord::Base
42
+ self.table_name = 'companies'
43
+ end
44
+ end
45
+
46
+ class Account < ActiveRecord::Base
47
+ with_options(:foreign_key => :firm_id) do |i|
48
+ i.belongs_to :firm, :class_name => 'MyApplication::Business::Firm'
49
+ i.belongs_to :qualified_billing_firm, :class_name => 'MyApplication::Billing::Firm'
50
+ i.belongs_to :unqualified_billing_firm, :class_name => 'Firm'
51
+ i.belongs_to :nested_qualified_billing_firm, :class_name => 'MyApplication::Billing::Nested::Firm'
52
+ i.belongs_to :nested_unqualified_billing_firm, :class_name => 'Nested::Firm'
53
+ end
54
+
55
+ protected
56
+ def validate
57
+ errors.add_on_empty "credit_limit"
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,3 @@
1
+ class Computer < ActiveRecord::Base
2
+ belongs_to :developer, :foreign_key=>'developer'
3
+ end
@@ -0,0 +1,16 @@
1
+ class Contact < ActiveRecord::Base
2
+ # mock out self.columns so no pesky db is needed for these tests
3
+ def self.column(name, sql_type = nil, options = {})
4
+ @columns ||= []
5
+ @columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, options[:default], sql_type.to_s, options[:null])
6
+ end
7
+
8
+ column :name, :string
9
+ column :age, :integer
10
+ column :avatar, :binary
11
+ column :created_at, :datetime
12
+ column :awesome, :boolean
13
+ column :preferences, :string
14
+
15
+ serialize :preferences
16
+ end
@@ -0,0 +1,5 @@
1
+ class Contract < ActiveRecord::Base
2
+ belongs_to :company
3
+ belongs_to :developer
4
+ end
5
+
@@ -0,0 +1,3 @@
1
+ class Course < ActiveRecord::Base
2
+ has_many :entrants
3
+ end
@@ -0,0 +1,73 @@
1
+ class Customer < ActiveRecord::Base
2
+ composed_of :address, :mapping => [ %w(address_street street), %w(address_city city), %w(address_country country) ], :allow_nil => true
3
+ composed_of :balance, :class_name => "Money", :mapping => %w(balance amount), :converter => Proc.new { |balance| balance.to_money }
4
+ composed_of :gps_location, :allow_nil => true
5
+ composed_of :fullname, :mapping => %w(name to_s), :constructor => Proc.new { |name| Fullname.parse(name) }, :converter => :parse
6
+ end
7
+
8
+ class Address
9
+ attr_reader :street, :city, :country
10
+
11
+ def initialize(street, city, country)
12
+ @street, @city, @country = street, city, country
13
+ end
14
+
15
+ def close_to?(other_address)
16
+ city == other_address.city && country == other_address.country
17
+ end
18
+
19
+ def ==(other)
20
+ other.is_a?(self.class) && other.street == street && other.city == city && other.country == country
21
+ end
22
+ end
23
+
24
+ class Money
25
+ attr_reader :amount, :currency
26
+
27
+ EXCHANGE_RATES = { "USD_TO_DKK" => 6, "DKK_TO_USD" => 0.6 }
28
+
29
+ def initialize(amount, currency = "USD")
30
+ @amount, @currency = amount, currency
31
+ end
32
+
33
+ def exchange_to(other_currency)
34
+ Money.new((amount * EXCHANGE_RATES["#{currency}_TO_#{other_currency}"]).floor, other_currency)
35
+ end
36
+ end
37
+
38
+ class GpsLocation
39
+ attr_reader :gps_location
40
+
41
+ def initialize(gps_location)
42
+ @gps_location = gps_location
43
+ end
44
+
45
+ def latitude
46
+ gps_location.split("x").first
47
+ end
48
+
49
+ def longitude
50
+ gps_location.split("x").last
51
+ end
52
+
53
+ def ==(other)
54
+ self.latitude == other.latitude && self.longitude == other.longitude
55
+ end
56
+ end
57
+
58
+ class Fullname
59
+ attr_reader :first, :last
60
+
61
+ def self.parse(str)
62
+ return nil unless str
63
+ new(*str.to_s.split)
64
+ end
65
+
66
+ def initialize(first, last = nil)
67
+ @first, @last = first, last
68
+ end
69
+
70
+ def to_s
71
+ "#{first} #{last.upcase}"
72
+ end
73
+ end
@@ -0,0 +1,2 @@
1
+ class Default < ActiveRecord::Base
2
+ end