validates_acceptance_of deep failure ?
Reported by jerome (at yayel) | June 22nd, 2008 @ 06:13 PM
Hi
It looks like validates_acceptance_of doesn't work wether it uses a db column or just a regular instance attribute.
$ rails test ; cd test
$ ./script/generate model User name:string terms_of_service:boolean
$ ./script/generate model Person name:string
$ rake db:migrate
class User < ActiveRecord::Base
validates_acceptance_of :terms_of_service
end
class Person < ActiveRecord::Base
attr_accessor :terms_of_service
validates_acceptance_of :terms_of_service
end
class UserTest < ActiveSupport::TestCase
def test_new_user_be_valid_since_boolean_is_nil
assert_valid User.new(:name => "Mister New")
end
def test_nice_user_should_be_valid
assert_valid User.new(:name => "Mister Yes", :terms_of_service => true)
end
def test_bad_user_should_not_be_valid
user = User.create(:name => "Mister No", :terms_of_service => false)
assert_equal user.errors.on(:terms_of_service), "must be accepted"
end
end
class PersonTest < ActiveSupport::TestCase
def test_new_person_be_valid_since_boolean_is_nil
assert_valid Person.new(:name => "Mister New")
end
def test_nice_person_should_be_valid
assert_valid Person.new(:name => "Mister Yes", :terms_of_service => true)
end
def test_bad_person_should_not_be_valid
person = Person.create(:name => "Mister No", :terms_of_service => false)
assert_equal person.errors.on(:terms_of_service), "must be accepted"
end
end
$ rake
(in /Users/jerome/tmp/test)
/opt/local/bin/ruby -Ilib:test "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader.rb" "test/unit/person_test.rb" "test/unit/user_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader
Started
..F..F
Finished in 0.327487 seconds.
1) Failure:
test_nice_person_should_be_valid(PersonTest)
[./test/unit/person_test.rb:9:in `test_nice_person_should_be_valid'
/opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/testing/setup_and_teardown.rb:33:in `__send__'
/opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/testing/setup_and_teardown.rb:33:in `run']:
Terms of service must be accepted.
<false> is not true.
2) Failure:
test_nice_user_should_be_valid(UserTest)
[./test/unit/user_test.rb:9:in `test_nice_user_should_be_valid'
/opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/testing/setup_and_teardown.rb:33:in `__send__'
/opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/testing/setup_and_teardown.rb:33:in `run']:
Terms of service must be accepted.
<false> is not true.
6 tests, 6 assertions, 2 failures, 0 errors
/opt/local/bin/ruby -Ilib:test "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader.rb"
/opt/local/bin/ruby -Ilib:test "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader.rb"
Comments and changes to this ticket
-
MatthewRudy June 22nd, 2008 @ 06:34 PM
I think this is because validates_acceptance_of has a default of :allow_nil => true,
def validates_acceptance_of(*attr_names) configuration = { :message => ActiveRecord::Errors.default_error_messages[:accepted], :on => :save, :allow_nil => true, :accept => "1" } configuration.update(attr_names.extract_options!) db_cols = begin column_names rescue ActiveRecord::StatementInvalid [] end names = attr_names.reject { |name| db_cols.include?(name.to_s) } attr_accessor(*names) validates_each(attr_names,configuration) do |record, attr_name, value| record.errors.add(attr_name, configuration[:message]) unless value == configuration[:accept] end endbut it does seem to default to only accept "1" as a valid value...
should probably be "1" or true?
def validates_acceptance_of(*attr_names) configuration = { :message => ActiveRecord::Errors.default_error_messages[:accepted], :on => :save, :allow_nil => true, :accept => ["1", true] } configuration.update(attr_names.extract_options!) db_cols = begin column_names rescue ActiveRecord::StatementInvalid [] end names = attr_names.reject { |name| db_cols.include?(name.to_s) } attr_accessor(*names) validates_each(attr_names,configuration) do |record, attr_name, value| record.errors.add(attr_name, configuration[:message]) unless safe_to_array(configuration[:accept]).include?(value) end endperhaps that works better?
-

jerome (at yayel) June 22nd, 2008 @ 07:20 PM
but the documentation says:
:accept - Specifies value that is considered accepted. The default value is a string "1", which makes it easy to relate to an HTML checkbox. This should be set to true if you are validating a database column, since the attribute is typecast from "1" to true before validation. -
-

-

jerome (at yayel) June 22nd, 2008 @ 08:39 PM
Ok so I misunderstanded the doc. The typecasting explanation was unclear for me. Setting :accept => true is a better option since it validates "1", 1 and true, while the default :accept => "1" only validates "1"...
What about changing this default value then ?
-
MatthewRudy June 22nd, 2008 @ 09:44 PM
well, that was my suggestion,
and what my code did was...
default to "1" or true
But, need to get a core team guy on here to decide what "should" be the default.
-
Lawrence Pit June 23rd, 2008 @ 12:40 AM
I brought this up last month on the core list. See
http://groups.google.com.au/grou...
It does work, though not as advertised. You do have to add a hidden checkbox with a default value.
-
Joshua Peek September 30th, 2008 @ 05:50 PM
- → Tag changed from to "2.1" activerecord bug validations
- → State changed from new to stale
Please Login or create a free account to add a new comment.
You can update this ticket by sending an email to from your email client. (help)
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
Source available from github
The Git repository resides at http://github.com/rails
Check out the current development trunk (Edge Rails) with:
git clone git://github.com/rails/rails.git
Creating or reviewing a patch
See the contributor guide.
Creating a feature request
Please don't. If you want a new feature in Rails, you'll have to pull up your sleeves and get busy yourself. Or convince someone else to do it. See the contributor guide on how to get going. But posting them here is just going to lead to ticket root.
Creating a bug report
When creating a bug report, be sure to include as much relevant information as possible. Post the code sample that causes the problem. Preferably, alter the unit tests and show through either changed or added tests how the expected behavior is not occuring.
Security vulnerabilities should be reported via an email to security@rubyonrails.org, do not use trac for reporting security vulnerabilities. All content in trac is publicly available as soon as it is posted.
Then don't get your hopes up. Unless you have a "Code Red, Mission Critical, The World is Coming to an End" kinda bug, you're creating this ticket in the hope that others with the same problem will be able to collaborate with you on solving it. Do not expect that the ticket automatically will see any activity or that others will jump to fix it. Creating a ticket like this is mostly to help yourself start on the path of fixing the problem and for others to sign on to with a "I'm having this problem too".
