activerecord 1.0.0 → 2.0.0

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

Potentially problematic release.


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

Files changed (311) hide show
  1. data/CHANGELOG +4928 -3
  2. data/README +45 -46
  3. data/RUNNING_UNIT_TESTS +8 -11
  4. data/Rakefile +247 -0
  5. data/install.rb +8 -38
  6. data/lib/active_record/aggregations.rb +64 -49
  7. data/lib/active_record/associations/association_collection.rb +217 -47
  8. data/lib/active_record/associations/association_proxy.rb +159 -0
  9. data/lib/active_record/associations/belongs_to_association.rb +56 -0
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
  11. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +155 -37
  12. data/lib/active_record/associations/has_many_association.rb +145 -75
  13. data/lib/active_record/associations/has_many_through_association.rb +283 -0
  14. data/lib/active_record/associations/has_one_association.rb +96 -0
  15. data/lib/active_record/associations.rb +1537 -304
  16. data/lib/active_record/attribute_methods.rb +328 -0
  17. data/lib/active_record/base.rb +2001 -588
  18. data/lib/active_record/calculations.rb +269 -0
  19. data/lib/active_record/callbacks.rb +169 -165
  20. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +308 -0
  21. data/lib/active_record/connection_adapters/abstract/database_statements.rb +171 -0
  22. data/lib/active_record/connection_adapters/abstract/query_cache.rb +87 -0
  23. data/lib/active_record/connection_adapters/abstract/quoting.rb +69 -0
  24. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +472 -0
  25. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +306 -0
  26. data/lib/active_record/connection_adapters/abstract_adapter.rb +125 -279
  27. data/lib/active_record/connection_adapters/mysql_adapter.rb +442 -77
  28. data/lib/active_record/connection_adapters/postgresql_adapter.rb +805 -135
  29. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -0
  30. data/lib/active_record/connection_adapters/sqlite_adapter.rb +353 -69
  31. data/lib/active_record/fixtures.rb +946 -100
  32. data/lib/active_record/locking/optimistic.rb +144 -0
  33. data/lib/active_record/locking/pessimistic.rb +77 -0
  34. data/lib/active_record/migration.rb +417 -0
  35. data/lib/active_record/observer.rb +142 -32
  36. data/lib/active_record/query_cache.rb +23 -0
  37. data/lib/active_record/reflection.rb +163 -70
  38. data/lib/active_record/schema.rb +58 -0
  39. data/lib/active_record/schema_dumper.rb +171 -0
  40. data/lib/active_record/serialization.rb +98 -0
  41. data/lib/active_record/serializers/json_serializer.rb +71 -0
  42. data/lib/active_record/serializers/xml_serializer.rb +315 -0
  43. data/lib/active_record/timestamp.rb +41 -0
  44. data/lib/active_record/transactions.rb +87 -57
  45. data/lib/active_record/validations.rb +909 -122
  46. data/lib/active_record/vendor/db2.rb +362 -0
  47. data/lib/active_record/vendor/mysql.rb +126 -29
  48. data/lib/active_record/version.rb +9 -0
  49. data/lib/active_record.rb +35 -7
  50. data/lib/activerecord.rb +1 -0
  51. data/test/aaa_create_tables_test.rb +72 -0
  52. data/test/abstract_unit.rb +73 -5
  53. data/test/active_schema_test_mysql.rb +43 -0
  54. data/test/adapter_test.rb +105 -0
  55. data/test/adapter_test_sqlserver.rb +95 -0
  56. data/test/aggregations_test.rb +110 -16
  57. data/test/all.sh +2 -2
  58. data/test/ar_schema_test.rb +33 -0
  59. data/test/association_inheritance_reload.rb +14 -0
  60. data/test/associations/ar_joins_test.rb +0 -0
  61. data/test/associations/callbacks_test.rb +147 -0
  62. data/test/associations/cascaded_eager_loading_test.rb +110 -0
  63. data/test/associations/eager_singularization_test.rb +145 -0
  64. data/test/associations/eager_test.rb +442 -0
  65. data/test/associations/extension_test.rb +47 -0
  66. data/test/associations/inner_join_association_test.rb +88 -0
  67. data/test/associations/join_model_test.rb +553 -0
  68. data/test/associations_test.rb +1930 -267
  69. data/test/attribute_methods_test.rb +146 -0
  70. data/test/base_test.rb +1316 -84
  71. data/test/binary_test.rb +32 -0
  72. data/test/calculations_test.rb +251 -0
  73. data/test/callbacks_test.rb +400 -0
  74. data/test/class_inheritable_attributes_test.rb +3 -4
  75. data/test/column_alias_test.rb +17 -0
  76. data/test/connection_test_firebird.rb +8 -0
  77. data/test/connection_test_mysql.rb +30 -0
  78. data/test/connections/native_db2/connection.rb +25 -0
  79. data/test/connections/native_firebird/connection.rb +26 -0
  80. data/test/connections/native_frontbase/connection.rb +27 -0
  81. data/test/connections/native_mysql/connection.rb +21 -18
  82. data/test/connections/native_openbase/connection.rb +21 -0
  83. data/test/connections/native_oracle/connection.rb +27 -0
  84. data/test/connections/native_postgresql/connection.rb +17 -18
  85. data/test/connections/native_sqlite/connection.rb +17 -16
  86. data/test/connections/native_sqlite3/connection.rb +25 -0
  87. data/test/connections/native_sqlite3/in_memory_connection.rb +18 -0
  88. data/test/connections/native_sybase/connection.rb +23 -0
  89. data/test/copy_table_test_sqlite.rb +69 -0
  90. data/test/datatype_test_postgresql.rb +203 -0
  91. data/test/date_time_test.rb +37 -0
  92. data/test/default_test_firebird.rb +16 -0
  93. data/test/defaults_test.rb +67 -0
  94. data/test/deprecated_finder_test.rb +30 -0
  95. data/test/finder_test.rb +607 -32
  96. data/test/fixtures/accounts.yml +28 -0
  97. data/test/fixtures/all/developers.yml +0 -0
  98. data/test/fixtures/all/people.csv +0 -0
  99. data/test/fixtures/all/tasks.yml +0 -0
  100. data/test/fixtures/author.rb +107 -0
  101. data/test/fixtures/author_favorites.yml +4 -0
  102. data/test/fixtures/authors.yml +7 -0
  103. data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +1 -0
  104. data/test/fixtures/bad_fixtures/attr_with_spaces +1 -0
  105. data/test/fixtures/bad_fixtures/blank_line +3 -0
  106. data/test/fixtures/bad_fixtures/duplicate_attributes +3 -0
  107. data/test/fixtures/bad_fixtures/missing_value +1 -0
  108. data/test/fixtures/binaries.yml +132 -0
  109. data/test/fixtures/binary.rb +2 -0
  110. data/test/fixtures/book.rb +4 -0
  111. data/test/fixtures/books.yml +7 -0
  112. data/test/fixtures/categories/special_categories.yml +9 -0
  113. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  114. data/test/fixtures/categories.yml +14 -0
  115. data/test/fixtures/categories_ordered.yml +7 -0
  116. data/test/fixtures/categories_posts.yml +23 -0
  117. data/test/fixtures/categorization.rb +5 -0
  118. data/test/fixtures/categorizations.yml +17 -0
  119. data/test/fixtures/category.rb +26 -0
  120. data/test/fixtures/citation.rb +6 -0
  121. data/test/fixtures/comment.rb +23 -0
  122. data/test/fixtures/comments.yml +59 -0
  123. data/test/fixtures/companies.yml +55 -0
  124. data/test/fixtures/company.rb +81 -4
  125. data/test/fixtures/company_in_module.rb +32 -6
  126. data/test/fixtures/computer.rb +4 -0
  127. data/test/fixtures/computers.yml +4 -0
  128. data/test/fixtures/contact.rb +16 -0
  129. data/test/fixtures/courses.yml +7 -0
  130. data/test/fixtures/customer.rb +28 -3
  131. data/test/fixtures/customers.yml +17 -0
  132. data/test/fixtures/db_definitions/db2.drop.sql +33 -0
  133. data/test/fixtures/db_definitions/db2.sql +235 -0
  134. data/test/fixtures/db_definitions/db22.drop.sql +2 -0
  135. data/test/fixtures/db_definitions/db22.sql +5 -0
  136. data/test/fixtures/db_definitions/firebird.drop.sql +65 -0
  137. data/test/fixtures/db_definitions/firebird.sql +310 -0
  138. data/test/fixtures/db_definitions/firebird2.drop.sql +2 -0
  139. data/test/fixtures/db_definitions/firebird2.sql +6 -0
  140. data/test/fixtures/db_definitions/frontbase.drop.sql +33 -0
  141. data/test/fixtures/db_definitions/frontbase.sql +273 -0
  142. data/test/fixtures/db_definitions/frontbase2.drop.sql +1 -0
  143. data/test/fixtures/db_definitions/frontbase2.sql +4 -0
  144. data/test/fixtures/db_definitions/openbase.drop.sql +2 -0
  145. data/test/fixtures/db_definitions/openbase.sql +318 -0
  146. data/test/fixtures/db_definitions/openbase2.drop.sql +2 -0
  147. data/test/fixtures/db_definitions/openbase2.sql +7 -0
  148. data/test/fixtures/db_definitions/oracle.drop.sql +67 -0
  149. data/test/fixtures/db_definitions/oracle.sql +330 -0
  150. data/test/fixtures/db_definitions/oracle2.drop.sql +2 -0
  151. data/test/fixtures/db_definitions/oracle2.sql +6 -0
  152. data/test/fixtures/db_definitions/postgresql.drop.sql +44 -0
  153. data/test/fixtures/db_definitions/postgresql.sql +217 -38
  154. data/test/fixtures/db_definitions/postgresql2.drop.sql +2 -0
  155. data/test/fixtures/db_definitions/postgresql2.sql +2 -2
  156. data/test/fixtures/db_definitions/schema.rb +354 -0
  157. data/test/fixtures/db_definitions/schema2.rb +11 -0
  158. data/test/fixtures/db_definitions/sqlite.drop.sql +33 -0
  159. data/test/fixtures/db_definitions/sqlite.sql +139 -5
  160. data/test/fixtures/db_definitions/sqlite2.drop.sql +2 -0
  161. data/test/fixtures/db_definitions/sqlite2.sql +1 -0
  162. data/test/fixtures/db_definitions/sybase.drop.sql +35 -0
  163. data/test/fixtures/db_definitions/sybase.sql +222 -0
  164. data/test/fixtures/db_definitions/sybase2.drop.sql +4 -0
  165. data/test/fixtures/db_definitions/sybase2.sql +5 -0
  166. data/test/fixtures/developer.rb +70 -6
  167. data/test/fixtures/developers.yml +21 -0
  168. data/test/fixtures/developers_projects/david_action_controller +2 -1
  169. data/test/fixtures/developers_projects/david_active_record +2 -1
  170. data/test/fixtures/developers_projects.yml +17 -0
  171. data/test/fixtures/edge.rb +5 -0
  172. data/test/fixtures/edges.yml +6 -0
  173. data/test/fixtures/entrants.yml +14 -0
  174. data/test/fixtures/example.log +1 -0
  175. data/test/fixtures/fk_test_has_fk.yml +3 -0
  176. data/test/fixtures/fk_test_has_pk.yml +2 -0
  177. data/test/fixtures/flowers.jpg +0 -0
  178. data/test/fixtures/funny_jokes.yml +10 -0
  179. data/test/fixtures/item.rb +7 -0
  180. data/test/fixtures/items.yml +4 -0
  181. data/test/fixtures/joke.rb +3 -0
  182. data/test/fixtures/keyboard.rb +3 -0
  183. data/test/fixtures/legacy_thing.rb +3 -0
  184. data/test/fixtures/legacy_things.yml +3 -0
  185. data/test/fixtures/matey.rb +4 -0
  186. data/test/fixtures/mateys.yml +4 -0
  187. data/test/fixtures/migrations/1_people_have_last_names.rb +9 -0
  188. data/test/fixtures/migrations/2_we_need_reminders.rb +12 -0
  189. data/test/fixtures/migrations/3_innocent_jointable.rb +12 -0
  190. data/test/fixtures/migrations_with_decimal/1_give_me_big_numbers.rb +15 -0
  191. data/test/fixtures/migrations_with_duplicate/1_people_have_last_names.rb +9 -0
  192. data/test/fixtures/migrations_with_duplicate/2_we_need_reminders.rb +12 -0
  193. data/test/fixtures/migrations_with_duplicate/3_foo.rb +7 -0
  194. data/test/fixtures/migrations_with_duplicate/3_innocent_jointable.rb +12 -0
  195. data/test/fixtures/migrations_with_missing_versions/1000_people_have_middle_names.rb +9 -0
  196. data/test/fixtures/migrations_with_missing_versions/1_people_have_last_names.rb +9 -0
  197. data/test/fixtures/migrations_with_missing_versions/3_we_need_reminders.rb +12 -0
  198. data/test/fixtures/migrations_with_missing_versions/4_innocent_jointable.rb +12 -0
  199. data/test/fixtures/minimalistic.rb +2 -0
  200. data/test/fixtures/minimalistics.yml +2 -0
  201. data/test/fixtures/mixed_case_monkey.rb +3 -0
  202. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  203. data/test/fixtures/mixins.yml +29 -0
  204. data/test/fixtures/movies.yml +7 -0
  205. data/test/fixtures/naked/csv/accounts.csv +1 -0
  206. data/test/fixtures/naked/yml/accounts.yml +1 -0
  207. data/test/fixtures/naked/yml/companies.yml +1 -0
  208. data/test/fixtures/naked/yml/courses.yml +1 -0
  209. data/test/fixtures/order.rb +4 -0
  210. data/test/fixtures/parrot.rb +13 -0
  211. data/test/fixtures/parrots.yml +27 -0
  212. data/test/fixtures/parrots_pirates.yml +7 -0
  213. data/test/fixtures/people.yml +3 -0
  214. data/test/fixtures/person.rb +4 -0
  215. data/test/fixtures/pirate.rb +5 -0
  216. data/test/fixtures/pirates.yml +9 -0
  217. data/test/fixtures/post.rb +59 -0
  218. data/test/fixtures/posts.yml +48 -0
  219. data/test/fixtures/project.rb +27 -2
  220. data/test/fixtures/projects.yml +7 -0
  221. data/test/fixtures/reader.rb +4 -0
  222. data/test/fixtures/readers.yml +4 -0
  223. data/test/fixtures/reply.rb +18 -2
  224. data/test/fixtures/reserved_words/distinct.yml +5 -0
  225. data/test/fixtures/reserved_words/distincts_selects.yml +11 -0
  226. data/test/fixtures/reserved_words/group.yml +14 -0
  227. data/test/fixtures/reserved_words/select.yml +8 -0
  228. data/test/fixtures/reserved_words/values.yml +7 -0
  229. data/test/fixtures/ship.rb +3 -0
  230. data/test/fixtures/ships.yml +5 -0
  231. data/test/fixtures/subject.rb +4 -0
  232. data/test/fixtures/subscriber.rb +4 -3
  233. data/test/fixtures/tag.rb +7 -0
  234. data/test/fixtures/tagging.rb +10 -0
  235. data/test/fixtures/taggings.yml +25 -0
  236. data/test/fixtures/tags.yml +7 -0
  237. data/test/fixtures/task.rb +3 -0
  238. data/test/fixtures/tasks.yml +7 -0
  239. data/test/fixtures/topic.rb +20 -3
  240. data/test/fixtures/topics.yml +22 -0
  241. data/test/fixtures/treasure.rb +4 -0
  242. data/test/fixtures/treasures.yml +10 -0
  243. data/test/fixtures/vertex.rb +9 -0
  244. data/test/fixtures/vertices.yml +4 -0
  245. data/test/fixtures_test.rb +574 -8
  246. data/test/inheritance_test.rb +113 -27
  247. data/test/json_serialization_test.rb +180 -0
  248. data/test/lifecycle_test.rb +56 -29
  249. data/test/locking_test.rb +273 -0
  250. data/test/method_scoping_test.rb +416 -0
  251. data/test/migration_test.rb +933 -0
  252. data/test/migration_test_firebird.rb +124 -0
  253. data/test/mixin_test.rb +95 -0
  254. data/test/modules_test.rb +23 -10
  255. data/test/multiple_db_test.rb +17 -3
  256. data/test/pk_test.rb +59 -15
  257. data/test/query_cache_test.rb +104 -0
  258. data/test/readonly_test.rb +107 -0
  259. data/test/reflection_test.rb +124 -27
  260. data/test/reserved_word_test_mysql.rb +177 -0
  261. data/test/schema_authorization_test_postgresql.rb +75 -0
  262. data/test/schema_dumper_test.rb +131 -0
  263. data/test/schema_test_postgresql.rb +64 -0
  264. data/test/serialization_test.rb +47 -0
  265. data/test/synonym_test_oracle.rb +17 -0
  266. data/test/table_name_test_sqlserver.rb +23 -0
  267. data/test/threaded_connections_test.rb +48 -0
  268. data/test/transactions_test.rb +227 -29
  269. data/test/unconnected_test.rb +14 -6
  270. data/test/validations_test.rb +1293 -32
  271. data/test/xml_serialization_test.rb +202 -0
  272. metadata +347 -143
  273. data/dev-utils/eval_debugger.rb +0 -9
  274. data/examples/associations.rb +0 -87
  275. data/examples/shared_setup.rb +0 -15
  276. data/examples/validation.rb +0 -88
  277. data/lib/active_record/deprecated_associations.rb +0 -70
  278. data/lib/active_record/support/class_attribute_accessors.rb +0 -43
  279. data/lib/active_record/support/class_inheritable_attributes.rb +0 -37
  280. data/lib/active_record/support/clean_logger.rb +0 -10
  281. data/lib/active_record/support/inflector.rb +0 -70
  282. data/lib/active_record/vendor/simple.rb +0 -702
  283. data/lib/active_record/wrappers/yaml_wrapper.rb +0 -15
  284. data/lib/active_record/wrappings.rb +0 -59
  285. data/rakefile +0 -122
  286. data/test/deprecated_associations_test.rb +0 -336
  287. data/test/fixtures/accounts/signals37 +0 -3
  288. data/test/fixtures/accounts/unknown +0 -2
  289. data/test/fixtures/companies/first_client +0 -6
  290. data/test/fixtures/companies/first_firm +0 -4
  291. data/test/fixtures/companies/second_client +0 -6
  292. data/test/fixtures/courses/java +0 -2
  293. data/test/fixtures/courses/ruby +0 -2
  294. data/test/fixtures/customers/david +0 -6
  295. data/test/fixtures/db_definitions/mysql.sql +0 -96
  296. data/test/fixtures/db_definitions/mysql2.sql +0 -4
  297. data/test/fixtures/developers/david +0 -2
  298. data/test/fixtures/developers/jamis +0 -2
  299. data/test/fixtures/entrants/first +0 -3
  300. data/test/fixtures/entrants/second +0 -3
  301. data/test/fixtures/entrants/third +0 -3
  302. data/test/fixtures/fixture_database.sqlite +0 -0
  303. data/test/fixtures/fixture_database_2.sqlite +0 -0
  304. data/test/fixtures/movies/first +0 -2
  305. data/test/fixtures/movies/second +0 -2
  306. data/test/fixtures/projects/action_controller +0 -2
  307. data/test/fixtures/projects/active_record +0 -2
  308. data/test/fixtures/topics/first +0 -9
  309. data/test/fixtures/topics/second +0 -8
  310. data/test/inflector_test.rb +0 -104
  311. data/test/thread_safety_test.rb +0 -33
@@ -1,20 +1,30 @@
1
1
  require 'abstract_unit'
2
2
  require 'fixtures/company'
3
-
3
+ require 'fixtures/project'
4
+ require 'fixtures/subscriber'
4
5
 
5
6
  class InheritanceTest < Test::Unit::TestCase
6
- def setup
7
- @company_fixtures = create_fixtures "companies"
7
+ fixtures :companies, :projects, :subscribers, :accounts
8
+
9
+ def test_company_descends_from_active_record
10
+ assert_raise(NoMethodError) { ActiveRecord::Base.descends_from_active_record? }
11
+ assert AbstractCompany.descends_from_active_record?, 'AbstractCompany should descend from ActiveRecord::Base'
12
+ assert Company.descends_from_active_record?, 'Company should descend from ActiveRecord::Base'
13
+ assert !Class.new(Company).descends_from_active_record?, 'Company subclass should not descend from ActiveRecord::Base'
8
14
  end
9
15
 
10
- def switch_to_alt_inheritance_column
11
- # we don't want misleading test results, so get rid of the values in the type column
12
- Company.find_all(nil, "id").each do |c|
13
- c['type'] = nil
14
- c.save
16
+ def test_a_bad_type_column
17
+ #SQLServer need to turn Identity Insert On before manually inserting into the Identity column
18
+ if current_adapter?(:SQLServerAdapter, :SybaseAdapter)
19
+ Company.connection.execute "SET IDENTITY_INSERT companies ON"
15
20
  end
16
-
17
- def Company.inheritance_column() "ruby_type" end
21
+ Company.connection.insert "INSERT INTO companies (id, #{QUOTED_TYPE}, name) VALUES(100, 'bad_class!', 'Not happening')"
22
+
23
+ #We then need to turn it back Off before continuing.
24
+ if current_adapter?(:SQLServerAdapter, :SybaseAdapter)
25
+ Company.connection.execute "SET IDENTITY_INSERT companies OFF"
26
+ end
27
+ assert_raises(ActiveRecord::SubclassNotFound) { Company.find(100) }
18
28
  end
19
29
 
20
30
  def test_inheritance_find
@@ -27,10 +37,11 @@ class InheritanceTest < Test::Unit::TestCase
27
37
  def test_alt_inheritance_find
28
38
  switch_to_alt_inheritance_column
29
39
  test_inheritance_find
40
+ switch_to_default_inheritance_column
30
41
  end
31
42
 
32
43
  def test_inheritance_find_all
33
- companies = Company.find_all(nil, "id")
44
+ companies = Company.find(:all, :order => 'id')
34
45
  assert companies[0].kind_of?(Firm), "37signals should be a firm"
35
46
  assert companies[1].kind_of?(Client), "Summit should be a client"
36
47
  end
@@ -38,6 +49,7 @@ class InheritanceTest < Test::Unit::TestCase
38
49
  def test_alt_inheritance_find_all
39
50
  switch_to_alt_inheritance_column
40
51
  test_inheritance_find_all
52
+ switch_to_default_inheritance_column
41
53
  end
42
54
 
43
55
  def test_inheritance_save
@@ -52,17 +64,19 @@ class InheritanceTest < Test::Unit::TestCase
52
64
  def test_alt_inheritance_save
53
65
  switch_to_alt_inheritance_column
54
66
  test_inheritance_save
67
+ switch_to_default_inheritance_column
55
68
  end
56
69
 
57
70
  def test_inheritance_condition
58
- assert_equal 3, Company.find_all.length
59
- assert_equal 1, Firm.find_all.length
60
- assert_equal 2, Client.find_all.length
71
+ assert_equal 9, Company.count
72
+ assert_equal 2, Firm.count
73
+ assert_equal 3, Client.count
61
74
  end
62
75
 
63
76
  def test_alt_inheritance_condition
64
77
  switch_to_alt_inheritance_column
65
78
  test_inheritance_condition
79
+ switch_to_default_inheritance_column
66
80
  end
67
81
 
68
82
  def test_finding_incorrect_type_data
@@ -73,53 +87,125 @@ class InheritanceTest < Test::Unit::TestCase
73
87
  def test_alt_finding_incorrect_type_data
74
88
  switch_to_alt_inheritance_column
75
89
  test_finding_incorrect_type_data
90
+ switch_to_default_inheritance_column
76
91
  end
77
92
 
78
93
  def test_update_all_within_inheritance
79
94
  Client.update_all "name = 'I am a client'"
80
- assert_equal "I am a client", Client.find_all.first.name
81
- assert_equal "37signals", Firm.find_all.first.name
95
+ assert_equal "I am a client", Client.find(:all).first.name
96
+ assert_equal "37signals", Firm.find(:all).first.name
82
97
  end
83
98
 
84
99
  def test_alt_update_all_within_inheritance
85
100
  switch_to_alt_inheritance_column
86
101
  test_update_all_within_inheritance
102
+ switch_to_default_inheritance_column
87
103
  end
88
104
 
89
105
  def test_destroy_all_within_inheritance
90
106
  Client.destroy_all
91
- assert_equal 0, Client.find_all.length
92
- assert_equal 1, Firm.find_all.length
107
+ assert_equal 0, Client.count
108
+ assert_equal 2, Firm.count
93
109
  end
94
110
 
95
111
  def test_alt_destroy_all_within_inheritance
96
112
  switch_to_alt_inheritance_column
97
113
  test_destroy_all_within_inheritance
114
+ switch_to_default_inheritance_column
98
115
  end
99
116
 
100
117
  def test_find_first_within_inheritance
101
- assert_kind_of Firm, Company.find_first("name = '37signals'")
102
- assert_kind_of Firm, Firm.find_first("name = '37signals'")
103
- assert_nil Client.find_first("name = '37signals'")
118
+ assert_kind_of Firm, Company.find(:first, :conditions => "name = '37signals'")
119
+ assert_kind_of Firm, Firm.find(:first, :conditions => "name = '37signals'")
120
+ assert_nil Client.find(:first, :conditions => "name = '37signals'")
104
121
  end
105
122
 
106
123
  def test_alt_find_first_within_inheritance
107
124
  switch_to_alt_inheritance_column
108
125
  test_find_first_within_inheritance
126
+ switch_to_default_inheritance_column
109
127
  end
110
128
 
111
129
  def test_complex_inheritance
112
130
  very_special_client = VerySpecialClient.create("name" => "veryspecial")
113
- assert_equal very_special_client, VerySpecialClient.find_first("name = 'veryspecial'")
114
- assert_equal very_special_client, SpecialClient.find_first("name = 'veryspecial'")
115
- assert_equal very_special_client, Company.find_first("name = 'veryspecial'")
116
- assert_equal very_special_client, Client.find_first("name = 'veryspecial'")
117
- assert_equal 1, Client.find_all("name = 'Summit'").size
131
+ assert_equal very_special_client, VerySpecialClient.find(:first, :conditions => "name = 'veryspecial'")
132
+ assert_equal very_special_client, SpecialClient.find(:first, :conditions => "name = 'veryspecial'")
133
+ assert_equal very_special_client, Company.find(:first, :conditions => "name = 'veryspecial'")
134
+ assert_equal very_special_client, Client.find(:first, :conditions => "name = 'veryspecial'")
135
+ assert_equal 1, Client.find(:all, :conditions => "name = 'Summit'").size
118
136
  assert_equal very_special_client, Client.find(very_special_client.id)
119
137
  end
120
138
 
121
139
  def test_alt_complex_inheritance
122
140
  switch_to_alt_inheritance_column
123
141
  test_complex_inheritance
142
+ switch_to_default_inheritance_column
143
+ end
144
+
145
+ def test_eager_load_belongs_to_something_inherited
146
+ account = Account.find(1, :include => :firm)
147
+ assert_not_nil account.instance_variable_get("@firm"), "nil proves eager load failed"
148
+ end
149
+
150
+ def test_alt_eager_loading
151
+ switch_to_alt_inheritance_column
152
+ test_eager_load_belongs_to_something_inherited
153
+ switch_to_default_inheritance_column
154
+ end
155
+
156
+ def test_inheritance_without_mapping
157
+ assert_kind_of SpecialSubscriber, SpecialSubscriber.find("webster132")
158
+ assert_nothing_raised { s = SpecialSubscriber.new("name" => "And breaaaaathe!"); s.id = 'roger'; s.save }
159
+ end
160
+
161
+ private
162
+ def switch_to_alt_inheritance_column
163
+ # we don't want misleading test results, so get rid of the values in the type column
164
+ Company.find(:all, :order => 'id').each do |c|
165
+ c['type'] = nil
166
+ c.save
167
+ end
168
+ [ Company, Firm, Client].each { |klass| klass.reset_column_information }
169
+ Company.set_inheritance_column('ruby_type')
170
+ end
171
+ def switch_to_default_inheritance_column
172
+ [ Company, Firm, Client].each { |klass| klass.reset_column_information }
173
+ Company.set_inheritance_column('type')
174
+ end
175
+ end
176
+
177
+
178
+ class InheritanceComputeTypeTest < Test::Unit::TestCase
179
+ fixtures :companies
180
+
181
+ def setup
182
+ Dependencies.log_activity = true
183
+ end
184
+
185
+ def teardown
186
+ Dependencies.log_activity = false
187
+ self.class.const_remove :FirmOnTheFly rescue nil
188
+ Firm.const_remove :FirmOnTheFly rescue nil
189
+ end
190
+
191
+ def test_instantiation_doesnt_try_to_require_corresponding_file
192
+ foo = Firm.find(:first).clone
193
+ foo.ruby_type = foo.type = 'FirmOnTheFly'
194
+ foo.save!
195
+
196
+ # Should fail without FirmOnTheFly in the type condition.
197
+ assert_raise(ActiveRecord::RecordNotFound) { Firm.find(foo.id) }
198
+
199
+ # Nest FirmOnTheFly in the test case where Dependencies won't see it.
200
+ self.class.const_set :FirmOnTheFly, Class.new(Firm)
201
+ assert_raise(ActiveRecord::SubclassNotFound) { Firm.find(foo.id) }
202
+
203
+ # Nest FirmOnTheFly in Firm where Dependencies will see it.
204
+ # This is analogous to nesting models in a migration.
205
+ Firm.const_set :FirmOnTheFly, Class.new(Firm)
206
+
207
+ # And instantiate will find the existing constant rather than trying
208
+ # to require firm_on_the_fly.
209
+ assert_nothing_raised { assert_kind_of Firm::FirmOnTheFly, Firm.find(foo.id) }
124
210
  end
125
- end
211
+ end
@@ -0,0 +1,180 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/contact'
3
+ require 'fixtures/post'
4
+ require 'fixtures/author'
5
+ require 'fixtures/tagging'
6
+ require 'fixtures/tag'
7
+ require 'fixtures/comment'
8
+
9
+ class JsonSerializationTest < Test::Unit::TestCase
10
+ def setup
11
+ @contact = Contact.new(
12
+ :name => 'Konata Izumi',
13
+ :age => 16,
14
+ :avatar => 'binarydata',
15
+ :created_at => Time.utc(2006, 8, 1),
16
+ :awesome => true,
17
+ :preferences => { :shows => 'anime' }
18
+ )
19
+ end
20
+
21
+ def test_should_encode_all_encodable_attributes
22
+ json = @contact.to_json
23
+
24
+ assert_match %r{"name": "Konata Izumi"}, json
25
+ assert_match %r{"age": 16}, json
26
+ assert json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
27
+ assert_match %r{"awesome": true}, json
28
+ assert_match %r{"preferences": \{"shows": "anime"\}}, json
29
+ end
30
+
31
+ def test_should_allow_attribute_filtering_with_only
32
+ json = @contact.to_json(:only => [:name, :age])
33
+
34
+ assert_match %r{"name": "Konata Izumi"}, json
35
+ assert_match %r{"age": 16}, json
36
+ assert_no_match %r{"awesome": true}, json
37
+ assert !json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
38
+ assert_no_match %r{"preferences": \{"shows": "anime"\}}, json
39
+ end
40
+
41
+ def test_should_allow_attribute_filtering_with_except
42
+ json = @contact.to_json(:except => [:name, :age])
43
+
44
+ assert_no_match %r{"name": "Konata Izumi"}, json
45
+ assert_no_match %r{"age": 16}, json
46
+ assert_match %r{"awesome": true}, json
47
+ assert json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
48
+ assert_match %r{"preferences": \{"shows": "anime"\}}, json
49
+ end
50
+
51
+ def test_methods_are_called_on_object
52
+ # Define methods on fixture.
53
+ def @contact.label; "Has cheezburger"; end
54
+ def @contact.favorite_quote; "Constraints are liberating"; end
55
+
56
+ # Single method.
57
+ assert_match %r{"label": "Has cheezburger"}, @contact.to_json(:only => :name, :methods => :label)
58
+
59
+ # Both methods.
60
+ methods_json = @contact.to_json(:only => :name, :methods => [:label, :favorite_quote])
61
+ assert_match %r{"label": "Has cheezburger"}, methods_json
62
+ assert_match %r{"favorite_quote": "Constraints are liberating"}, methods_json
63
+ end
64
+ end
65
+
66
+ class DatabaseConnectedJsonEncodingTest < Test::Unit::TestCase
67
+ fixtures :authors, :posts, :comments, :tags, :taggings
68
+
69
+ def setup
70
+ @david = authors(:david)
71
+ @mary = authors(:mary)
72
+ end
73
+
74
+ def test_includes_uses_association_name
75
+ json = @david.to_json(:include => :posts)
76
+
77
+ assert_match %r{"posts": \[}, json
78
+
79
+ assert_match %r{"id": 1}, json
80
+ assert_match %r{"name": "David"}, json
81
+
82
+ assert_match %r{"author_id": 1}, json
83
+ assert_match %r{"title": "Welcome to the weblog"}, json
84
+ assert_match %r{"body": "Such a lovely day"}, json
85
+
86
+ assert_match %r{"title": "So I was thinking"}, json
87
+ assert_match %r{"body": "Like I hopefully always am"}, json
88
+ end
89
+
90
+ def test_includes_uses_association_name_and_applies_attribute_filters
91
+ json = @david.to_json(:include => { :posts => { :only => :title } })
92
+
93
+ assert_match %r{"name": "David"}, json
94
+ assert_match %r{"posts": \[}, json
95
+
96
+ assert_match %r{"title": "Welcome to the weblog"}, json
97
+ assert_no_match %r{"body": "Such a lovely day"}, json
98
+
99
+ assert_match %r{"title": "So I was thinking"}, json
100
+ assert_no_match %r{"body": "Like I hopefully always am"}, json
101
+ end
102
+
103
+ def test_includes_fetches_second_level_associations
104
+ json = @david.to_json(:include => { :posts => { :include => { :comments => { :only => :body } } } })
105
+
106
+ assert_match %r{"name": "David"}, json
107
+ assert_match %r{"posts": \[}, json
108
+
109
+ assert_match %r{"comments": \[}, json
110
+ assert_match %r{\{"body": "Thank you again for the welcome"\}}, json
111
+ assert_match %r{\{"body": "Don't think too hard"\}}, json
112
+ assert_no_match %r{"post_id": }, json
113
+ end
114
+
115
+ def test_includes_fetches_nth_level_associations
116
+ json = @david.to_json(
117
+ :include => {
118
+ :posts => {
119
+ :include => {
120
+ :taggings => {
121
+ :include => {
122
+ :tag => { :only => :name }
123
+ }
124
+ }
125
+ }
126
+ }
127
+ })
128
+
129
+ assert_match %r{"name": "David"}, json
130
+ assert_match %r{"posts": \[}, json
131
+
132
+ assert_match %r{"taggings": \[}, json
133
+ assert_match %r{"tag": \{"name": "General"\}}, json
134
+ end
135
+
136
+ def test_should_not_call_methods_on_associations_that_dont_respond
137
+ def @david.favorite_quote; "Constraints are liberating"; end
138
+ json = @david.to_json(:include => :posts, :methods => :favorite_quote)
139
+
140
+ assert !@david.posts.first.respond_to?(:favorite_quote)
141
+ assert_match %r{"favorite_quote": "Constraints are liberating"}, json
142
+ assert_equal %r{"favorite_quote": }.match(json).size, 1
143
+ end
144
+
145
+ def test_should_allow_only_option_for_list_of_authors
146
+ authors = [@david, @mary]
147
+
148
+ assert_equal %([{"name": "David"}, {"name": "Mary"}]), authors.to_json(:only => :name)
149
+ end
150
+
151
+ def test_should_allow_except_option_for_list_of_authors
152
+ authors = [@david, @mary]
153
+
154
+ assert_equal %([{"id": 1}, {"id": 2}]), authors.to_json(:except => [:name, :author_address_id])
155
+ end
156
+
157
+ def test_should_allow_includes_for_list_of_authors
158
+ authors = [@david, @mary]
159
+ json = authors.to_json(
160
+ :only => :name,
161
+ :include => {
162
+ :posts => { :only => :id }
163
+ }
164
+ )
165
+
166
+ ['"name": "David"', '"posts": [', '{"id": 1}', '{"id": 2}', '{"id": 4}',
167
+ '{"id": 5}', '{"id": 6}', '"name": "Mary"', '"posts": [{"id": 7}]'].each do |fragment|
168
+ assert json.include?(fragment), json
169
+ end
170
+ end
171
+
172
+ def test_should_allow_options_for_hash_of_authors
173
+ authors_hash = {
174
+ 1 => @david,
175
+ 2 => @mary
176
+ }
177
+
178
+ assert_equal %({1: {"name": "David"}}), authors_hash.to_json(:only => [1, :name])
179
+ end
180
+ end
@@ -1,10 +1,11 @@
1
- # require File.dirname(__FILE__) + '/../dev-utils/eval_debugger'
2
1
  require 'abstract_unit'
3
2
  require 'fixtures/topic'
4
3
  require 'fixtures/developer'
4
+ require 'fixtures/reply'
5
5
 
6
6
  class Topic; def after_find() end end
7
7
  class Developer; def after_find() end end
8
+ class SpecialDeveloper < Developer; end
8
9
 
9
10
  class TopicManualObserver
10
11
  include Singleton
@@ -26,7 +27,7 @@ class TopicManualObserver
26
27
  end
27
28
 
28
29
  class TopicaObserver < ActiveRecord::Observer
29
- def self.observed_class() Topic end
30
+ observe :topic
30
31
 
31
32
  attr_reader :topic
32
33
 
@@ -45,66 +46,92 @@ end
45
46
 
46
47
  class MultiObserver < ActiveRecord::Observer
47
48
  attr_reader :record
48
-
49
+
49
50
  def self.observed_class() [ Topic, Developer ] end
50
51
 
52
+ cattr_reader :last_inherited
53
+ @@last_inherited = nil
54
+
55
+ def observed_class_inherited_with_testing(subclass)
56
+ observed_class_inherited_without_testing(subclass)
57
+ @@last_inherited = subclass
58
+ end
59
+
60
+ alias_method_chain :observed_class_inherited, :testing
61
+
51
62
  def after_find(record)
52
63
  @record = record
53
64
  end
54
-
55
65
  end
56
66
 
57
67
  class LifecycleTest < Test::Unit::TestCase
58
- def setup
59
- @topics, @developers = create_fixtures("topics", "developers")
60
- end
68
+ fixtures :topics, :developers
61
69
 
62
70
  def test_before_destroy
63
71
  assert_equal 2, Topic.count
64
72
  Topic.find(1).destroy
65
73
  assert_equal 0, Topic.count
66
74
  end
67
-
75
+
68
76
  def test_after_save
69
- topic_observer = TopicManualObserver.instance
77
+ ActiveRecord::Base.observers = :topic_manual_observer
78
+ ActiveRecord::Base.instantiate_observers
70
79
 
71
80
  topic = Topic.find(1)
72
81
  topic.title = "hello"
73
82
  topic.save
74
-
75
- assert topic_observer.has_been_notified?
76
- assert_equal :after_save, topic_observer.callbacks.last["callback_method"]
83
+
84
+ assert TopicManualObserver.instance.has_been_notified?
85
+ assert_equal :after_save, TopicManualObserver.instance.callbacks.last["callback_method"]
77
86
  end
78
-
87
+
79
88
  def test_observer_update_on_save
80
- topic_observer = TopicManualObserver.instance
89
+ ActiveRecord::Base.observers = TopicManualObserver
90
+ ActiveRecord::Base.instantiate_observers
81
91
 
82
- topic = Topic.find(1)
83
- assert topic_observer.has_been_notified?
84
- assert_equal :after_find, topic_observer.callbacks.first["callback_method"]
92
+ topic = Topic.find(1)
93
+ assert TopicManualObserver.instance.has_been_notified?
94
+ assert_equal :after_find, TopicManualObserver.instance.callbacks.first["callback_method"]
85
95
  end
86
-
96
+
87
97
  def test_auto_observer
88
98
  topic_observer = TopicaObserver.instance
89
99
 
90
- topic = Topic.find(1)
91
- assert_equal topic_observer.topic.title, topic.title
100
+ topic = Topic.find(1)
101
+ assert_equal topic.title, topic_observer.topic.title
92
102
  end
93
-
94
- def test_infered_auto_observer
103
+
104
+ def test_inferred_auto_observer
95
105
  topic_observer = TopicObserver.instance
96
106
 
97
- topic = Topic.find(1)
98
- assert_equal topic_observer.topic.title, topic.title
107
+ topic = Topic.find(1)
108
+ assert_equal topic.title, topic_observer.topic.title
99
109
  end
100
-
110
+
101
111
  def test_observing_two_classes
102
112
  multi_observer = MultiObserver.instance
103
113
 
104
114
  topic = Topic.find(1)
105
- assert_equal multi_observer.record.title, topic.title
115
+ assert_equal topic.title, multi_observer.record.title
106
116
 
107
- developer = Developer.find(1)
108
- assert_equal multi_observer.record.name, developer.name
117
+ developer = Developer.find(1)
118
+ assert_equal developer.name, multi_observer.record.name
109
119
  end
110
- end
120
+
121
+ def test_observing_subclasses
122
+ multi_observer = MultiObserver.instance
123
+
124
+ developer = SpecialDeveloper.find(1)
125
+ assert_equal developer.name, multi_observer.record.name
126
+
127
+ klass = Class.new(Developer)
128
+ assert_equal klass, multi_observer.last_inherited
129
+
130
+ developer = klass.find(1)
131
+ assert_equal developer.name, multi_observer.record.name
132
+ end
133
+
134
+ def test_invalid_observer
135
+ assert_raise(ArgumentError) { Topic.observers = Object.new; Topic.instantiate_observers }
136
+ end
137
+ end