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
@@ -0,0 +1,32 @@
1
+ require 'abstract_unit'
2
+
3
+ # Without using prepared statements, it makes no sense to test
4
+ # BLOB data with SQL Server, because the length of a statement is
5
+ # limited to 8KB.
6
+ #
7
+ # Without using prepared statements, it makes no sense to test
8
+ # BLOB data with DB2 or Firebird, because the length of a statement
9
+ # is limited to 32KB.
10
+ unless current_adapter?(:SQLServerAdapter, :SybaseAdapter, :DB2Adapter, :FirebirdAdapter)
11
+ require 'fixtures/binary'
12
+
13
+ class BinaryTest < Test::Unit::TestCase
14
+ FIXTURES = %w(flowers.jpg example.log)
15
+
16
+ def test_load_save
17
+ Binary.delete_all
18
+
19
+ FIXTURES.each do |filename|
20
+ data = File.read("#{File.dirname(__FILE__)}/fixtures/#{filename}").freeze
21
+
22
+ bin = Binary.new(:data => data)
23
+ assert_equal data, bin.data, 'Newly assigned data differs from original'
24
+
25
+ bin.save!
26
+ assert_equal data, bin.data, 'Data differs from original after save'
27
+
28
+ assert_equal data, bin.reload.data, 'Reloaded data differs from original'
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,251 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/company'
3
+ require 'fixtures/topic'
4
+
5
+ Company.has_many :accounts
6
+
7
+ class NumericData < ActiveRecord::Base
8
+ self.table_name = 'numeric_data'
9
+ end
10
+
11
+ class CalculationsTest < Test::Unit::TestCase
12
+ fixtures :companies, :accounts, :topics
13
+
14
+ def test_should_sum_field
15
+ assert_equal 318, Account.sum(:credit_limit)
16
+ end
17
+
18
+ def test_should_average_field
19
+ value = Account.average(:credit_limit)
20
+ assert_kind_of Float, value
21
+ assert_in_delta 53.0, value, 0.001
22
+ end
23
+
24
+ def test_should_return_nil_as_average
25
+ assert_nil NumericData.average(:bank_balance)
26
+ end
27
+
28
+ def test_should_get_maximum_of_field
29
+ assert_equal 60, Account.maximum(:credit_limit)
30
+ end
31
+
32
+ def test_should_get_maximum_of_field_with_include
33
+ assert_equal 50, Account.maximum(:credit_limit, :include => :firm, :conditions => "companies.name != 'Summit'")
34
+ end
35
+
36
+ def test_should_get_maximum_of_field_with_scoped_include
37
+ Account.with_scope :find => { :include => :firm, :conditions => "companies.name != 'Summit'" } do
38
+ assert_equal 50, Account.maximum(:credit_limit)
39
+ end
40
+ end
41
+
42
+ def test_should_get_minimum_of_field
43
+ assert_equal 50, Account.minimum(:credit_limit)
44
+ end
45
+
46
+ def test_should_group_by_field
47
+ c = Account.sum(:credit_limit, :group => :firm_id)
48
+ [1,6,2].each { |firm_id| assert c.keys.include?(firm_id) }
49
+ end
50
+
51
+ def test_should_group_by_summed_field
52
+ c = Account.sum(:credit_limit, :group => :firm_id)
53
+ assert_equal 50, c[1]
54
+ assert_equal 105, c[6]
55
+ assert_equal 60, c[2]
56
+ end
57
+
58
+ def test_should_order_by_grouped_field
59
+ c = Account.sum(:credit_limit, :group => :firm_id, :order => "firm_id")
60
+ assert_equal [1, 2, 6, 9], c.keys.compact
61
+ end
62
+
63
+ def test_should_order_by_calculation
64
+ c = Account.sum(:credit_limit, :group => :firm_id, :order => "sum_credit_limit desc, firm_id")
65
+ assert_equal [105, 60, 53, 50, 50], c.keys.collect { |k| c[k] }
66
+ assert_equal [6, 2, 9, 1], c.keys.compact
67
+ end
68
+
69
+ def test_should_limit_calculation
70
+ c = Account.sum(:credit_limit, :conditions => "firm_id IS NOT NULL",
71
+ :group => :firm_id, :order => "firm_id", :limit => 2)
72
+ assert_equal [1, 2], c.keys.compact
73
+ end
74
+
75
+ def test_should_limit_calculation_with_offset
76
+ c = Account.sum(:credit_limit, :conditions => "firm_id IS NOT NULL",
77
+ :group => :firm_id, :order => "firm_id", :limit => 2, :offset => 1)
78
+ assert_equal [2, 6], c.keys.compact
79
+ end
80
+
81
+ def test_should_group_by_summed_field_having_condition
82
+ c = Account.sum(:credit_limit, :group => :firm_id,
83
+ :having => 'sum(credit_limit) > 50')
84
+ assert_nil c[1]
85
+ assert_equal 105, c[6]
86
+ assert_equal 60, c[2]
87
+ end
88
+
89
+ def test_should_group_by_summed_association
90
+ c = Account.sum(:credit_limit, :group => :firm)
91
+ assert_equal 50, c[companies(:first_firm)]
92
+ assert_equal 105, c[companies(:rails_core)]
93
+ assert_equal 60, c[companies(:first_client)]
94
+ end
95
+
96
+ def test_should_sum_field_with_conditions
97
+ assert_equal 105, Account.sum(:credit_limit, :conditions => 'firm_id = 6')
98
+ end
99
+
100
+ def test_should_group_by_summed_field_with_conditions
101
+ c = Account.sum(:credit_limit, :conditions => 'firm_id > 1',
102
+ :group => :firm_id)
103
+ assert_nil c[1]
104
+ assert_equal 105, c[6]
105
+ assert_equal 60, c[2]
106
+ end
107
+
108
+ def test_should_group_by_summed_field_with_conditions_and_having
109
+ c = Account.sum(:credit_limit, :conditions => 'firm_id > 1',
110
+ :group => :firm_id,
111
+ :having => 'sum(credit_limit) > 60')
112
+ assert_nil c[1]
113
+ assert_equal 105, c[6]
114
+ assert_nil c[2]
115
+ end
116
+
117
+ def test_should_group_by_fields_with_table_alias
118
+ c = Account.sum(:credit_limit, :group => 'accounts.firm_id')
119
+ assert_equal 50, c[1]
120
+ assert_equal 105, c[6]
121
+ assert_equal 60, c[2]
122
+ end
123
+
124
+ def test_should_calculate_with_invalid_field
125
+ assert_equal 6, Account.calculate(:count, '*')
126
+ assert_equal 6, Account.calculate(:count, :all)
127
+ end
128
+
129
+ def test_should_calculate_grouped_with_invalid_field
130
+ c = Account.count(:all, :group => 'accounts.firm_id')
131
+ assert_equal 1, c[1]
132
+ assert_equal 2, c[6]
133
+ assert_equal 1, c[2]
134
+ end
135
+
136
+ def test_should_calculate_grouped_association_with_invalid_field
137
+ c = Account.count(:all, :group => :firm)
138
+ assert_equal 1, c[companies(:first_firm)]
139
+ assert_equal 2, c[companies(:rails_core)]
140
+ assert_equal 1, c[companies(:first_client)]
141
+ end
142
+
143
+ uses_mocha 'group_by_non_numeric_foreign_key_association' do
144
+ def test_should_group_by_association_with_non_numeric_foreign_key
145
+ ActiveRecord::Base.connection.expects(:select_all).returns([{"count_all" => 1, "firm_id" => "ABC"}])
146
+
147
+ firm = mock()
148
+ firm.expects(:id).returns("ABC")
149
+ firm.expects(:class).returns(Firm)
150
+ Company.expects(:find).with(["ABC"]).returns([firm])
151
+
152
+ column = mock()
153
+ column.expects(:name).at_least_once.returns(:firm_id)
154
+ column.expects(:type_cast).with("ABC").returns("ABC")
155
+ Account.expects(:columns).at_least_once.returns([column])
156
+
157
+ c = Account.count(:all, :group => :firm)
158
+ assert_equal Firm, c.first.first.class
159
+ assert_equal 1, c.first.last
160
+ end
161
+ end
162
+
163
+ def test_should_not_modify_options_when_using_includes
164
+ options = {:conditions => 'companies.id > 1', :include => :firm}
165
+ options_copy = options.dup
166
+
167
+ Account.count(:all, options)
168
+ assert_equal options_copy, options
169
+ end
170
+
171
+ def test_should_calculate_grouped_by_function
172
+ c = Company.count(:all, :group => "UPPER(#{QUOTED_TYPE})")
173
+ assert_equal 2, c[nil]
174
+ assert_equal 1, c['DEPENDENTFIRM']
175
+ assert_equal 3, c['CLIENT']
176
+ assert_equal 2, c['FIRM']
177
+ end
178
+
179
+ def test_should_calculate_grouped_by_function_with_table_alias
180
+ c = Company.count(:all, :group => "UPPER(companies.#{QUOTED_TYPE})")
181
+ assert_equal 2, c[nil]
182
+ assert_equal 1, c['DEPENDENTFIRM']
183
+ assert_equal 3, c['CLIENT']
184
+ assert_equal 2, c['FIRM']
185
+ end
186
+
187
+ def test_should_not_overshadow_enumerable_sum
188
+ assert_equal 6, [1, 2, 3].sum(&:abs)
189
+ end
190
+
191
+ def test_should_sum_scoped_field
192
+ assert_equal 15, companies(:rails_core).companies.sum(:id)
193
+ end
194
+
195
+ def test_should_sum_scoped_field_with_conditions
196
+ assert_equal 8, companies(:rails_core).companies.sum(:id, :conditions => 'id > 7')
197
+ end
198
+
199
+ def test_should_group_by_scoped_field
200
+ c = companies(:rails_core).companies.sum(:id, :group => :name)
201
+ assert_equal 7, c['Leetsoft']
202
+ assert_equal 8, c['Jadedpixel']
203
+ end
204
+
205
+ def test_should_group_by_summed_field_with_conditions_and_having
206
+ c = companies(:rails_core).companies.sum(:id, :group => :name,
207
+ :having => 'sum(id) > 7')
208
+ assert_nil c['Leetsoft']
209
+ assert_equal 8, c['Jadedpixel']
210
+ end
211
+
212
+ def test_should_reject_invalid_options
213
+ assert_nothing_raised do
214
+ [:count, :sum].each do |func|
215
+ # empty options are valid
216
+ Company.send(:validate_calculation_options, func)
217
+ # these options are valid for all calculations
218
+ [:select, :conditions, :joins, :order, :group, :having, :distinct].each do |opt|
219
+ Company.send(:validate_calculation_options, func, opt => true)
220
+ end
221
+ end
222
+
223
+ # :include is only valid on :count
224
+ Company.send(:validate_calculation_options, :count, :include => true)
225
+ end
226
+
227
+ assert_raises(ArgumentError) { Company.send(:validate_calculation_options, :sum, :foo => :bar) }
228
+ assert_raises(ArgumentError) { Company.send(:validate_calculation_options, :count, :foo => :bar) }
229
+ end
230
+
231
+ def test_should_count_selected_field_with_include
232
+ assert_equal 6, Account.count(:distinct => true, :include => :firm)
233
+ assert_equal 4, Account.count(:distinct => true, :include => :firm, :select => :credit_limit)
234
+ end
235
+
236
+ def test_count_with_column_parameter
237
+ assert_equal 5, Account.count(:firm_id)
238
+ end
239
+
240
+ def test_count_with_column_and_options_parameter
241
+ assert_equal 2, Account.count(:firm_id, :conditions => "credit_limit = 50")
242
+ end
243
+
244
+ def test_count_with_no_parameters_isnt_deprecated
245
+ assert_not_deprecated { Account.count }
246
+ end
247
+
248
+ def test_count_with_too_many_parameters_raises
249
+ assert_raise(ArgumentError) { Account.count(1, 2, 3) }
250
+ end
251
+ end
@@ -0,0 +1,400 @@
1
+ require 'abstract_unit'
2
+
3
+ class CallbackDeveloper < ActiveRecord::Base
4
+ set_table_name 'developers'
5
+
6
+ class << self
7
+ def callback_string(callback_method)
8
+ "history << [#{callback_method.to_sym.inspect}, :string]"
9
+ end
10
+
11
+ def callback_proc(callback_method)
12
+ Proc.new { |model| model.history << [callback_method, :proc] }
13
+ end
14
+
15
+ def define_callback_method(callback_method)
16
+ define_method("#{callback_method}_method") do |model|
17
+ model.history << [callback_method, :method]
18
+ end
19
+ end
20
+
21
+ def callback_object(callback_method)
22
+ klass = Class.new
23
+ klass.send(:define_method, callback_method) do |model|
24
+ model.history << [callback_method, :object]
25
+ end
26
+ klass.new
27
+ end
28
+ end
29
+
30
+ ActiveRecord::Callbacks::CALLBACKS.each do |callback_method|
31
+ callback_method_sym = callback_method.to_sym
32
+ define_callback_method(callback_method_sym)
33
+ send(callback_method, callback_method_sym)
34
+ send(callback_method, callback_string(callback_method_sym))
35
+ send(callback_method, callback_proc(callback_method_sym))
36
+ send(callback_method, callback_object(callback_method_sym))
37
+ send(callback_method) { |model| model.history << [callback_method_sym, :block] }
38
+ end
39
+
40
+ def history
41
+ @history ||= []
42
+ end
43
+
44
+ # after_initialize and after_find are invoked only if instance methods have been defined.
45
+ def after_initialize
46
+ end
47
+
48
+ def after_find
49
+ end
50
+ end
51
+
52
+ class ParentDeveloper < ActiveRecord::Base
53
+ set_table_name 'developers'
54
+ attr_accessor :after_save_called
55
+ before_validation {|record| record.after_save_called = true}
56
+ end
57
+
58
+ class ChildDeveloper < ParentDeveloper
59
+
60
+ end
61
+
62
+ class RecursiveCallbackDeveloper < ActiveRecord::Base
63
+ set_table_name 'developers'
64
+
65
+ before_save :on_before_save
66
+ after_save :on_after_save
67
+
68
+ attr_reader :on_before_save_called, :on_after_save_called
69
+
70
+ def on_before_save
71
+ @on_before_save_called ||= 0
72
+ @on_before_save_called += 1
73
+ save unless @on_before_save_called > 1
74
+ end
75
+
76
+ def on_after_save
77
+ @on_after_save_called ||= 0
78
+ @on_after_save_called += 1
79
+ save unless @on_after_save_called > 1
80
+ end
81
+ end
82
+
83
+ class ImmutableDeveloper < ActiveRecord::Base
84
+ set_table_name 'developers'
85
+
86
+ validates_inclusion_of :salary, :in => 50000..200000
87
+
88
+ before_save :cancel
89
+ before_destroy :cancel
90
+
91
+ def cancelled?
92
+ @cancelled == true
93
+ end
94
+
95
+ private
96
+ def cancel
97
+ @cancelled = true
98
+ false
99
+ end
100
+ end
101
+
102
+ class ImmutableMethodDeveloper < ActiveRecord::Base
103
+ set_table_name 'developers'
104
+
105
+ validates_inclusion_of :salary, :in => 50000..200000
106
+
107
+ def cancelled?
108
+ @cancelled == true
109
+ end
110
+
111
+ def before_save
112
+ @cancelled = true
113
+ false
114
+ end
115
+
116
+ def before_destroy
117
+ @cancelled = true
118
+ false
119
+ end
120
+ end
121
+
122
+ class CallbackCancellationDeveloper < ActiveRecord::Base
123
+ set_table_name 'developers'
124
+ def before_create
125
+ false
126
+ end
127
+ end
128
+
129
+ class CallbacksTest < Test::Unit::TestCase
130
+ fixtures :developers
131
+
132
+ def test_initialize
133
+ david = CallbackDeveloper.new
134
+ assert_equal [
135
+ [ :after_initialize, :string ],
136
+ [ :after_initialize, :proc ],
137
+ [ :after_initialize, :object ],
138
+ [ :after_initialize, :block ],
139
+ ], david.history
140
+ end
141
+
142
+ def test_find
143
+ david = CallbackDeveloper.find(1)
144
+ assert_equal [
145
+ [ :after_find, :string ],
146
+ [ :after_find, :proc ],
147
+ [ :after_find, :object ],
148
+ [ :after_find, :block ],
149
+ [ :after_initialize, :string ],
150
+ [ :after_initialize, :proc ],
151
+ [ :after_initialize, :object ],
152
+ [ :after_initialize, :block ],
153
+ ], david.history
154
+ end
155
+
156
+ def test_new_valid?
157
+ david = CallbackDeveloper.new
158
+ david.valid?
159
+ assert_equal [
160
+ [ :after_initialize, :string ],
161
+ [ :after_initialize, :proc ],
162
+ [ :after_initialize, :object ],
163
+ [ :after_initialize, :block ],
164
+ [ :before_validation, :string ],
165
+ [ :before_validation, :proc ],
166
+ [ :before_validation, :object ],
167
+ [ :before_validation, :block ],
168
+ [ :before_validation_on_create, :string ],
169
+ [ :before_validation_on_create, :proc ],
170
+ [ :before_validation_on_create, :object ],
171
+ [ :before_validation_on_create, :block ],
172
+ [ :after_validation, :string ],
173
+ [ :after_validation, :proc ],
174
+ [ :after_validation, :object ],
175
+ [ :after_validation, :block ],
176
+ [ :after_validation_on_create, :string ],
177
+ [ :after_validation_on_create, :proc ],
178
+ [ :after_validation_on_create, :object ],
179
+ [ :after_validation_on_create, :block ]
180
+ ], david.history
181
+ end
182
+
183
+ def test_existing_valid?
184
+ david = CallbackDeveloper.find(1)
185
+ david.valid?
186
+ assert_equal [
187
+ [ :after_find, :string ],
188
+ [ :after_find, :proc ],
189
+ [ :after_find, :object ],
190
+ [ :after_find, :block ],
191
+ [ :after_initialize, :string ],
192
+ [ :after_initialize, :proc ],
193
+ [ :after_initialize, :object ],
194
+ [ :after_initialize, :block ],
195
+ [ :before_validation, :string ],
196
+ [ :before_validation, :proc ],
197
+ [ :before_validation, :object ],
198
+ [ :before_validation, :block ],
199
+ [ :before_validation_on_update, :string ],
200
+ [ :before_validation_on_update, :proc ],
201
+ [ :before_validation_on_update, :object ],
202
+ [ :before_validation_on_update, :block ],
203
+ [ :after_validation, :string ],
204
+ [ :after_validation, :proc ],
205
+ [ :after_validation, :object ],
206
+ [ :after_validation, :block ],
207
+ [ :after_validation_on_update, :string ],
208
+ [ :after_validation_on_update, :proc ],
209
+ [ :after_validation_on_update, :object ],
210
+ [ :after_validation_on_update, :block ]
211
+ ], david.history
212
+ end
213
+
214
+ def test_create
215
+ david = CallbackDeveloper.create('name' => 'David', 'salary' => 1000000)
216
+ assert_equal [
217
+ [ :after_initialize, :string ],
218
+ [ :after_initialize, :proc ],
219
+ [ :after_initialize, :object ],
220
+ [ :after_initialize, :block ],
221
+ [ :before_validation, :string ],
222
+ [ :before_validation, :proc ],
223
+ [ :before_validation, :object ],
224
+ [ :before_validation, :block ],
225
+ [ :before_validation_on_create, :string ],
226
+ [ :before_validation_on_create, :proc ],
227
+ [ :before_validation_on_create, :object ],
228
+ [ :before_validation_on_create, :block ],
229
+ [ :after_validation, :string ],
230
+ [ :after_validation, :proc ],
231
+ [ :after_validation, :object ],
232
+ [ :after_validation, :block ],
233
+ [ :after_validation_on_create, :string ],
234
+ [ :after_validation_on_create, :proc ],
235
+ [ :after_validation_on_create, :object ],
236
+ [ :after_validation_on_create, :block ],
237
+ [ :before_save, :string ],
238
+ [ :before_save, :proc ],
239
+ [ :before_save, :object ],
240
+ [ :before_save, :block ],
241
+ [ :before_create, :string ],
242
+ [ :before_create, :proc ],
243
+ [ :before_create, :object ],
244
+ [ :before_create, :block ],
245
+ [ :after_create, :string ],
246
+ [ :after_create, :proc ],
247
+ [ :after_create, :object ],
248
+ [ :after_create, :block ],
249
+ [ :after_save, :string ],
250
+ [ :after_save, :proc ],
251
+ [ :after_save, :object ],
252
+ [ :after_save, :block ]
253
+ ], david.history
254
+ end
255
+
256
+ def test_save
257
+ david = CallbackDeveloper.find(1)
258
+ david.save
259
+ assert_equal [
260
+ [ :after_find, :string ],
261
+ [ :after_find, :proc ],
262
+ [ :after_find, :object ],
263
+ [ :after_find, :block ],
264
+ [ :after_initialize, :string ],
265
+ [ :after_initialize, :proc ],
266
+ [ :after_initialize, :object ],
267
+ [ :after_initialize, :block ],
268
+ [ :before_validation, :string ],
269
+ [ :before_validation, :proc ],
270
+ [ :before_validation, :object ],
271
+ [ :before_validation, :block ],
272
+ [ :before_validation_on_update, :string ],
273
+ [ :before_validation_on_update, :proc ],
274
+ [ :before_validation_on_update, :object ],
275
+ [ :before_validation_on_update, :block ],
276
+ [ :after_validation, :string ],
277
+ [ :after_validation, :proc ],
278
+ [ :after_validation, :object ],
279
+ [ :after_validation, :block ],
280
+ [ :after_validation_on_update, :string ],
281
+ [ :after_validation_on_update, :proc ],
282
+ [ :after_validation_on_update, :object ],
283
+ [ :after_validation_on_update, :block ],
284
+ [ :before_save, :string ],
285
+ [ :before_save, :proc ],
286
+ [ :before_save, :object ],
287
+ [ :before_save, :block ],
288
+ [ :before_update, :string ],
289
+ [ :before_update, :proc ],
290
+ [ :before_update, :object ],
291
+ [ :before_update, :block ],
292
+ [ :after_update, :string ],
293
+ [ :after_update, :proc ],
294
+ [ :after_update, :object ],
295
+ [ :after_update, :block ],
296
+ [ :after_save, :string ],
297
+ [ :after_save, :proc ],
298
+ [ :after_save, :object ],
299
+ [ :after_save, :block ]
300
+ ], david.history
301
+ end
302
+
303
+ def test_destroy
304
+ david = CallbackDeveloper.find(1)
305
+ david.destroy
306
+ assert_equal [
307
+ [ :after_find, :string ],
308
+ [ :after_find, :proc ],
309
+ [ :after_find, :object ],
310
+ [ :after_find, :block ],
311
+ [ :after_initialize, :string ],
312
+ [ :after_initialize, :proc ],
313
+ [ :after_initialize, :object ],
314
+ [ :after_initialize, :block ],
315
+ [ :before_destroy, :string ],
316
+ [ :before_destroy, :proc ],
317
+ [ :before_destroy, :object ],
318
+ [ :before_destroy, :block ],
319
+ [ :after_destroy, :string ],
320
+ [ :after_destroy, :proc ],
321
+ [ :after_destroy, :object ],
322
+ [ :after_destroy, :block ]
323
+ ], david.history
324
+ end
325
+
326
+ def test_delete
327
+ david = CallbackDeveloper.find(1)
328
+ CallbackDeveloper.delete(david.id)
329
+ assert_equal [
330
+ [ :after_find, :string ],
331
+ [ :after_find, :proc ],
332
+ [ :after_find, :object ],
333
+ [ :after_find, :block ],
334
+ [ :after_initialize, :string ],
335
+ [ :after_initialize, :proc ],
336
+ [ :after_initialize, :object ],
337
+ [ :after_initialize, :block ],
338
+ ], david.history
339
+ end
340
+
341
+ def test_before_save_returning_false
342
+ david = ImmutableDeveloper.find(1)
343
+ assert david.valid?
344
+ assert !david.save
345
+ assert_raises(ActiveRecord::RecordNotSaved) { david.save! }
346
+
347
+ david = ImmutableDeveloper.find(1)
348
+ david.salary = 10_000_000
349
+ assert !david.valid?
350
+ assert !david.save
351
+ assert_raises(ActiveRecord::RecordInvalid) { david.save! }
352
+ end
353
+
354
+ def test_before_create_returning_false
355
+ someone = CallbackCancellationDeveloper.new
356
+ assert someone.valid?
357
+ assert !someone.save
358
+ end
359
+
360
+ def test_before_destroy_returning_false
361
+ david = ImmutableDeveloper.find(1)
362
+ assert !david.destroy
363
+ assert_not_nil ImmutableDeveloper.find_by_id(1)
364
+ end
365
+
366
+ def test_zzz_callback_returning_false # must be run last since we modify CallbackDeveloper
367
+ david = CallbackDeveloper.find(1)
368
+ CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :returning_false]; return false }
369
+ CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :should_never_get_here] }
370
+ david.save
371
+ assert_equal [
372
+ [ :after_find, :string ],
373
+ [ :after_find, :proc ],
374
+ [ :after_find, :object ],
375
+ [ :after_find, :block ],
376
+ [ :after_initialize, :string ],
377
+ [ :after_initialize, :proc ],
378
+ [ :after_initialize, :object ],
379
+ [ :after_initialize, :block ],
380
+ [ :before_validation, :string ],
381
+ [ :before_validation, :proc ],
382
+ [ :before_validation, :object ],
383
+ [ :before_validation, :block ],
384
+ [ :before_validation, :returning_false ]
385
+ ], david.history
386
+ end
387
+
388
+ def test_inheritence_of_callbacks
389
+ parent = ParentDeveloper.new
390
+ assert !parent.after_save_called
391
+ parent.save
392
+ assert parent.after_save_called
393
+
394
+ child = ChildDeveloper.new
395
+ assert !child.after_save_called
396
+ child.save
397
+ assert child.after_save_called
398
+ end
399
+
400
+ end
@@ -1,7 +1,6 @@
1
- $:.unshift(File.dirname(__FILE__) + '/../lib')
2
-
3
1
  require 'test/unit'
4
- require 'active_record/support/class_inheritable_attributes'
2
+ require 'abstract_unit'
3
+ require 'active_support/core_ext/class/inheritable_attributes'
5
4
 
6
5
  class A
7
6
  include ClassInheritableAttributes
@@ -30,4 +29,4 @@ class ClassInheritableAttributesTest < Test::Unit::TestCase
30
29
  assert_equal [ :one, :two, :four ], D.read_inheritable_attribute("first")
31
30
  assert_equal [ :one, :two ], B.read_inheritable_attribute("first")
32
31
  end
33
- end
32
+ end