activerecord_authorails 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,32 @@
1
+ require 'abstract_unit'
2
+
3
+ class TestRecord < ActiveRecord::Base
4
+ end
5
+
6
+ class TestUnconnectedAdaptor < Test::Unit::TestCase
7
+ self.use_transactional_fixtures = false
8
+
9
+ def setup
10
+ @underlying = ActiveRecord::Base.connection
11
+ @specification = ActiveRecord::Base.remove_connection
12
+ end
13
+
14
+ def teardown
15
+ @underlying = nil
16
+ ActiveRecord::Base.establish_connection(@specification)
17
+ end
18
+
19
+ def test_connection_no_longer_established
20
+ assert_raise(ActiveRecord::ConnectionNotEstablished) do
21
+ TestRecord.find(1)
22
+ end
23
+
24
+ assert_raise(ActiveRecord::ConnectionNotEstablished) do
25
+ TestRecord.new.save
26
+ end
27
+ end
28
+
29
+ def test_underlying_adapter_no_longer_active
30
+ assert !@underlying.active?, "Removed adapter should no longer be active"
31
+ end
32
+ end
@@ -0,0 +1,1097 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/topic'
3
+ require 'fixtures/reply'
4
+ require 'fixtures/developer'
5
+
6
+ # The following methods in Topic are used in test_conditional_validation_*
7
+ class Topic
8
+ def condition_is_true
9
+ return true
10
+ end
11
+
12
+ def condition_is_true_but_its_not
13
+ return false
14
+ end
15
+ end
16
+
17
+ class ValidationsTest < Test::Unit::TestCase
18
+ fixtures :topics, :developers
19
+
20
+ def setup
21
+ Topic.write_inheritable_attribute(:validate, nil)
22
+ Topic.write_inheritable_attribute(:validate_on_create, nil)
23
+ Topic.write_inheritable_attribute(:validate_on_update, nil)
24
+ end
25
+
26
+ def test_single_field_validation
27
+ r = Reply.new
28
+ r.title = "There's no content!"
29
+ assert !r.valid?, "A reply without content shouldn't be saveable"
30
+
31
+ r.content = "Messa content!"
32
+ assert r.valid?, "A reply with content should be saveable"
33
+ end
34
+
35
+ def test_single_attr_validation_and_error_msg
36
+ r = Reply.new
37
+ r.title = "There's no content!"
38
+ assert !r.valid?
39
+ assert r.errors.invalid?("content"), "A reply without content should mark that attribute as invalid"
40
+ assert_equal "Empty", r.errors.on("content"), "A reply without content should contain an error"
41
+ assert_equal 1, r.errors.count
42
+ end
43
+
44
+ def test_double_attr_validation_and_error_msg
45
+ r = Reply.new
46
+ assert !r.valid?
47
+
48
+ assert r.errors.invalid?("title"), "A reply without title should mark that attribute as invalid"
49
+ assert_equal "Empty", r.errors.on("title"), "A reply without title should contain an error"
50
+
51
+ assert r.errors.invalid?("content"), "A reply without content should mark that attribute as invalid"
52
+ assert_equal "Empty", r.errors.on("content"), "A reply without content should contain an error"
53
+
54
+ assert_equal 2, r.errors.count
55
+ end
56
+
57
+ def test_error_on_create
58
+ r = Reply.new
59
+ r.title = "Wrong Create"
60
+ assert !r.valid?
61
+ assert r.errors.invalid?("title"), "A reply with a bad title should mark that attribute as invalid"
62
+ assert_equal "is Wrong Create", r.errors.on("title"), "A reply with a bad content should contain an error"
63
+ end
64
+
65
+ def test_error_on_update
66
+ r = Reply.new
67
+ r.title = "Bad"
68
+ r.content = "Good"
69
+ assert r.save, "First save should be successful"
70
+
71
+ r.title = "Wrong Update"
72
+ assert !r.save, "Second save should fail"
73
+
74
+ assert r.errors.invalid?("title"), "A reply with a bad title should mark that attribute as invalid"
75
+ assert_equal "is Wrong Update", r.errors.on("title"), "A reply with a bad content should contain an error"
76
+ end
77
+
78
+ def test_invalid_record_exception
79
+ assert_raises(ActiveRecord::RecordInvalid) { Reply.create! }
80
+ assert_raises(ActiveRecord::RecordInvalid) { Reply.new.save! }
81
+
82
+ begin
83
+ r = Reply.new
84
+ r.save!
85
+ flunk
86
+ rescue ActiveRecord::RecordInvalid => invalid
87
+ assert_equal r, invalid.record
88
+ end
89
+ end
90
+
91
+ def test_scoped_create_without_attributes
92
+ Reply.with_scope(:create => {}) do
93
+ assert_raises(ActiveRecord::RecordInvalid) { Reply.create! }
94
+ end
95
+ end
96
+
97
+ def test_single_error_per_attr_iteration
98
+ r = Reply.new
99
+ r.save
100
+
101
+ errors = []
102
+ r.errors.each { |attr, msg| errors << [attr, msg] }
103
+
104
+ assert errors.include?(["title", "Empty"])
105
+ assert errors.include?(["content", "Empty"])
106
+ end
107
+
108
+ def test_multiple_errors_per_attr_iteration_with_full_error_composition
109
+ r = Reply.new
110
+ r.title = "Wrong Create"
111
+ r.content = "Mismatch"
112
+ r.save
113
+
114
+ errors = []
115
+ r.errors.each_full { |error| errors << error }
116
+
117
+ assert_equal "Title is Wrong Create", errors[0]
118
+ assert_equal "Title is Content Mismatch", errors[1]
119
+ assert_equal 2, r.errors.count
120
+ end
121
+
122
+ def test_errors_on_base
123
+ r = Reply.new
124
+ r.content = "Mismatch"
125
+ r.save
126
+ r.errors.add_to_base "Reply is not dignifying"
127
+
128
+ errors = []
129
+ r.errors.each_full { |error| errors << error }
130
+
131
+ assert_equal "Reply is not dignifying", r.errors.on_base
132
+
133
+ assert errors.include?("Title Empty")
134
+ assert errors.include?("Reply is not dignifying")
135
+ assert_equal 2, r.errors.count
136
+ end
137
+
138
+ def test_create_without_validation
139
+ reply = Reply.new
140
+ assert !reply.save
141
+ assert reply.save(false)
142
+ end
143
+
144
+ def test_create_without_validation_bang
145
+ count = Reply.count
146
+ assert_nothing_raised { Reply.new.save_without_validation! }
147
+ assert count+1, Reply.count
148
+ end
149
+
150
+ def test_validates_each
151
+ perform = true
152
+ hits = 0
153
+ Topic.validates_each(:title, :content, [:title, :content]) do |record, attr|
154
+ if perform
155
+ record.errors.add attr, 'gotcha'
156
+ hits += 1
157
+ end
158
+ end
159
+ t = Topic.new("title" => "valid", "content" => "whatever")
160
+ assert !t.save
161
+ assert_equal 4, hits
162
+ assert_equal %w(gotcha gotcha), t.errors.on(:title)
163
+ assert_equal %w(gotcha gotcha), t.errors.on(:content)
164
+ ensure
165
+ perform = false
166
+ end
167
+
168
+ def test_no_title_confirmation
169
+ Topic.validates_confirmation_of(:title)
170
+
171
+ t = Topic.new(:author_name => "Plutarch")
172
+ assert t.valid?
173
+
174
+ t.title_confirmation = "Parallel Lives"
175
+ assert !t.valid?
176
+
177
+ t.title_confirmation = nil
178
+ t.title = "Parallel Lives"
179
+ assert t.valid?
180
+
181
+ t.title_confirmation = "Parallel Lives"
182
+ assert t.valid?
183
+ end
184
+
185
+ def test_title_confirmation
186
+ Topic.validates_confirmation_of(:title)
187
+
188
+ t = Topic.create("title" => "We should be confirmed","title_confirmation" => "")
189
+ assert !t.save
190
+
191
+ t.title_confirmation = "We should be confirmed"
192
+ assert t.save
193
+ end
194
+
195
+ def test_terms_of_service_agreement_no_acceptance
196
+ Topic.validates_acceptance_of(:terms_of_service, :on => :create)
197
+
198
+ t = Topic.create("title" => "We should not be confirmed")
199
+ assert t.save
200
+ end
201
+
202
+ def test_terms_of_service_agreement
203
+ Topic.validates_acceptance_of(:terms_of_service, :on => :create)
204
+
205
+ t = Topic.create("title" => "We should be confirmed","terms_of_service" => "")
206
+ assert !t.save
207
+ assert_equal "must be accepted", t.errors.on(:terms_of_service)
208
+
209
+ t.terms_of_service = "1"
210
+ assert t.save
211
+ end
212
+
213
+
214
+ def test_eula
215
+ Topic.validates_acceptance_of(:eula, :message => "must be abided", :on => :create)
216
+
217
+ t = Topic.create("title" => "We should be confirmed","eula" => "")
218
+ assert !t.save
219
+ assert_equal "must be abided", t.errors.on(:eula)
220
+
221
+ t.eula = "1"
222
+ assert t.save
223
+ end
224
+
225
+ def test_terms_of_service_agreement_with_accept_value
226
+ Topic.validates_acceptance_of(:terms_of_service, :on => :create, :accept => "I agree.")
227
+
228
+ t = Topic.create("title" => "We should be confirmed", "terms_of_service" => "")
229
+ assert !t.save
230
+ assert_equal "must be accepted", t.errors.on(:terms_of_service)
231
+
232
+ t.terms_of_service = "I agree."
233
+ assert t.save
234
+ end
235
+
236
+ def test_validate_presences
237
+ Topic.validates_presence_of(:title, :content)
238
+
239
+ t = Topic.create
240
+ assert !t.save
241
+ assert_equal "can't be blank", t.errors.on(:title)
242
+ assert_equal "can't be blank", t.errors.on(:content)
243
+
244
+ t.title = "something"
245
+ t.content = " "
246
+
247
+ assert !t.save
248
+ assert_equal "can't be blank", t.errors.on(:content)
249
+
250
+ t.content = "like stuff"
251
+
252
+ assert t.save
253
+ end
254
+
255
+ def test_validate_uniqueness
256
+ Topic.validates_uniqueness_of(:title)
257
+
258
+ t = Topic.new("title" => "I'm unique!")
259
+ assert t.save, "Should save t as unique"
260
+
261
+ t.content = "Remaining unique"
262
+ assert t.save, "Should still save t as unique"
263
+
264
+ t2 = Topic.new("title" => "I'm unique!")
265
+ assert !t2.valid?, "Shouldn't be valid"
266
+ assert !t2.save, "Shouldn't save t2 as unique"
267
+ assert_equal "has already been taken", t2.errors.on(:title)
268
+
269
+ t2.title = "Now Im really also unique"
270
+ assert t2.save, "Should now save t2 as unique"
271
+ end
272
+
273
+ def test_validate_uniqueness_with_scope
274
+ Reply.validates_uniqueness_of(:content, :scope => "parent_id")
275
+
276
+ t = Topic.create("title" => "I'm unique!")
277
+
278
+ r1 = t.replies.create "title" => "r1", "content" => "hello world"
279
+ assert r1.valid?, "Saving r1"
280
+
281
+ r2 = t.replies.create "title" => "r2", "content" => "hello world"
282
+ assert !r2.valid?, "Saving r2 first time"
283
+
284
+ r2.content = "something else"
285
+ assert r2.save, "Saving r2 second time"
286
+
287
+ t2 = Topic.create("title" => "I'm unique too!")
288
+ r3 = t2.replies.create "title" => "r3", "content" => "hello world"
289
+ assert r3.valid?, "Saving r3"
290
+ end
291
+
292
+ def test_validate_uniqueness_with_scope_array
293
+ Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
294
+
295
+ t = Topic.create("title" => "The earth is actually flat!")
296
+
297
+ r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
298
+ assert r1.valid?, "Saving r1"
299
+
300
+ r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
301
+ assert !r2.valid?, "Saving r2. Double reply by same author."
302
+
303
+ r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
304
+ assert r2.save, "Saving r2 the second time."
305
+
306
+ r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
307
+ assert !r3.valid?, "Saving r3"
308
+
309
+ r3.author_name = "jj"
310
+ assert r3.save, "Saving r3 the second time."
311
+
312
+ r3.author_name = "jeremy"
313
+ assert !r3.save, "Saving r3 the third time."
314
+ end
315
+
316
+ def test_validate_case_insensitive_uniqueness
317
+ Topic.validates_uniqueness_of(:title, :parent_id, :case_sensitive => false, :allow_nil => true)
318
+
319
+ t = Topic.new("title" => "I'm unique!", :parent_id => 2)
320
+ assert t.save, "Should save t as unique"
321
+
322
+ t.content = "Remaining unique"
323
+ assert t.save, "Should still save t as unique"
324
+
325
+ t2 = Topic.new("title" => "I'm UNIQUE!", :parent_id => 1)
326
+ assert !t2.valid?, "Shouldn't be valid"
327
+ assert !t2.save, "Shouldn't save t2 as unique"
328
+ assert t2.errors.on(:title)
329
+ assert t2.errors.on(:parent_id)
330
+ assert_equal "has already been taken", t2.errors.on(:title)
331
+
332
+ t2.title = "I'm truly UNIQUE!"
333
+ assert !t2.valid?, "Shouldn't be valid"
334
+ assert !t2.save, "Shouldn't save t2 as unique"
335
+ assert_nil t2.errors.on(:title)
336
+ assert t2.errors.on(:parent_id)
337
+
338
+ t2.parent_id = 3
339
+ assert t2.save, "Should now save t2 as unique"
340
+
341
+ t2.parent_id = nil
342
+ t2.title = nil
343
+ assert t2.valid?, "should validate with nil"
344
+ assert t2.save, "should save with nil"
345
+ end
346
+
347
+ def test_validate_format
348
+ Topic.validates_format_of(:title, :content, :with => /^Validation\smacros \w+!$/, :message => "is bad data")
349
+
350
+ t = Topic.create("title" => "i'm incorrect", "content" => "Validation macros rule!")
351
+ assert !t.valid?, "Shouldn't be valid"
352
+ assert !t.save, "Shouldn't save because it's invalid"
353
+ assert_equal "is bad data", t.errors.on(:title)
354
+ assert_nil t.errors.on(:content)
355
+
356
+ t.title = "Validation macros rule!"
357
+
358
+ assert t.save
359
+ assert_nil t.errors.on(:title)
360
+
361
+ assert_raise(ArgumentError) { Topic.validates_format_of(:title, :content) }
362
+ end
363
+
364
+ # testing ticket #3142
365
+ def test_validate_format_numeric
366
+ Topic.validates_format_of(:title, :content, :with => /^[1-9][0-9]*$/, :message => "is bad data")
367
+
368
+ t = Topic.create("title" => "72x", "content" => "6789")
369
+ assert !t.valid?, "Shouldn't be valid"
370
+ assert !t.save, "Shouldn't save because it's invalid"
371
+ assert_equal "is bad data", t.errors.on(:title)
372
+ assert_nil t.errors.on(:content)
373
+
374
+ t.title = "-11"
375
+ assert !t.valid?, "Shouldn't be valid"
376
+
377
+ t.title = "03"
378
+ assert !t.valid?, "Shouldn't be valid"
379
+
380
+ t.title = "z44"
381
+ assert !t.valid?, "Shouldn't be valid"
382
+
383
+ t.title = "5v7"
384
+ assert !t.valid?, "Shouldn't be valid"
385
+
386
+ t.title = "1"
387
+
388
+ assert t.save
389
+ assert_nil t.errors.on(:title)
390
+ end
391
+
392
+ def test_validates_inclusion_of
393
+ Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ) )
394
+
395
+ assert !Topic.create("title" => "a!", "content" => "abc").valid?
396
+ assert !Topic.create("title" => "a b", "content" => "abc").valid?
397
+ assert !Topic.create("title" => nil, "content" => "def").valid?
398
+
399
+ t = Topic.create("title" => "a", "content" => "I know you are but what am I?")
400
+ assert t.valid?
401
+ t.title = "uhoh"
402
+ assert !t.valid?
403
+ assert t.errors.on(:title)
404
+ assert_equal "is not included in the list", t.errors["title"]
405
+
406
+ assert_raise(ArgumentError) { Topic.validates_inclusion_of( :title, :in => nil ) }
407
+ assert_raise(ArgumentError) { Topic.validates_inclusion_of( :title, :in => 0) }
408
+
409
+ assert_nothing_raised(ArgumentError) { Topic.validates_inclusion_of( :title, :in => "hi!" ) }
410
+ assert_nothing_raised(ArgumentError) { Topic.validates_inclusion_of( :title, :in => {} ) }
411
+ assert_nothing_raised(ArgumentError) { Topic.validates_inclusion_of( :title, :in => [] ) }
412
+ end
413
+
414
+ def test_validates_inclusion_of_with_allow_nil
415
+ Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ), :allow_nil=>true )
416
+
417
+ assert !Topic.create("title" => "a!", "content" => "abc").valid?
418
+ assert !Topic.create("title" => "", "content" => "abc").valid?
419
+ assert Topic.create("title" => nil, "content" => "abc").valid?
420
+ end
421
+
422
+ def test_numericality_with_allow_nil_and_getter_method
423
+ Developer.validates_numericality_of( :salary, :allow_nil => true)
424
+ developer = Developer.new("name" => "michael", "salary" => nil)
425
+ developer.instance_eval("def salary; read_attribute('salary') ? read_attribute('salary') : 100000; end")
426
+ assert developer.valid?
427
+ end
428
+
429
+ def test_validates_exclusion_of
430
+ Topic.validates_exclusion_of( :title, :in => %w( abe monkey ) )
431
+
432
+ assert Topic.create("title" => "something", "content" => "abc").valid?
433
+ assert !Topic.create("title" => "monkey", "content" => "abc").valid?
434
+ end
435
+
436
+ def test_validates_length_of_using_minimum
437
+ Topic.validates_length_of :title, :minimum => 5
438
+
439
+ t = Topic.create("title" => "valid", "content" => "whatever")
440
+ assert t.valid?
441
+
442
+ t.title = "not"
443
+ assert !t.valid?
444
+ assert t.errors.on(:title)
445
+ assert_equal "is too short (minimum is 5 characters)", t.errors["title"]
446
+
447
+ t.title = ""
448
+ assert !t.valid?
449
+ assert t.errors.on(:title)
450
+ assert_equal "is too short (minimum is 5 characters)", t.errors["title"]
451
+
452
+ t.title = nil
453
+ assert !t.valid?
454
+ assert t.errors.on(:title)
455
+ assert_equal "is too short (minimum is 5 characters)", t.errors["title"]
456
+ end
457
+
458
+ def test_optionally_validates_length_of_using_minimum
459
+ Topic.validates_length_of :title, :minimum => 5, :allow_nil => true
460
+
461
+ t = Topic.create("title" => "valid", "content" => "whatever")
462
+ assert t.valid?
463
+
464
+ t.title = nil
465
+ assert t.valid?
466
+ end
467
+
468
+ def test_validates_length_of_using_maximum
469
+ Topic.validates_length_of :title, :maximum => 5
470
+
471
+ t = Topic.create("title" => "valid", "content" => "whatever")
472
+ assert t.valid?
473
+
474
+ t.title = "notvalid"
475
+ assert !t.valid?
476
+ assert t.errors.on(:title)
477
+ assert_equal "is too long (maximum is 5 characters)", t.errors["title"]
478
+
479
+ t.title = ""
480
+ assert t.valid?
481
+
482
+ t.title = nil
483
+ assert !t.valid?
484
+ end
485
+
486
+ def test_optionally_validates_length_of_using_maximum
487
+ Topic.validates_length_of :title, :maximum => 5, :allow_nil => true
488
+
489
+ t = Topic.create("title" => "valid", "content" => "whatever")
490
+ assert t.valid?
491
+
492
+ t.title = nil
493
+ assert t.valid?
494
+ end
495
+
496
+ def test_validates_length_of_using_within
497
+ Topic.validates_length_of(:title, :content, :within => 3..5)
498
+
499
+ t = Topic.new("title" => "a!", "content" => "I'm ooooooooh so very long")
500
+ assert !t.valid?
501
+ assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title)
502
+ assert_equal "is too long (maximum is 5 characters)", t.errors.on(:content)
503
+
504
+ t.title = nil
505
+ t.content = nil
506
+ assert !t.valid?
507
+ assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title)
508
+ assert_equal "is too short (minimum is 3 characters)", t.errors.on(:content)
509
+
510
+ t.title = "abe"
511
+ t.content = "mad"
512
+ assert t.valid?
513
+ end
514
+
515
+ def test_optionally_validates_length_of_using_within
516
+ Topic.validates_length_of :title, :content, :within => 3..5, :allow_nil => true
517
+
518
+ t = Topic.create('title' => 'abc', 'content' => 'abcd')
519
+ assert t.valid?
520
+
521
+ t.title = nil
522
+ assert t.valid?
523
+ end
524
+
525
+ def test_optionally_validates_length_of_using_within_on_create
526
+ Topic.validates_length_of :title, :content, :within => 5..10, :on => :create, :too_long => "my string is too long: %d"
527
+
528
+ t = Topic.create("title" => "thisisnotvalid", "content" => "whatever")
529
+ assert !t.save
530
+ assert t.errors.on(:title)
531
+ assert_equal "my string is too long: 10", t.errors[:title]
532
+
533
+ t.title = "butthisis"
534
+ assert t.save
535
+
536
+ t.title = "few"
537
+ assert t.save
538
+
539
+ t.content = "andthisislong"
540
+ assert t.save
541
+
542
+ t.content = t.title = "iamfine"
543
+ assert t.save
544
+ end
545
+
546
+ def test_optionally_validates_length_of_using_within_on_update
547
+ Topic.validates_length_of :title, :content, :within => 5..10, :on => :update, :too_short => "my string is too short: %d"
548
+
549
+ t = Topic.create("title" => "vali", "content" => "whatever")
550
+ assert !t.save
551
+ assert t.errors.on(:title)
552
+
553
+ t.title = "not"
554
+ assert !t.save
555
+ assert t.errors.on(:title)
556
+ assert_equal "my string is too short: 5", t.errors[:title]
557
+
558
+ t.title = "valid"
559
+ t.content = "andthisistoolong"
560
+ assert !t.save
561
+ assert t.errors.on(:content)
562
+
563
+ t.content = "iamfine"
564
+ assert t.save
565
+ end
566
+
567
+ def test_validates_length_of_using_is
568
+ Topic.validates_length_of :title, :is => 5
569
+
570
+ t = Topic.create("title" => "valid", "content" => "whatever")
571
+ assert t.valid?
572
+
573
+ t.title = "notvalid"
574
+ assert !t.valid?
575
+ assert t.errors.on(:title)
576
+ assert_equal "is the wrong length (should be 5 characters)", t.errors["title"]
577
+
578
+ t.title = ""
579
+ assert !t.valid?
580
+
581
+ t.title = nil
582
+ assert !t.valid?
583
+ end
584
+
585
+ def test_optionally_validates_length_of_using_is
586
+ Topic.validates_length_of :title, :is => 5, :allow_nil => true
587
+
588
+ t = Topic.create("title" => "valid", "content" => "whatever")
589
+ assert t.valid?
590
+
591
+ t.title = nil
592
+ assert t.valid?
593
+ end
594
+
595
+ def test_validates_length_of_using_bignum
596
+ bigmin = 2 ** 30
597
+ bigmax = 2 ** 32
598
+ bigrange = bigmin...bigmax
599
+ assert_nothing_raised do
600
+ Topic.validates_length_of :title, :is => bigmin + 5
601
+ Topic.validates_length_of :title, :within => bigrange
602
+ Topic.validates_length_of :title, :in => bigrange
603
+ Topic.validates_length_of :title, :minimum => bigmin
604
+ Topic.validates_length_of :title, :maximum => bigmax
605
+ end
606
+ end
607
+
608
+ def test_validates_length_with_globaly_modified_error_message
609
+ ActiveRecord::Errors.default_error_messages[:too_short] = 'tu est trops petit hombre %d'
610
+ Topic.validates_length_of :title, :minimum => 10
611
+ t = Topic.create(:title => 'too short')
612
+ assert !t.valid?
613
+
614
+ assert_equal 'tu est trops petit hombre 10', t.errors['title']
615
+ end
616
+
617
+ def test_add_on_boundary_breaking_is_deprecated
618
+ t = Topic.new('title' => 'noreplies', 'content' => 'whatever')
619
+ class << t
620
+ def validate
621
+ errors.add_on_boundary_breaking('title', 1..6)
622
+ end
623
+ end
624
+ assert_deprecated 'add_on_boundary_breaking' do
625
+ assert !t.valid?
626
+ end
627
+ end
628
+
629
+ def test_validates_size_of_association
630
+ assert_nothing_raised { Topic.validates_size_of :replies, :minimum => 1 }
631
+ t = Topic.new('title' => 'noreplies', 'content' => 'whatever')
632
+ assert !t.save
633
+ assert t.errors.on(:replies)
634
+ t.replies.create('title' => 'areply', 'content' => 'whateveragain')
635
+ assert t.valid?
636
+ end
637
+
638
+ def test_validates_length_of_nasty_params
639
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, :minimum=>6, :maximum=>9) }
640
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>6, :maximum=>9) }
641
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>6, :minimum=>9) }
642
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>6, :is=>9) }
643
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, :minimum=>"a") }
644
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, :maximum=>"a") }
645
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>"a") }
646
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, :is=>"a") }
647
+ end
648
+
649
+ def test_validates_length_of_custom_errors_for_minimum_with_message
650
+ Topic.validates_length_of( :title, :minimum=>5, :message=>"boo %d" )
651
+ t = Topic.create("title" => "uhoh", "content" => "whatever")
652
+ assert !t.valid?
653
+ assert t.errors.on(:title)
654
+ assert_equal "boo 5", t.errors["title"]
655
+ end
656
+
657
+ def test_validates_length_of_custom_errors_for_minimum_with_too_short
658
+ Topic.validates_length_of( :title, :minimum=>5, :too_short=>"hoo %d" )
659
+ t = Topic.create("title" => "uhoh", "content" => "whatever")
660
+ assert !t.valid?
661
+ assert t.errors.on(:title)
662
+ assert_equal "hoo 5", t.errors["title"]
663
+ end
664
+
665
+ def test_validates_length_of_custom_errors_for_maximum_with_message
666
+ Topic.validates_length_of( :title, :maximum=>5, :message=>"boo %d" )
667
+ t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
668
+ assert !t.valid?
669
+ assert t.errors.on(:title)
670
+ assert_equal "boo 5", t.errors["title"]
671
+ end
672
+
673
+ def test_validates_length_of_custom_errors_for_maximum_with_too_long
674
+ Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d" )
675
+ t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
676
+ assert !t.valid?
677
+ assert t.errors.on(:title)
678
+ assert_equal "hoo 5", t.errors["title"]
679
+ end
680
+
681
+ def test_validates_length_of_custom_errors_for_is_with_message
682
+ Topic.validates_length_of( :title, :is=>5, :message=>"boo %d" )
683
+ t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
684
+ assert !t.valid?
685
+ assert t.errors.on(:title)
686
+ assert_equal "boo 5", t.errors["title"]
687
+ end
688
+
689
+ def test_validates_length_of_custom_errors_for_is_with_wrong_length
690
+ Topic.validates_length_of( :title, :is=>5, :wrong_length=>"hoo %d" )
691
+ t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
692
+ assert !t.valid?
693
+ assert t.errors.on(:title)
694
+ assert_equal "hoo 5", t.errors["title"]
695
+ end
696
+
697
+ def kcode_scope(kcode)
698
+ orig_kcode = $KCODE
699
+ $KCODE = kcode
700
+ begin
701
+ yield
702
+ ensure
703
+ $KCODE = orig_kcode
704
+ end
705
+ end
706
+
707
+ def test_validates_length_of_using_minimum_utf8
708
+ kcode_scope('UTF8') do
709
+ Topic.validates_length_of :title, :minimum => 5
710
+
711
+ t = Topic.create("title" => "一二三四五", "content" => "whatever")
712
+ assert t.valid?
713
+
714
+ t.title = "一二三四"
715
+ assert !t.valid?
716
+ assert t.errors.on(:title)
717
+ assert_equal "is too short (minimum is 5 characters)", t.errors["title"]
718
+ end
719
+ end
720
+
721
+ def test_validates_length_of_using_maximum_utf8
722
+ kcode_scope('UTF8') do
723
+ Topic.validates_length_of :title, :maximum => 5
724
+
725
+ t = Topic.create("title" => "一二三四五", "content" => "whatever")
726
+ assert t.valid?
727
+
728
+ t.title = "一二34五六"
729
+ assert !t.valid?
730
+ assert t.errors.on(:title)
731
+ assert_equal "is too long (maximum is 5 characters)", t.errors["title"]
732
+ end
733
+ end
734
+
735
+ def test_validates_length_of_using_within_utf8
736
+ kcode_scope('UTF8') do
737
+ Topic.validates_length_of(:title, :content, :within => 3..5)
738
+
739
+ t = Topic.new("title" => "一二", "content" => "12三四五六七")
740
+ assert !t.valid?
741
+ assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title)
742
+ assert_equal "is too long (maximum is 5 characters)", t.errors.on(:content)
743
+ t.title = "一二三"
744
+ t.content = "12三"
745
+ assert t.valid?
746
+ end
747
+ end
748
+
749
+ def test_optionally_validates_length_of_using_within_utf8
750
+ kcode_scope('UTF8') do
751
+ Topic.validates_length_of :title, :content, :within => 3..5, :allow_nil => true
752
+
753
+ t = Topic.create('title' => '一二三', 'content' => '一二三四五')
754
+ assert t.valid?
755
+
756
+ t.title = nil
757
+ assert t.valid?
758
+ end
759
+ end
760
+
761
+ def test_optionally_validates_length_of_using_within_on_create_utf8
762
+ kcode_scope('UTF8') do
763
+ Topic.validates_length_of :title, :content, :within => 5..10, :on => :create, :too_long => "長すぎます: %d"
764
+
765
+ t = Topic.create("title" => "一二三四五六七八九十A", "content" => "whatever")
766
+ assert !t.save
767
+ assert t.errors.on(:title)
768
+ assert_equal "長すぎます: 10", t.errors[:title]
769
+
770
+ t.title = "一二三四五六七八九"
771
+ assert t.save
772
+
773
+ t.title = "一二3"
774
+ assert t.save
775
+
776
+ t.content = "一二三四五六七八九十"
777
+ assert t.save
778
+
779
+ t.content = t.title = "一二三四五六"
780
+ assert t.save
781
+ end
782
+ end
783
+
784
+ def test_optionally_validates_length_of_using_within_on_update_utf8
785
+ kcode_scope('UTF8') do
786
+ Topic.validates_length_of :title, :content, :within => 5..10, :on => :update, :too_short => "短すぎます: %d"
787
+
788
+ t = Topic.create("title" => "一二三4", "content" => "whatever")
789
+ assert !t.save
790
+ assert t.errors.on(:title)
791
+
792
+ t.title = "1二三4"
793
+ assert !t.save
794
+ assert t.errors.on(:title)
795
+ assert_equal "短すぎます: 5", t.errors[:title]
796
+
797
+ t.title = "valid"
798
+ t.content = "一二三四五六七八九十A"
799
+ assert !t.save
800
+ assert t.errors.on(:content)
801
+
802
+ t.content = "一二345"
803
+ assert t.save
804
+ end
805
+ end
806
+
807
+ def test_validates_length_of_using_is_utf8
808
+ kcode_scope('UTF8') do
809
+ Topic.validates_length_of :title, :is => 5
810
+
811
+ t = Topic.create("title" => "一二345", "content" => "whatever")
812
+ assert t.valid?
813
+
814
+ t.title = "一二345六"
815
+ assert !t.valid?
816
+ assert t.errors.on(:title)
817
+ assert_equal "is the wrong length (should be 5 characters)", t.errors["title"]
818
+ end
819
+ end
820
+
821
+ def test_validates_size_of_association_utf8
822
+ kcode_scope('UTF8') do
823
+ assert_nothing_raised { Topic.validates_size_of :replies, :minimum => 1 }
824
+ t = Topic.new('title' => 'あいうえお', 'content' => 'かきくけこ')
825
+ assert !t.save
826
+ assert t.errors.on(:replies)
827
+ t.replies.create('title' => 'あいうえお', 'content' => 'かきくけこ')
828
+ assert t.valid?
829
+ end
830
+ end
831
+
832
+ def test_validates_associated_many
833
+ Topic.validates_associated( :replies )
834
+ t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
835
+ t.replies << [r = Reply.create("title" => "A reply"), r2 = Reply.create("title" => "Another reply")]
836
+ assert !t.valid?
837
+ assert t.errors.on(:replies)
838
+ assert_equal 1, r.errors.count # make sure all associated objects have been validated
839
+ assert_equal 1, r2.errors.count
840
+ r.content = r2.content = "non-empty"
841
+ assert t.valid?
842
+ end
843
+
844
+ def test_validates_associated_one
845
+ Reply.validates_associated( :topic )
846
+ Topic.validates_presence_of( :content )
847
+ r = Reply.create("title" => "A reply", "content" => "with content!")
848
+ r.topic = Topic.create("title" => "uhohuhoh")
849
+ assert !r.valid?
850
+ assert r.errors.on(:topic)
851
+ r.topic.content = "non-empty"
852
+ assert r.valid?
853
+ end
854
+
855
+ def test_validate_block
856
+ Topic.validate { |topic| topic.errors.add("title", "will never be valid") }
857
+ t = Topic.create("title" => "Title", "content" => "whatever")
858
+ assert !t.valid?
859
+ assert t.errors.on(:title)
860
+ assert_equal "will never be valid", t.errors["title"]
861
+ end
862
+
863
+ def test_invalid_validator
864
+ Topic.validate 3
865
+ assert_raise(ActiveRecord::ActiveRecordError) { t = Topic.create }
866
+ end
867
+
868
+ def test_throw_away_typing
869
+ d = Developer.new("name" => "David", "salary" => "100,000")
870
+ assert !d.valid?
871
+ assert_equal 100, d.salary
872
+ assert_equal "100,000", d.salary_before_type_cast
873
+ end
874
+
875
+ def test_validates_acceptance_of_with_custom_error_using_quotes
876
+ Developer.validates_acceptance_of :salary, :message=> "This string contains 'single' and \"double\" quotes"
877
+ d = Developer.new
878
+ d.salary = "0"
879
+ assert !d.valid?
880
+ assert_equal d.errors.on(:salary).first, "This string contains 'single' and \"double\" quotes"
881
+ end
882
+
883
+ def test_validates_confirmation_of_with_custom_error_using_quotes
884
+ Developer.validates_confirmation_of :name, :message=> "confirm 'single' and \"double\" quotes"
885
+ d = Developer.new
886
+ d.name = "John"
887
+ d.name_confirmation = "Johnny"
888
+ assert !d.valid?
889
+ assert_equal "confirm 'single' and \"double\" quotes", d.errors.on(:name)
890
+ end
891
+
892
+ def test_validates_format_of_with_custom_error_using_quotes
893
+ Developer.validates_format_of :name, :with => /^(A-Z*)$/, :message=> "format 'single' and \"double\" quotes"
894
+ d = Developer.new
895
+ d.name = d.name_confirmation = "John 32"
896
+ assert !d.valid?
897
+ assert_equal "format 'single' and \"double\" quotes", d.errors.on(:name)
898
+ end
899
+
900
+ def test_validates_inclusion_of_with_custom_error_using_quotes
901
+ Developer.validates_inclusion_of :salary, :in => 1000..80000, :message=> "This string contains 'single' and \"double\" quotes"
902
+ d = Developer.new
903
+ d.salary = "90,000"
904
+ assert !d.valid?
905
+ assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:salary).first
906
+ end
907
+
908
+ def test_validates_length_of_with_custom_too_long_using_quotes
909
+ Developer.validates_length_of :name, :maximum => 4, :too_long=> "This string contains 'single' and \"double\" quotes"
910
+ d = Developer.new
911
+ d.name = "Jeffrey"
912
+ assert !d.valid?
913
+ assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).first
914
+ end
915
+
916
+ def test_validates_length_of_with_custom_too_short_using_quotes
917
+ Developer.validates_length_of :name, :minimum => 4, :too_short=> "This string contains 'single' and \"double\" quotes"
918
+ d = Developer.new
919
+ d.name = "Joe"
920
+ assert !d.valid?
921
+ assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).first
922
+ end
923
+
924
+ def test_validates_length_of_with_custom_message_using_quotes
925
+ Developer.validates_length_of :name, :minimum => 4, :message=> "This string contains 'single' and \"double\" quotes"
926
+ d = Developer.new
927
+ d.name = "Joe"
928
+ assert !d.valid?
929
+ assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).first
930
+ end
931
+
932
+ def test_validates_presence_of_with_custom_message_using_quotes
933
+ Developer.validates_presence_of :non_existent, :message=> "This string contains 'single' and \"double\" quotes"
934
+ d = Developer.new
935
+ d.name = "Joe"
936
+ assert !d.valid?
937
+ assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:non_existent)
938
+ end
939
+
940
+ def test_validates_uniqueness_of_with_custom_message_using_quotes
941
+ Developer.validates_uniqueness_of :name, :message=> "This string contains 'single' and \"double\" quotes"
942
+ d = Developer.new
943
+ d.name = "David"
944
+ assert !d.valid?
945
+ assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).first
946
+ end
947
+
948
+ def test_validates_associated_with_custom_message_using_quotes
949
+ Reply.validates_associated :topic, :message=> "This string contains 'single' and \"double\" quotes"
950
+ Topic.validates_presence_of :content
951
+ r = Reply.create("title" => "A reply", "content" => "with content!")
952
+ r.topic = Topic.create("title" => "uhohuhoh")
953
+ assert !r.valid?
954
+ assert_equal "This string contains 'single' and \"double\" quotes", r.errors.on(:topic).first
955
+ end
956
+
957
+ def test_conditional_validation_using_method_true
958
+ # When the method returns true
959
+ Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", :if => :condition_is_true )
960
+ t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
961
+ assert !t.valid?
962
+ assert t.errors.on(:title)
963
+ assert_equal "hoo 5", t.errors["title"]
964
+ end
965
+
966
+ def test_conditional_validation_using_method_false
967
+ # When the method returns false
968
+ Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", :if => :condition_is_true_but_its_not )
969
+ t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
970
+ assert t.valid?
971
+ assert !t.errors.on(:title)
972
+ end
973
+
974
+ def test_conditional_validation_using_string_true
975
+ # When the evaluated string returns true
976
+ Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", :if => "a = 1; a == 1" )
977
+ t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
978
+ assert !t.valid?
979
+ assert t.errors.on(:title)
980
+ assert_equal "hoo 5", t.errors["title"]
981
+ end
982
+
983
+ def test_conditional_validation_using_string_false
984
+ # When the evaluated string returns false
985
+ Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", :if => "false")
986
+ t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
987
+ assert t.valid?
988
+ assert !t.errors.on(:title)
989
+ end
990
+
991
+ def test_conditional_validation_using_block_true
992
+ # When the block returns true
993
+ Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d",
994
+ :if => Proc.new { |r| r.content.size > 4 } )
995
+ t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
996
+ assert !t.valid?
997
+ assert t.errors.on(:title)
998
+ assert_equal "hoo 5", t.errors["title"]
999
+ end
1000
+
1001
+ def test_conditional_validation_using_block_false
1002
+ # When the block returns false
1003
+ Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d",
1004
+ :if => Proc.new { |r| r.title != "uhohuhoh"} )
1005
+ t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
1006
+ assert t.valid?
1007
+ assert !t.errors.on(:title)
1008
+ end
1009
+
1010
+ def test_validates_associated_missing
1011
+ Reply.validates_presence_of(:topic)
1012
+ r = Reply.create("title" => "A reply", "content" => "with content!")
1013
+ assert !r.valid?
1014
+ assert r.errors.on(:topic)
1015
+
1016
+ r.topic = Topic.find :first
1017
+ assert r.valid?
1018
+ end
1019
+
1020
+ def test_errors_to_xml
1021
+ r = Reply.new :title => "Wrong Create"
1022
+ assert !r.valid?
1023
+ xml = r.errors.to_xml(:skip_instruct => true)
1024
+ assert_equal "<errors>", xml.first(8)
1025
+ assert xml.include?("<error>Title is Wrong Create</error>")
1026
+ assert xml.include?("<error>Content Empty</error>")
1027
+ end
1028
+ end
1029
+
1030
+
1031
+ class ValidatesNumericalityTest < Test::Unit::TestCase
1032
+ NIL = [nil]
1033
+ BLANK = ["", " ", " \t \r \n"]
1034
+ BIGDECIMAL_STRINGS = %w(12345678901234567890.1234567890) # 30 significent digits
1035
+ FLOAT_STRINGS = %w(0.0 +0.0 -0.0 10.0 10.5 -10.5 -0.0001 -090.1 90.1e1 -90.1e5 -90.1e-5 90e-5)
1036
+ INTEGER_STRINGS = %w(0 +0 -0 10 +10 -10 0090 -090)
1037
+ FLOATS = [0.0, 10.0, 10.5, -10.5, -0.0001] + FLOAT_STRINGS
1038
+ INTEGERS = [0, 10, -10] + INTEGER_STRINGS
1039
+ BIGDECIMAL = BIGDECIMAL_STRINGS.collect! { |bd| BigDecimal.new(bd) }
1040
+ JUNK = ["not a number", "42 not a number", "0xdeadbeef", "00-1", "--3", "+-3", "+3-1", "-+019.0", "12.12.13.12", "123\nnot a number"]
1041
+
1042
+ def setup
1043
+ Topic.write_inheritable_attribute(:validate, nil)
1044
+ Topic.write_inheritable_attribute(:validate_on_create, nil)
1045
+ Topic.write_inheritable_attribute(:validate_on_update, nil)
1046
+ end
1047
+
1048
+ def test_default_validates_numericality_of
1049
+ Topic.validates_numericality_of :approved
1050
+
1051
+ invalid!(NIL + BLANK + JUNK)
1052
+ valid!(FLOATS + INTEGERS + BIGDECIMAL)
1053
+ end
1054
+
1055
+ def test_validates_numericality_of_with_nil_allowed
1056
+ Topic.validates_numericality_of :approved, :allow_nil => true
1057
+
1058
+ invalid!(BLANK + JUNK)
1059
+ valid!(NIL + FLOATS + INTEGERS + BIGDECIMAL)
1060
+ end
1061
+
1062
+ def test_validates_numericality_of_with_integer_only
1063
+ Topic.validates_numericality_of :approved, :only_integer => true
1064
+
1065
+ invalid!(NIL + BLANK + JUNK + FLOATS + BIGDECIMAL)
1066
+ valid!(INTEGERS)
1067
+ end
1068
+
1069
+ def test_validates_numericality_of_with_integer_only_and_nil_allowed
1070
+ Topic.validates_numericality_of :approved, :only_integer => true, :allow_nil => true
1071
+
1072
+ invalid!(BLANK + JUNK + FLOATS + BIGDECIMAL)
1073
+ valid!(NIL + INTEGERS)
1074
+ end
1075
+
1076
+ private
1077
+ def invalid!(values)
1078
+ with_each_topic_approved_value(values) do |topic, value|
1079
+ assert !topic.valid?, "#{value.inspect} not rejected as a number"
1080
+ assert topic.errors.on(:approved)
1081
+ end
1082
+ end
1083
+
1084
+ def valid!(values)
1085
+ with_each_topic_approved_value(values) do |topic, value|
1086
+ assert topic.valid?, "#{value.inspect} not accepted as a number"
1087
+ end
1088
+ end
1089
+
1090
+ def with_each_topic_approved_value(values)
1091
+ topic = Topic.new("title" => "numeric test", "content" => "whatever")
1092
+ values.each do |value|
1093
+ topic.approved = value
1094
+ yield topic, value
1095
+ end
1096
+ end
1097
+ end