我正在努力验证Ruby验证:确认=>在我的Rails应用程序中是真的。请考虑以下代码:
# == Schema Information
#
# Table name: things
#
# id :integer not null, primary key
# pin :integer(8)
# created_at :datetime
# updated_at :datetime
#
class Things < ActiveRecord::Base
#attr_accessor :pin
attr_accessible :pin, :pin_confirmation
validates :pin,
:confirmation => true,
:length => { :within => 7..15 },
:numericality => { :only_integer => true }
端
如上面的代码,我的验证在Rails控制台上运行良好:
1.9.3-p0 :002 > l2 = Thing.create! :pin => 1234567, :pin_confirmation => 1111111
ActiveRecord::RecordInvalid: Validation failed: Pin doesn't match confirmation
....
1.9.3-p0 :003 > l2 = Thing.create! :pin => 1234567, :pin_confirmation => 1234567
=> #<Thing id: 2, pin: 1234567, created_at: "2012-01-30 22:03:29", updated_at: "2012-01-30 22:03:29">
但是通过rspec和从rails服务器手动测试会导致验证失败,并说当它们做得不好时它们不匹配。如果我取消注释attr_accessor:pin,验证将通过但是:pin当然不会写入数据库。
我完全相信我错过了一些明显而重要的东西 - 只是撞到了一堵砖墙。
答案 0 :(得分:1)
就像Frederick上面所说,问题是将String的实例与Integer实例进行比较。
很可能,这是你控制器中的内容:
Thing.new(params[:thing]) # note all these params come in as a string
正在发生的事情是,由于#pin是一个整数列,您将获得以下行为:
my_thing = Thing.new
my_thing.pin = "123456"
my_thing.pin # Will be the integer 123456, the attribute has been auto-cast for you
但是因为#pin_confirmed只是一个常规属性,而不是一个整数列,所以你会看到这种奇怪之处:</ p>
my_thing = Thing.new
my_thing.pin_confirmation = "123456"
my_thing.pin_confirmation # Will be the *string* "123456", the attribute has been set as is
很自然,在这种情况下,无论你有什么价值,因为它们通过“params”哈希(总是一组字符串)进入,你最终会为两个属性分配字符串值,但是它们将被投射到不同的类型。
有几种方法可以解决这个问题。
一,您可以在数据库中创建#pin_confirmation作为整数列。
另一种是你可以为以下形式的#pin_confirmation添加属性设置器:
def pin_confirmation=(val)
@pin_confirmation = val.to_i
end