Here's an activerecord test that not passing:
## validations_test.rb -- activerecord [ruby]
def test_validates_length_of_using_maximum_utf8
with_kcode('UTF8') do
Topic.validates_length_of :title, :maximum => 5
t = Topic.create("title" => "一二三四五", "content" => "whatever")
assert t.valid?
t.title = "一二34五六"
assert !t.valid?
assert t.errors.on(:title)
assert_equal "is too long (maximum is 5 characters)", t.errors["title"]
end
end
## output
5) Failure:
test_validates_length_of_using_maximum_utf8(ValidationsTest)
[test/cases/validations_test.rb:1004:in `test_validates_length_of_using_maximum_utf8'
test/cases/validations_test.rb:1442:in `with_kcode'
test/cases/validations_test.rb:1000:in `test_validates_length_of_using_maximum_utf8'
./test/cases/../../../activesupport/lib/active_support/testing/setup_and_teardown.rb:57:in `run']:
<false> is not true.
The error happens on this statement: assert t.valid?
## ar_utf8.rb [ruby]
# this is a plain program that should duplicate the same error
# but it doesn't -- everything works correctly.
require 'rubygems'
require 'activerecord'
def with_kcode(kcode)
if RUBY_VERSION < '1.9'
orig_kcode, $KCODE = $KCODE, kcode
begin
yield
ensure
$KCODE = orig_kcode
end
else
yield
end
end
@logger = Logger.new $stderr
ActiveRecord::Base.logger = @logger
ActiveRecord::Base.colorize_logging = false
# GRANT ALL PRIVILEGES ON my_activerecord_test.* to 'rails'@'localhost';
pool = ActiveRecord::Base.establish_connection(
:adapter => RUBY_PLATFORM =~ /java/ ? 'jdbcmysql' : 'mysql',
:username => 'rails',
:encoding => 'utf8',
:database => 'my_activerecord_test'
)
ActiveRecord::Schema.define do
drop_table :posts if pool.connection.table_exists?(:posts)
create_table :posts do |t|
t.string :subject
t.text :body
end
end
class Post < ActiveRecord::Base
validates_length_of :subject, :maximum => 5
end
with_kcode('UTF8') do
p1 = Post.create(:subject => "一二三四五", :body => 'this is the body')
len1 = p1.subject.length
len2 = p1.subject.mb_chars.length
puts "length: #{len1}, #{len2}"
puts p1.valid?
puts p1.errors.on(:subject)
p2 = Post.find(:first)
p2.subject = "一二34五六"
puts p2.valid?
puts p2.errors.on(:subject)
end
## output
$ jruby ar_utf8.rb
SQL (1.3ms) SET SQL_AUTO_IS_NULL=0
-- drop_table(:posts)
SQL (2.5ms) DROP TABLE `posts`
-> 0.0037s
-> 0 rows
-- create_table(:posts)
SQL (2.2ms) CREATE TABLE `posts` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `subject` varchar(255), `body` text) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin
-> 0.0072s
-> 0 rows
SQL (2.1ms) INSERT INTO `posts` (`subject`, `body`) VALUES('一二三四五', 'this is the body')
length: 15, 5
true
nil
Post Load (1.6ms) SELECT * FROM `posts` LIMIT 1
false
is too long (maximum is 5 characters)