Fixed validates_length_of to work on UTF-8 strings by using characters instead...

Fixed validates_length_of to work on UTF-8 strings by using characters instead of bytes (closes #3699) [Masao Mutoh]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3654 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
上级 ad9f678d
*SVN*
* Fixed validates_length_of to work on UTF-8 strings by using characters instead of bytes #3699 [Masao Mutoh]
* Fixed that reflections would bleed across class boundaries in single-table inheritance setups #3796 [lars@pind.com]
* Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Base.maxmium, and the generic Base.calculate. All can be used with :group and :having. Calculations and statitics need no longer require custom SQL. #3958 [Rick Olson]. Examples:
......
......@@ -439,31 +439,35 @@ def validates_length_of(*attrs)
option_value = options[range_options.first]
case option
when :within, :in
raise ArgumentError, ":#{option} must be a Range" unless option_value.is_a?(Range)
too_short = options[:too_short] % option_value.begin
too_long = options[:too_long] % option_value.end
validates_each(attrs, options) do |record, attr, value|
if value.nil? or value.size < option_value.begin
record.errors.add(attr, too_short)
elsif value.size > option_value.end
record.errors.add(attr, too_long)
when :within, :in
raise ArgumentError, ":#{option} must be a Range" unless option_value.is_a?(Range)
too_short = options[:too_short] % option_value.begin
too_long = options[:too_long] % option_value.end
validates_each(attrs, options) do |record, attr, value|
if value.nil? or value.split(//).size < option_value.begin
record.errors.add(attr, too_short)
elsif value.split(//).size > option_value.end
record.errors.add(attr, too_long)
end
end
end
when :is, :minimum, :maximum
raise ArgumentError, ":#{option} must be a nonnegative Integer" unless option_value.is_a?(Integer) and option_value >= 0
when :is, :minimum, :maximum
raise ArgumentError, ":#{option} must be a nonnegative Integer" unless option_value.is_a?(Integer) and option_value >= 0
# Declare different validations per option.
validity_checks = { :is => "==", :minimum => ">=", :maximum => "<=" }
message_options = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long }
# Declare different validations per option.
validity_checks = { :is => "==", :minimum => ">=", :maximum => "<=" }
message_options = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long }
message = (options[:message] || options[message_options[option]]) % option_value
message = (options[:message] || options[message_options[option]]) % option_value
validates_each(attrs, options) do |record, attr, value|
record.errors.add(attr, message) unless !value.nil? and value.size.method(validity_checks[option])[option_value]
end
validates_each(attrs, options) do |record, attr, value|
if value.kind_of?(String)
record.errors.add(attr, message) unless !value.nil? and value.split(//).size.method(validity_checks[option])[option_value]
else
record.errors.add(attr, message) unless !value.nil? and value.size.method(validity_checks[option])[option_value]
end
end
end
end
......
......@@ -10,6 +10,7 @@
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:username => "rails",
:encoding => "utf8",
:database => db1
)
......
......@@ -614,6 +614,141 @@ def test_validates_length_of_custom_errors_for_is_with_wrong_length
assert_equal "hoo 5", t.errors["title"]
end
def kcode_scope(kcode)
orig_kcode = $KCODE
$KCODE = kcode
begin
yield
ensure
$KCODE = orig_kcode
end
end
def test_validates_length_of_using_minimum_utf8
kcode_scope('UTF8') do
Topic.validates_length_of :title, :minimum => 5
t = Topic.create("title" => "一二三四五", "content" => "whatever")
assert t.valid?
t.title = "一二三四"
assert !t.valid?
assert t.errors.on(:title)
assert_equal "is too short (min is 5 characters)", t.errors["title"]
end
end
def test_validates_length_of_using_maximum_utf8
kcode_scope('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 (max is 5 characters)", t.errors["title"]
end
end
def test_validates_length_of_using_within_utf8
kcode_scope('UTF8') do
Topic.validates_length_of(:title, :content, :within => 3..5)
t = Topic.new("title" => "一二", "content" => "12三四五六七")
assert !t.valid?
assert_equal "is too short (min is 3 characters)", t.errors.on(:title)
assert_equal "is too long (max is 5 characters)", t.errors.on(:content)
t.title = "一二三"
t.content = "12三"
assert t.valid?
end
end
def test_optionally_validates_length_of_using_within_utf8
kcode_scope('UTF8') do
Topic.validates_length_of :title, :content, :within => 3..5, :allow_nil => true
t = Topic.create('title' => '一二三', 'content' => '一二三四五')
assert t.valid?
t.title = nil
assert t.valid?
end
end
def test_optionally_validates_length_of_using_within_on_create_utf8
kcode_scope('UTF8') do
Topic.validates_length_of :title, :content, :within => 5..10, :on => :create, :too_long => "長すぎます: %d"
t = Topic.create("title" => "一二三四五六七八九十A", "content" => "whatever")
assert !t.save
assert t.errors.on(:title)
assert_equal "長すぎます: 10", t.errors[:title]
t.title = "一二三四五六七八九"
assert t.save
t.title = "一二3"
assert t.save
t.content = "一二三四五六七八九十"
assert t.save
t.content = t.title = "一二三四五六"
assert t.save
end
end
def test_optionally_validates_length_of_using_within_on_update_utf8
kcode_scope('UTF8') do
Topic.validates_length_of :title, :content, :within => 5..10, :on => :update, :too_short => "短すぎます: %d"
t = Topic.create("title" => "一二三4", "content" => "whatever")
assert !t.save
assert t.errors.on(:title)
t.title = "1二三4"
assert !t.save
assert t.errors.on(:title)
assert_equal "短すぎます: 5", t.errors[:title]
t.title = "valid"
t.content = "一二三四五六七八九十A"
assert !t.save
assert t.errors.on(:content)
t.content = "一二345"
assert t.save
end
end
def test_validates_length_of_using_is_utf8
kcode_scope('UTF8') do
Topic.validates_length_of :title, :is => 5
t = Topic.create("title" => "一二345", "content" => "whatever")
assert t.valid?
t.title = "一二345六"
assert !t.valid?
assert t.errors.on(:title)
assert_equal "is the wrong length (should be 5 characters)", t.errors["title"]
end
end
def test_validates_size_of_association_utf8
kcode_scope('UTF8') do
assert_nothing_raised { Topic.validates_size_of :replies, :minimum => 1 }
t = Topic.new('title' => 'あいうえお', 'content' => 'かきくけこ')
assert !t.save
assert t.errors.on(:replies)
t.replies.create('title' => 'あいうえお', 'content' => 'かきくけこ')
assert t.valid?
end
end
def test_validates_associated_many
Topic.validates_associated( :replies )
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册