activerecord_authorails 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. data/CHANGELOG +3043 -0
  2. data/README +360 -0
  3. data/RUNNING_UNIT_TESTS +64 -0
  4. data/Rakefile +226 -0
  5. data/examples/associations.png +0 -0
  6. data/examples/associations.rb +87 -0
  7. data/examples/shared_setup.rb +15 -0
  8. data/examples/validation.rb +85 -0
  9. data/install.rb +30 -0
  10. data/lib/active_record.rb +85 -0
  11. data/lib/active_record/acts/list.rb +244 -0
  12. data/lib/active_record/acts/nested_set.rb +211 -0
  13. data/lib/active_record/acts/tree.rb +89 -0
  14. data/lib/active_record/aggregations.rb +191 -0
  15. data/lib/active_record/associations.rb +1637 -0
  16. data/lib/active_record/associations/association_collection.rb +190 -0
  17. data/lib/active_record/associations/association_proxy.rb +158 -0
  18. data/lib/active_record/associations/belongs_to_association.rb +56 -0
  19. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
  20. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +169 -0
  21. data/lib/active_record/associations/has_many_association.rb +210 -0
  22. data/lib/active_record/associations/has_many_through_association.rb +247 -0
  23. data/lib/active_record/associations/has_one_association.rb +80 -0
  24. data/lib/active_record/attribute_methods.rb +75 -0
  25. data/lib/active_record/base.rb +2164 -0
  26. data/lib/active_record/calculations.rb +270 -0
  27. data/lib/active_record/callbacks.rb +367 -0
  28. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +279 -0
  29. data/lib/active_record/connection_adapters/abstract/database_statements.rb +130 -0
  30. data/lib/active_record/connection_adapters/abstract/quoting.rb +58 -0
  31. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +343 -0
  32. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +310 -0
  33. data/lib/active_record/connection_adapters/abstract_adapter.rb +161 -0
  34. data/lib/active_record/connection_adapters/db2_adapter.rb +228 -0
  35. data/lib/active_record/connection_adapters/firebird_adapter.rb +728 -0
  36. data/lib/active_record/connection_adapters/frontbase_adapter.rb +861 -0
  37. data/lib/active_record/connection_adapters/mysql_adapter.rb +414 -0
  38. data/lib/active_record/connection_adapters/openbase_adapter.rb +350 -0
  39. data/lib/active_record/connection_adapters/oracle_adapter.rb +689 -0
  40. data/lib/active_record/connection_adapters/postgresql_adapter.rb +584 -0
  41. data/lib/active_record/connection_adapters/sqlite_adapter.rb +407 -0
  42. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +591 -0
  43. data/lib/active_record/connection_adapters/sybase_adapter.rb +662 -0
  44. data/lib/active_record/deprecated_associations.rb +104 -0
  45. data/lib/active_record/deprecated_finders.rb +44 -0
  46. data/lib/active_record/fixtures.rb +628 -0
  47. data/lib/active_record/locking/optimistic.rb +106 -0
  48. data/lib/active_record/locking/pessimistic.rb +77 -0
  49. data/lib/active_record/migration.rb +394 -0
  50. data/lib/active_record/observer.rb +178 -0
  51. data/lib/active_record/query_cache.rb +64 -0
  52. data/lib/active_record/reflection.rb +222 -0
  53. data/lib/active_record/schema.rb +58 -0
  54. data/lib/active_record/schema_dumper.rb +149 -0
  55. data/lib/active_record/timestamp.rb +51 -0
  56. data/lib/active_record/transactions.rb +136 -0
  57. data/lib/active_record/validations.rb +843 -0
  58. data/lib/active_record/vendor/db2.rb +362 -0
  59. data/lib/active_record/vendor/mysql.rb +1214 -0
  60. data/lib/active_record/vendor/simple.rb +693 -0
  61. data/lib/active_record/version.rb +9 -0
  62. data/lib/active_record/wrappers/yaml_wrapper.rb +15 -0
  63. data/lib/active_record/wrappings.rb +58 -0
  64. data/lib/active_record/xml_serialization.rb +308 -0
  65. data/test/aaa_create_tables_test.rb +59 -0
  66. data/test/abstract_unit.rb +77 -0
  67. data/test/active_schema_test_mysql.rb +31 -0
  68. data/test/adapter_test.rb +87 -0
  69. data/test/adapter_test_sqlserver.rb +81 -0
  70. data/test/aggregations_test.rb +95 -0
  71. data/test/all.sh +8 -0
  72. data/test/ar_schema_test.rb +33 -0
  73. data/test/association_inheritance_reload.rb +14 -0
  74. data/test/associations/callbacks_test.rb +126 -0
  75. data/test/associations/cascaded_eager_loading_test.rb +138 -0
  76. data/test/associations/eager_test.rb +393 -0
  77. data/test/associations/extension_test.rb +42 -0
  78. data/test/associations/join_model_test.rb +497 -0
  79. data/test/associations_test.rb +1809 -0
  80. data/test/attribute_methods_test.rb +49 -0
  81. data/test/base_test.rb +1586 -0
  82. data/test/binary_test.rb +37 -0
  83. data/test/calculations_test.rb +219 -0
  84. data/test/callbacks_test.rb +377 -0
  85. data/test/class_inheritable_attributes_test.rb +32 -0
  86. data/test/column_alias_test.rb +17 -0
  87. data/test/connection_test_firebird.rb +8 -0
  88. data/test/connections/native_db2/connection.rb +25 -0
  89. data/test/connections/native_firebird/connection.rb +26 -0
  90. data/test/connections/native_frontbase/connection.rb +27 -0
  91. data/test/connections/native_mysql/connection.rb +24 -0
  92. data/test/connections/native_openbase/connection.rb +21 -0
  93. data/test/connections/native_oracle/connection.rb +27 -0
  94. data/test/connections/native_postgresql/connection.rb +23 -0
  95. data/test/connections/native_sqlite/connection.rb +34 -0
  96. data/test/connections/native_sqlite3/connection.rb +34 -0
  97. data/test/connections/native_sqlite3/in_memory_connection.rb +18 -0
  98. data/test/connections/native_sqlserver/connection.rb +23 -0
  99. data/test/connections/native_sqlserver_odbc/connection.rb +25 -0
  100. data/test/connections/native_sybase/connection.rb +23 -0
  101. data/test/copy_table_sqlite.rb +64 -0
  102. data/test/datatype_test_postgresql.rb +52 -0
  103. data/test/default_test_firebird.rb +16 -0
  104. data/test/defaults_test.rb +60 -0
  105. data/test/deprecated_associations_test.rb +396 -0
  106. data/test/deprecated_finder_test.rb +151 -0
  107. data/test/empty_date_time_test.rb +25 -0
  108. data/test/finder_test.rb +504 -0
  109. data/test/fixtures/accounts.yml +28 -0
  110. data/test/fixtures/author.rb +99 -0
  111. data/test/fixtures/author_favorites.yml +4 -0
  112. data/test/fixtures/authors.yml +7 -0
  113. data/test/fixtures/auto_id.rb +4 -0
  114. data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +1 -0
  115. data/test/fixtures/bad_fixtures/attr_with_spaces +1 -0
  116. data/test/fixtures/bad_fixtures/blank_line +3 -0
  117. data/test/fixtures/bad_fixtures/duplicate_attributes +3 -0
  118. data/test/fixtures/bad_fixtures/missing_value +1 -0
  119. data/test/fixtures/binary.rb +2 -0
  120. data/test/fixtures/categories.yml +14 -0
  121. data/test/fixtures/categories/special_categories.yml +9 -0
  122. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  123. data/test/fixtures/categories_ordered.yml +7 -0
  124. data/test/fixtures/categories_posts.yml +23 -0
  125. data/test/fixtures/categorization.rb +5 -0
  126. data/test/fixtures/categorizations.yml +17 -0
  127. data/test/fixtures/category.rb +20 -0
  128. data/test/fixtures/column_name.rb +3 -0
  129. data/test/fixtures/comment.rb +23 -0
  130. data/test/fixtures/comments.yml +59 -0
  131. data/test/fixtures/companies.yml +55 -0
  132. data/test/fixtures/company.rb +107 -0
  133. data/test/fixtures/company_in_module.rb +59 -0
  134. data/test/fixtures/computer.rb +3 -0
  135. data/test/fixtures/computers.yml +4 -0
  136. data/test/fixtures/course.rb +3 -0
  137. data/test/fixtures/courses.yml +7 -0
  138. data/test/fixtures/customer.rb +55 -0
  139. data/test/fixtures/customers.yml +17 -0
  140. data/test/fixtures/db_definitions/db2.drop.sql +32 -0
  141. data/test/fixtures/db_definitions/db2.sql +231 -0
  142. data/test/fixtures/db_definitions/db22.drop.sql +2 -0
  143. data/test/fixtures/db_definitions/db22.sql +5 -0
  144. data/test/fixtures/db_definitions/firebird.drop.sql +63 -0
  145. data/test/fixtures/db_definitions/firebird.sql +304 -0
  146. data/test/fixtures/db_definitions/firebird2.drop.sql +2 -0
  147. data/test/fixtures/db_definitions/firebird2.sql +6 -0
  148. data/test/fixtures/db_definitions/frontbase.drop.sql +32 -0
  149. data/test/fixtures/db_definitions/frontbase.sql +268 -0
  150. data/test/fixtures/db_definitions/frontbase2.drop.sql +1 -0
  151. data/test/fixtures/db_definitions/frontbase2.sql +4 -0
  152. data/test/fixtures/db_definitions/mysql.drop.sql +32 -0
  153. data/test/fixtures/db_definitions/mysql.sql +234 -0
  154. data/test/fixtures/db_definitions/mysql2.drop.sql +2 -0
  155. data/test/fixtures/db_definitions/mysql2.sql +5 -0
  156. data/test/fixtures/db_definitions/openbase.drop.sql +2 -0
  157. data/test/fixtures/db_definitions/openbase.sql +302 -0
  158. data/test/fixtures/db_definitions/openbase2.drop.sql +2 -0
  159. data/test/fixtures/db_definitions/openbase2.sql +7 -0
  160. data/test/fixtures/db_definitions/oracle.drop.sql +65 -0
  161. data/test/fixtures/db_definitions/oracle.sql +325 -0
  162. data/test/fixtures/db_definitions/oracle2.drop.sql +2 -0
  163. data/test/fixtures/db_definitions/oracle2.sql +6 -0
  164. data/test/fixtures/db_definitions/postgresql.drop.sql +37 -0
  165. data/test/fixtures/db_definitions/postgresql.sql +263 -0
  166. data/test/fixtures/db_definitions/postgresql2.drop.sql +2 -0
  167. data/test/fixtures/db_definitions/postgresql2.sql +5 -0
  168. data/test/fixtures/db_definitions/schema.rb +60 -0
  169. data/test/fixtures/db_definitions/sqlite.drop.sql +32 -0
  170. data/test/fixtures/db_definitions/sqlite.sql +215 -0
  171. data/test/fixtures/db_definitions/sqlite2.drop.sql +2 -0
  172. data/test/fixtures/db_definitions/sqlite2.sql +5 -0
  173. data/test/fixtures/db_definitions/sqlserver.drop.sql +34 -0
  174. data/test/fixtures/db_definitions/sqlserver.sql +243 -0
  175. data/test/fixtures/db_definitions/sqlserver2.drop.sql +2 -0
  176. data/test/fixtures/db_definitions/sqlserver2.sql +5 -0
  177. data/test/fixtures/db_definitions/sybase.drop.sql +34 -0
  178. data/test/fixtures/db_definitions/sybase.sql +218 -0
  179. data/test/fixtures/db_definitions/sybase2.drop.sql +4 -0
  180. data/test/fixtures/db_definitions/sybase2.sql +5 -0
  181. data/test/fixtures/default.rb +2 -0
  182. data/test/fixtures/developer.rb +52 -0
  183. data/test/fixtures/developers.yml +21 -0
  184. data/test/fixtures/developers_projects.yml +17 -0
  185. data/test/fixtures/developers_projects/david_action_controller +3 -0
  186. data/test/fixtures/developers_projects/david_active_record +3 -0
  187. data/test/fixtures/developers_projects/jamis_active_record +2 -0
  188. data/test/fixtures/edge.rb +5 -0
  189. data/test/fixtures/edges.yml +6 -0
  190. data/test/fixtures/entrant.rb +3 -0
  191. data/test/fixtures/entrants.yml +14 -0
  192. data/test/fixtures/fk_test_has_fk.yml +3 -0
  193. data/test/fixtures/fk_test_has_pk.yml +2 -0
  194. data/test/fixtures/flowers.jpg +0 -0
  195. data/test/fixtures/funny_jokes.yml +10 -0
  196. data/test/fixtures/joke.rb +6 -0
  197. data/test/fixtures/keyboard.rb +3 -0
  198. data/test/fixtures/legacy_thing.rb +3 -0
  199. data/test/fixtures/legacy_things.yml +3 -0
  200. data/test/fixtures/migrations/1_people_have_last_names.rb +9 -0
  201. data/test/fixtures/migrations/2_we_need_reminders.rb +12 -0
  202. data/test/fixtures/migrations/3_innocent_jointable.rb +12 -0
  203. data/test/fixtures/migrations_with_decimal/1_give_me_big_numbers.rb +15 -0
  204. data/test/fixtures/migrations_with_duplicate/1_people_have_last_names.rb +9 -0
  205. data/test/fixtures/migrations_with_duplicate/2_we_need_reminders.rb +12 -0
  206. data/test/fixtures/migrations_with_duplicate/3_foo.rb +7 -0
  207. data/test/fixtures/migrations_with_duplicate/3_innocent_jointable.rb +12 -0
  208. data/test/fixtures/migrations_with_missing_versions/1000_people_have_middle_names.rb +9 -0
  209. data/test/fixtures/migrations_with_missing_versions/1_people_have_last_names.rb +9 -0
  210. data/test/fixtures/migrations_with_missing_versions/3_we_need_reminders.rb +12 -0
  211. data/test/fixtures/migrations_with_missing_versions/4_innocent_jointable.rb +12 -0
  212. data/test/fixtures/mixed_case_monkey.rb +3 -0
  213. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  214. data/test/fixtures/mixin.rb +63 -0
  215. data/test/fixtures/mixins.yml +127 -0
  216. data/test/fixtures/movie.rb +5 -0
  217. data/test/fixtures/movies.yml +7 -0
  218. data/test/fixtures/naked/csv/accounts.csv +1 -0
  219. data/test/fixtures/naked/yml/accounts.yml +1 -0
  220. data/test/fixtures/naked/yml/companies.yml +1 -0
  221. data/test/fixtures/naked/yml/courses.yml +1 -0
  222. data/test/fixtures/order.rb +4 -0
  223. data/test/fixtures/people.yml +3 -0
  224. data/test/fixtures/person.rb +4 -0
  225. data/test/fixtures/post.rb +58 -0
  226. data/test/fixtures/posts.yml +48 -0
  227. data/test/fixtures/project.rb +27 -0
  228. data/test/fixtures/projects.yml +7 -0
  229. data/test/fixtures/reader.rb +4 -0
  230. data/test/fixtures/readers.yml +4 -0
  231. data/test/fixtures/reply.rb +37 -0
  232. data/test/fixtures/subject.rb +4 -0
  233. data/test/fixtures/subscriber.rb +6 -0
  234. data/test/fixtures/subscribers/first +2 -0
  235. data/test/fixtures/subscribers/second +2 -0
  236. data/test/fixtures/tag.rb +7 -0
  237. data/test/fixtures/tagging.rb +6 -0
  238. data/test/fixtures/taggings.yml +18 -0
  239. data/test/fixtures/tags.yml +7 -0
  240. data/test/fixtures/task.rb +3 -0
  241. data/test/fixtures/tasks.yml +7 -0
  242. data/test/fixtures/topic.rb +25 -0
  243. data/test/fixtures/topics.yml +22 -0
  244. data/test/fixtures/vertex.rb +9 -0
  245. data/test/fixtures/vertices.yml +4 -0
  246. data/test/fixtures_test.rb +401 -0
  247. data/test/inheritance_test.rb +205 -0
  248. data/test/lifecycle_test.rb +137 -0
  249. data/test/locking_test.rb +190 -0
  250. data/test/method_scoping_test.rb +416 -0
  251. data/test/migration_test.rb +768 -0
  252. data/test/migration_test_firebird.rb +124 -0
  253. data/test/mixin_nested_set_test.rb +196 -0
  254. data/test/mixin_test.rb +550 -0
  255. data/test/modules_test.rb +34 -0
  256. data/test/multiple_db_test.rb +60 -0
  257. data/test/pk_test.rb +104 -0
  258. data/test/readonly_test.rb +107 -0
  259. data/test/reflection_test.rb +159 -0
  260. data/test/schema_authorization_test_postgresql.rb +75 -0
  261. data/test/schema_dumper_test.rb +96 -0
  262. data/test/schema_test_postgresql.rb +64 -0
  263. data/test/synonym_test_oracle.rb +17 -0
  264. data/test/table_name_test_sqlserver.rb +23 -0
  265. data/test/threaded_connections_test.rb +48 -0
  266. data/test/transactions_test.rb +230 -0
  267. data/test/unconnected_test.rb +32 -0
  268. data/test/validations_test.rb +1097 -0
  269. data/test/xml_serialization_test.rb +125 -0
  270. metadata +365 -0
@@ -0,0 +1,37 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/binary'
3
+
4
+ class BinaryTest < Test::Unit::TestCase
5
+ BINARY_FIXTURE_PATH = File.dirname(__FILE__) + '/fixtures/flowers.jpg'
6
+
7
+ def setup
8
+ Binary.connection.execute 'DELETE FROM binaries'
9
+ @data = File.read(BINARY_FIXTURE_PATH).freeze
10
+ end
11
+
12
+ def test_truth
13
+ assert true
14
+ end
15
+
16
+ # Without using prepared statements, it makes no sense to test
17
+ # BLOB data with SQL Server, because the length of a statement is
18
+ # limited to 8KB.
19
+ #
20
+ # Without using prepared statements, it makes no sense to test
21
+ # BLOB data with DB2 or Firebird, because the length of a statement
22
+ # is limited to 32KB.
23
+ unless %w(SQLServer Sybase DB2 Oracle Firebird).include? ActiveRecord::Base.connection.adapter_name
24
+ def test_load_save
25
+ bin = Binary.new
26
+ bin.data = @data
27
+
28
+ assert @data == bin.data, 'Newly assigned data differs from original'
29
+
30
+ bin.save
31
+ assert @data == bin.data, 'Data differs from original after save'
32
+
33
+ db_bin = Binary.find(bin.id)
34
+ assert @data == db_bin.data, 'Reloaded data differs from original'
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,219 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/company'
3
+ require 'fixtures/topic'
4
+
5
+ Company.has_many :accounts
6
+
7
+ class CalculationsTest < Test::Unit::TestCase
8
+ fixtures :companies, :accounts, :topics
9
+
10
+ def test_should_sum_field
11
+ assert_equal 318, Account.sum(:credit_limit)
12
+ end
13
+
14
+ def test_should_average_field
15
+ value = Account.average(:credit_limit)
16
+ assert_kind_of Float, value
17
+ assert_in_delta 53.0, value, 0.001
18
+ end
19
+
20
+ def test_should_get_maximum_of_field
21
+ assert_equal 60, Account.maximum(:credit_limit)
22
+ end
23
+
24
+ def test_should_get_maximum_of_field_with_include
25
+ assert_equal 50, Account.maximum(:credit_limit, :include => :firm, :conditions => "companies.name != 'Summit'")
26
+ end
27
+
28
+ def test_should_get_maximum_of_field_with_scoped_include
29
+ Account.with_scope :find => { :include => :firm, :conditions => "companies.name != 'Summit'" } do
30
+ assert_equal 50, Account.maximum(:credit_limit)
31
+ end
32
+ end
33
+
34
+ def test_should_get_minimum_of_field
35
+ assert_equal 50, Account.minimum(:credit_limit)
36
+ end
37
+
38
+ def test_should_group_by_field
39
+ c = Account.sum(:credit_limit, :group => :firm_id)
40
+ [1,6,2].each { |firm_id| assert c.keys.include?(firm_id) }
41
+ end
42
+
43
+ def test_should_group_by_summed_field
44
+ c = Account.sum(:credit_limit, :group => :firm_id)
45
+ assert_equal 50, c[1]
46
+ assert_equal 105, c[6]
47
+ assert_equal 60, c[2]
48
+ end
49
+
50
+ def test_should_order_by_grouped_field
51
+ c = Account.sum(:credit_limit, :group => :firm_id, :order => "firm_id")
52
+ assert_equal [1, 2, 6, 9], c.keys.compact
53
+ end
54
+
55
+ def test_should_order_by_calculation
56
+ c = Account.sum(:credit_limit, :group => :firm_id, :order => "sum_credit_limit desc, firm_id")
57
+ assert_equal [105, 60, 53, 50, 50], c.keys.collect { |k| c[k] }
58
+ assert_equal [6, 2, 9, 1], c.keys.compact
59
+ end
60
+
61
+ def test_should_limit_calculation
62
+ c = Account.sum(:credit_limit, :conditions => "firm_id IS NOT NULL",
63
+ :group => :firm_id, :order => "firm_id", :limit => 2)
64
+ assert_equal [1, 2], c.keys.compact
65
+ end
66
+
67
+ def test_should_limit_calculation_with_offset
68
+ c = Account.sum(:credit_limit, :conditions => "firm_id IS NOT NULL",
69
+ :group => :firm_id, :order => "firm_id", :limit => 2, :offset => 1)
70
+ assert_equal [2, 6], c.keys.compact
71
+ end
72
+
73
+ def test_should_group_by_summed_field_having_condition
74
+ c = Account.sum(:credit_limit, :group => :firm_id,
75
+ :having => 'sum(credit_limit) > 50')
76
+ assert_nil c[1]
77
+ assert_equal 105, c[6]
78
+ assert_equal 60, c[2]
79
+ end
80
+
81
+ def test_should_group_by_summed_association
82
+ c = Account.sum(:credit_limit, :group => :firm)
83
+ assert_equal 50, c[companies(:first_firm)]
84
+ assert_equal 105, c[companies(:rails_core)]
85
+ assert_equal 60, c[companies(:first_client)]
86
+ end
87
+
88
+ def test_should_sum_field_with_conditions
89
+ assert_equal 105, Account.sum(:credit_limit, :conditions => 'firm_id = 6')
90
+ end
91
+
92
+ def test_should_group_by_summed_field_with_conditions
93
+ c = Account.sum(:credit_limit, :conditions => 'firm_id > 1',
94
+ :group => :firm_id)
95
+ assert_nil c[1]
96
+ assert_equal 105, c[6]
97
+ assert_equal 60, c[2]
98
+ end
99
+
100
+ def test_should_group_by_summed_field_with_conditions_and_having
101
+ c = Account.sum(:credit_limit, :conditions => 'firm_id > 1',
102
+ :group => :firm_id,
103
+ :having => 'sum(credit_limit) > 60')
104
+ assert_nil c[1]
105
+ assert_equal 105, c[6]
106
+ assert_nil c[2]
107
+ end
108
+
109
+ def test_should_group_by_fields_with_table_alias
110
+ c = Account.sum(:credit_limit, :group => 'accounts.firm_id')
111
+ assert_equal 50, c[1]
112
+ assert_equal 105, c[6]
113
+ assert_equal 60, c[2]
114
+ end
115
+
116
+ def test_should_calculate_with_invalid_field
117
+ assert_equal 6, Account.calculate(:count, '*')
118
+ assert_equal 6, Account.calculate(:count, :all)
119
+ end
120
+
121
+ def test_should_calculate_grouped_with_invalid_field
122
+ c = Account.count(:all, :group => 'accounts.firm_id')
123
+ assert_equal 1, c[1]
124
+ assert_equal 2, c[6]
125
+ assert_equal 1, c[2]
126
+ end
127
+
128
+ def test_should_calculate_grouped_association_with_invalid_field
129
+ c = Account.count(:all, :group => :firm)
130
+ assert_equal 1, c[companies(:first_firm)]
131
+ assert_equal 2, c[companies(:rails_core)]
132
+ assert_equal 1, c[companies(:first_client)]
133
+ end
134
+
135
+ def test_should_not_modify_options_when_using_includes
136
+ options = {:conditions => 'companies.id > 1', :include => :firm}
137
+ options_copy = options.dup
138
+
139
+ Account.count(:all, options)
140
+ assert_equal options_copy, options
141
+ end
142
+
143
+ def test_should_calculate_grouped_by_function
144
+ c = Company.count(:all, :group => "UPPER(#{QUOTED_TYPE})")
145
+ assert_equal 2, c[nil]
146
+ assert_equal 1, c['DEPENDENTFIRM']
147
+ assert_equal 3, c['CLIENT']
148
+ assert_equal 2, c['FIRM']
149
+ end
150
+
151
+ def test_should_calculate_grouped_by_function_with_table_alias
152
+ c = Company.count(:all, :group => "UPPER(companies.#{QUOTED_TYPE})")
153
+ assert_equal 2, c[nil]
154
+ assert_equal 1, c['DEPENDENTFIRM']
155
+ assert_equal 3, c['CLIENT']
156
+ assert_equal 2, c['FIRM']
157
+ end
158
+
159
+ def test_should_not_overshadow_enumerable_sum
160
+ assert_equal 6, [1, 2, 3].sum(&:abs)
161
+ end
162
+
163
+ def test_should_sum_scoped_field
164
+ assert_equal 15, companies(:rails_core).companies.sum(:id)
165
+ end
166
+
167
+ def test_should_sum_scoped_field_with_conditions
168
+ assert_equal 8, companies(:rails_core).companies.sum(:id, :conditions => 'id > 7')
169
+ end
170
+
171
+ def test_should_group_by_scoped_field
172
+ c = companies(:rails_core).companies.sum(:id, :group => :name)
173
+ assert_equal 7, c['Leetsoft']
174
+ assert_equal 8, c['Jadedpixel']
175
+ end
176
+
177
+ def test_should_group_by_summed_field_with_conditions_and_having
178
+ c = companies(:rails_core).companies.sum(:id, :group => :name,
179
+ :having => 'sum(id) > 7')
180
+ assert_nil c['Leetsoft']
181
+ assert_equal 8, c['Jadedpixel']
182
+ end
183
+
184
+ def test_should_reject_invalid_options
185
+ assert_nothing_raised do
186
+ [:count, :sum].each do |func|
187
+ # empty options are valid
188
+ Company.send(:validate_calculation_options, func)
189
+ # these options are valid for all calculations
190
+ [:select, :conditions, :joins, :order, :group, :having, :distinct].each do |opt|
191
+ Company.send(:validate_calculation_options, func, opt => true)
192
+ end
193
+ end
194
+
195
+ # :include is only valid on :count
196
+ Company.send(:validate_calculation_options, :count, :include => true)
197
+ end
198
+
199
+ assert_raises(ArgumentError) { Company.send(:validate_calculation_options, :sum, :foo => :bar) }
200
+ assert_raises(ArgumentError) { Company.send(:validate_calculation_options, :count, :foo => :bar) }
201
+ end
202
+
203
+ def test_should_count_selected_field_with_include
204
+ assert_equal 6, Account.count(:distinct => true, :include => :firm)
205
+ assert_equal 4, Account.count(:distinct => true, :include => :firm, :select => :credit_limit)
206
+ end
207
+
208
+ def test_deprecated_count_with_string_parameters
209
+ assert_deprecated('count') { Account.count('credit_limit > 50') }
210
+ end
211
+
212
+ def test_count_with_no_parameters_isnt_deprecated
213
+ assert_not_deprecated { Account.count }
214
+ end
215
+
216
+ def test_count_with_too_many_parameters_raises
217
+ assert_raise(ArgumentError) { Account.count(1, 2, 3) }
218
+ end
219
+ end
@@ -0,0 +1,377 @@
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 RecursiveCallbackDeveloper < ActiveRecord::Base
53
+ set_table_name 'developers'
54
+
55
+ before_save :on_before_save
56
+ after_save :on_after_save
57
+
58
+ attr_reader :on_before_save_called, :on_after_save_called
59
+
60
+ def on_before_save
61
+ @on_before_save_called ||= 0
62
+ @on_before_save_called += 1
63
+ save unless @on_before_save_called > 1
64
+ end
65
+
66
+ def on_after_save
67
+ @on_after_save_called ||= 0
68
+ @on_after_save_called += 1
69
+ save unless @on_after_save_called > 1
70
+ end
71
+ end
72
+
73
+ class ImmutableDeveloper < ActiveRecord::Base
74
+ set_table_name 'developers'
75
+
76
+ validates_inclusion_of :salary, :in => 50000..200000
77
+
78
+ before_save :cancel
79
+ before_destroy :cancel
80
+
81
+ def cancelled?
82
+ @cancelled == true
83
+ end
84
+
85
+ private
86
+ def cancel
87
+ @cancelled = true
88
+ false
89
+ end
90
+ end
91
+
92
+ class ImmutableMethodDeveloper < ActiveRecord::Base
93
+ set_table_name 'developers'
94
+
95
+ validates_inclusion_of :salary, :in => 50000..200000
96
+
97
+ def cancelled?
98
+ @cancelled == true
99
+ end
100
+
101
+ def before_save
102
+ @cancelled = true
103
+ false
104
+ end
105
+
106
+ def before_destroy
107
+ @cancelled = true
108
+ false
109
+ end
110
+ end
111
+
112
+ class CallbackCancellationDeveloper < ActiveRecord::Base
113
+ set_table_name 'developers'
114
+ def before_create
115
+ false
116
+ end
117
+ end
118
+
119
+ class CallbacksTest < Test::Unit::TestCase
120
+ fixtures :developers
121
+
122
+ def test_initialize
123
+ david = CallbackDeveloper.new
124
+ assert_equal [
125
+ [ :after_initialize, :string ],
126
+ [ :after_initialize, :proc ],
127
+ [ :after_initialize, :object ],
128
+ [ :after_initialize, :block ],
129
+ ], david.history
130
+ end
131
+
132
+ def test_find
133
+ david = CallbackDeveloper.find(1)
134
+ assert_equal [
135
+ [ :after_find, :string ],
136
+ [ :after_find, :proc ],
137
+ [ :after_find, :object ],
138
+ [ :after_find, :block ],
139
+ [ :after_initialize, :string ],
140
+ [ :after_initialize, :proc ],
141
+ [ :after_initialize, :object ],
142
+ [ :after_initialize, :block ],
143
+ ], david.history
144
+ end
145
+
146
+ def test_new_valid?
147
+ david = CallbackDeveloper.new
148
+ david.valid?
149
+ assert_equal [
150
+ [ :after_initialize, :string ],
151
+ [ :after_initialize, :proc ],
152
+ [ :after_initialize, :object ],
153
+ [ :after_initialize, :block ],
154
+ [ :before_validation, :string ],
155
+ [ :before_validation, :proc ],
156
+ [ :before_validation, :object ],
157
+ [ :before_validation, :block ],
158
+ [ :before_validation_on_create, :string ],
159
+ [ :before_validation_on_create, :proc ],
160
+ [ :before_validation_on_create, :object ],
161
+ [ :before_validation_on_create, :block ],
162
+ [ :after_validation, :string ],
163
+ [ :after_validation, :proc ],
164
+ [ :after_validation, :object ],
165
+ [ :after_validation, :block ],
166
+ [ :after_validation_on_create, :string ],
167
+ [ :after_validation_on_create, :proc ],
168
+ [ :after_validation_on_create, :object ],
169
+ [ :after_validation_on_create, :block ]
170
+ ], david.history
171
+ end
172
+
173
+ def test_existing_valid?
174
+ david = CallbackDeveloper.find(1)
175
+ david.valid?
176
+ assert_equal [
177
+ [ :after_find, :string ],
178
+ [ :after_find, :proc ],
179
+ [ :after_find, :object ],
180
+ [ :after_find, :block ],
181
+ [ :after_initialize, :string ],
182
+ [ :after_initialize, :proc ],
183
+ [ :after_initialize, :object ],
184
+ [ :after_initialize, :block ],
185
+ [ :before_validation, :string ],
186
+ [ :before_validation, :proc ],
187
+ [ :before_validation, :object ],
188
+ [ :before_validation, :block ],
189
+ [ :before_validation_on_update, :string ],
190
+ [ :before_validation_on_update, :proc ],
191
+ [ :before_validation_on_update, :object ],
192
+ [ :before_validation_on_update, :block ],
193
+ [ :after_validation, :string ],
194
+ [ :after_validation, :proc ],
195
+ [ :after_validation, :object ],
196
+ [ :after_validation, :block ],
197
+ [ :after_validation_on_update, :string ],
198
+ [ :after_validation_on_update, :proc ],
199
+ [ :after_validation_on_update, :object ],
200
+ [ :after_validation_on_update, :block ]
201
+ ], david.history
202
+ end
203
+
204
+ def test_create
205
+ david = CallbackDeveloper.create('name' => 'David', 'salary' => 1000000)
206
+ assert_equal [
207
+ [ :after_initialize, :string ],
208
+ [ :after_initialize, :proc ],
209
+ [ :after_initialize, :object ],
210
+ [ :after_initialize, :block ],
211
+ [ :before_validation, :string ],
212
+ [ :before_validation, :proc ],
213
+ [ :before_validation, :object ],
214
+ [ :before_validation, :block ],
215
+ [ :before_validation_on_create, :string ],
216
+ [ :before_validation_on_create, :proc ],
217
+ [ :before_validation_on_create, :object ],
218
+ [ :before_validation_on_create, :block ],
219
+ [ :after_validation, :string ],
220
+ [ :after_validation, :proc ],
221
+ [ :after_validation, :object ],
222
+ [ :after_validation, :block ],
223
+ [ :after_validation_on_create, :string ],
224
+ [ :after_validation_on_create, :proc ],
225
+ [ :after_validation_on_create, :object ],
226
+ [ :after_validation_on_create, :block ],
227
+ [ :before_save, :string ],
228
+ [ :before_save, :proc ],
229
+ [ :before_save, :object ],
230
+ [ :before_save, :block ],
231
+ [ :before_create, :string ],
232
+ [ :before_create, :proc ],
233
+ [ :before_create, :object ],
234
+ [ :before_create, :block ],
235
+ [ :after_create, :string ],
236
+ [ :after_create, :proc ],
237
+ [ :after_create, :object ],
238
+ [ :after_create, :block ],
239
+ [ :after_save, :string ],
240
+ [ :after_save, :proc ],
241
+ [ :after_save, :object ],
242
+ [ :after_save, :block ]
243
+ ], david.history
244
+ end
245
+
246
+ def test_save
247
+ david = CallbackDeveloper.find(1)
248
+ david.save
249
+ assert_equal [
250
+ [ :after_find, :string ],
251
+ [ :after_find, :proc ],
252
+ [ :after_find, :object ],
253
+ [ :after_find, :block ],
254
+ [ :after_initialize, :string ],
255
+ [ :after_initialize, :proc ],
256
+ [ :after_initialize, :object ],
257
+ [ :after_initialize, :block ],
258
+ [ :before_validation, :string ],
259
+ [ :before_validation, :proc ],
260
+ [ :before_validation, :object ],
261
+ [ :before_validation, :block ],
262
+ [ :before_validation_on_update, :string ],
263
+ [ :before_validation_on_update, :proc ],
264
+ [ :before_validation_on_update, :object ],
265
+ [ :before_validation_on_update, :block ],
266
+ [ :after_validation, :string ],
267
+ [ :after_validation, :proc ],
268
+ [ :after_validation, :object ],
269
+ [ :after_validation, :block ],
270
+ [ :after_validation_on_update, :string ],
271
+ [ :after_validation_on_update, :proc ],
272
+ [ :after_validation_on_update, :object ],
273
+ [ :after_validation_on_update, :block ],
274
+ [ :before_save, :string ],
275
+ [ :before_save, :proc ],
276
+ [ :before_save, :object ],
277
+ [ :before_save, :block ],
278
+ [ :before_update, :string ],
279
+ [ :before_update, :proc ],
280
+ [ :before_update, :object ],
281
+ [ :before_update, :block ],
282
+ [ :after_update, :string ],
283
+ [ :after_update, :proc ],
284
+ [ :after_update, :object ],
285
+ [ :after_update, :block ],
286
+ [ :after_save, :string ],
287
+ [ :after_save, :proc ],
288
+ [ :after_save, :object ],
289
+ [ :after_save, :block ]
290
+ ], david.history
291
+ end
292
+
293
+ def test_destroy
294
+ david = CallbackDeveloper.find(1)
295
+ david.destroy
296
+ assert_equal [
297
+ [ :after_find, :string ],
298
+ [ :after_find, :proc ],
299
+ [ :after_find, :object ],
300
+ [ :after_find, :block ],
301
+ [ :after_initialize, :string ],
302
+ [ :after_initialize, :proc ],
303
+ [ :after_initialize, :object ],
304
+ [ :after_initialize, :block ],
305
+ [ :before_destroy, :string ],
306
+ [ :before_destroy, :proc ],
307
+ [ :before_destroy, :object ],
308
+ [ :before_destroy, :block ],
309
+ [ :after_destroy, :string ],
310
+ [ :after_destroy, :proc ],
311
+ [ :after_destroy, :object ],
312
+ [ :after_destroy, :block ]
313
+ ], david.history
314
+ end
315
+
316
+ def test_delete
317
+ david = CallbackDeveloper.find(1)
318
+ CallbackDeveloper.delete(david.id)
319
+ assert_equal [
320
+ [ :after_find, :string ],
321
+ [ :after_find, :proc ],
322
+ [ :after_find, :object ],
323
+ [ :after_find, :block ],
324
+ [ :after_initialize, :string ],
325
+ [ :after_initialize, :proc ],
326
+ [ :after_initialize, :object ],
327
+ [ :after_initialize, :block ],
328
+ ], david.history
329
+ end
330
+
331
+ def test_before_save_returning_false
332
+ david = ImmutableDeveloper.find(1)
333
+ assert david.valid?
334
+ assert !david.save
335
+ assert_raises(ActiveRecord::RecordNotSaved) { david.save! }
336
+
337
+ david = ImmutableDeveloper.find(1)
338
+ david.salary = 10_000_000
339
+ assert !david.valid?
340
+ assert !david.save
341
+ assert_raises(ActiveRecord::RecordInvalid) { david.save! }
342
+ end
343
+
344
+ def test_before_create_returning_false
345
+ someone = CallbackCancellationDeveloper.new
346
+ assert someone.valid?
347
+ assert !someone.save
348
+ end
349
+
350
+ def test_before_destroy_returning_false
351
+ david = ImmutableDeveloper.find(1)
352
+ assert !david.destroy
353
+ assert_not_nil ImmutableDeveloper.find_by_id(1)
354
+ end
355
+
356
+ def test_zzz_callback_returning_false # must be run last since we modify CallbackDeveloper
357
+ david = CallbackDeveloper.find(1)
358
+ CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :returning_false]; return false }
359
+ CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :should_never_get_here] }
360
+ david.save
361
+ assert_equal [
362
+ [ :after_find, :string ],
363
+ [ :after_find, :proc ],
364
+ [ :after_find, :object ],
365
+ [ :after_find, :block ],
366
+ [ :after_initialize, :string ],
367
+ [ :after_initialize, :proc ],
368
+ [ :after_initialize, :object ],
369
+ [ :after_initialize, :block ],
370
+ [ :before_validation, :string ],
371
+ [ :before_validation, :proc ],
372
+ [ :before_validation, :object ],
373
+ [ :before_validation, :block ],
374
+ [ :before_validation, :returning_false ]
375
+ ], david.history
376
+ end
377
+ end