2009-11-26 107 views
0

我在与验证我的回报率模型的一个问题:ActiveRecord的自定义验证问题

 
def save 
    self.accessed = Time.now.to_s 
    self.modified = accessed 
    validate_username 
    super 
end 
 
def validate_username 
    if User.find(:first, :select => :id, :conditions => ["userid = '#{self.userid}'"]) 
    self.errors.add(:userid, "already exists") 
    end 
end 

正如你所看到的,我把它换成了型号的保存方法,用我自己的,主叫validate_username前我称之为父级.save方法。我的问题是,即使添加了错误,Rails仍会尝试将新行插入到数据库中,即使用户名是重复的。我在这里做错了什么?

PS:我没有使用validate_uniqueness_of因为区分大小写以下问题:https://rails.lighthouseapp.com/projects/8994/tickets/2503-validates_uniqueness_of-is-horribly-inefficient-in-mysql

更新:我试过weppos解决方案,它的工作原理,但并不像我想它。现在,该字段被标记为不正确,但前提是所有其他字段都是正确的。我的意思是,如果我输入了一个错误的电子邮件地址,例如,电子邮件字段被标记为有问题,但用户ID字段不是。当我提交正确的电子邮件地址时,用户标识字段被标记为不正确。希望你们明白我的意思:d

UPDATE2:数据应在某种程度上得到验证,它不应该是可以插入用户ID重复到数据库中,不区分大小写。用户ID具有格式“用户域”,例如。 “test-something.net”。不幸的是,validates_uniqueness_of :userid不起作用,它会尝试将“test-something.net”插入到数据库中,即使已经存在“Test-something.net”。 validate_username应该是我对此问题的(快速)解决方法,但它不起作用。 weppos解决方案确实奏效,但并不像我想要的那样(正如我的第一次更新中所解释的)。

还没有想出这个呢......任何人?

最好的问候, x3ro

+0

你可以提供更多关于如何验证数据的细节吗? – 2009-11-27 15:50:02

回答

5

为什么不使用回调并保持save方法不变? 另外,避免直接的SQL值插值。

class ... < ActiveRecord::Base 

    before_save :set_defaults 
    before_create :validate_username 

    protected 

    def set_defaults 
    self.accessed = Time.now.to_s 
    self.modified = accessed 
    end 

    def validate_username 
    errors.add(:userid, "already exists") if User.exists?(:userid => self.userid) 
    errors.empty? 
    end 

end 
+0

before_create而不是before_save。否则validate_username将在所有保存中失败。否则很好的答案。 – EmFi 2009-11-26 18:24:47

+0

好点的EmFi! – 2009-11-27 11:45:29

0

如何调用超级只有validate_username返回true或类似的东西?

 
def save 
    self.accessed = Time.now.to_s 
    self.modified = accessed 
    super if validate_username 
end 
 
def validate_username 
    if User.find(:first, :select => :id, :conditions => ["userid = '#{self.userid}'"]) 
    self.errors.add(:userid, "already exists") 
    return false 
    end 
end 

......我想,你也可以完全删除超级调用。不确定,但你可以测试一下。