ActiveRecord自定义验证问题

时间:2009-11-26 12:46:17

标签: ruby-on-rails validation activerecord

我在RoR模型中遇到验证问题:

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

正如您所看到的,我已经用自己的方法替换了Model的save方法,在调用父.save方法之前调用validate_username。我的问题是,即使添加了错误,Rails仍会尝试将新行插入数据库,即使用户名是重复的。我在这里做错了什么?

PS:由于区分大小写的以下问题,我没有使用validate_uniqueness_ofhttps://rails.lighthouseapp.com/projects/8994/tickets/2503-validates_uniqueness_of-is-horribly-inefficient-in-mysql

更新:我尝试了weppos解决方案,但它确实有效,但并不像我希望的那样。现在,该字段被标记为不正确,但仅当所有其他字段都正确时。我的意思是,如果我输入一个错误的电子邮件地址,例如,电子邮件字段标记为es faulty,userid字段不是。当我提交正确的电子邮件地址时,userid字段被标记为不正确。希望你们明白我的意思:D

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

还没想出来......有人吗?

祝你好运, x3ro

2 个答案:

答案 0 :(得分:5)

为什么不使用回调并保持保存方法不变? 另外,避免直接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

答案 1 :(得分:0)

如果validate_username返回true或类似的东西,那么如何调用super?

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

...我认为你也可以完全删除超级电话。不确定,但你可以测试一下。