代码之家  ›  专栏  ›  技术社区  ›  fresskoma

ActiveRecord自定义验证问题

  •  0
  • fresskoma  · 技术社区  · 15 年前

    我的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
    

    如您所见,我用自己的方法替换了模型的save方法,在调用parent.save方法之前调用validate_用户名。我的问题是,即使添加了错误,Rails仍然尝试将新行插入数据库,即使用户名是重复的。我在这里做错什么了?

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

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

    更新2:数据应该以一种方式进行验证,即不可能将重复的用户ID插入数据库,不区分大小写。用户ID的格式为“用户域”,例如“test something.net”。不幸的是, validates_uniqueness_of :userid 不起作用,它尝试将“test something.net”插入数据库,即使已经有“test something.net”了。验证用户名应该是我解决这个问题的(快速)解决方案,但它不起作用。WEPPOS解决方案确实有效,但并不像我希望的那样(正如我第一次更新中所解释的那样)。

    还没弄清楚…有人吗?

    最好的问候, X3RO

    2 回复  |  直到 15 年前
        1
  •  5
  •   EmFi    15 年前

    为什么不使用回调并保持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
    
        2
  •  0
  •   marcgg    15 年前

    如果validate_用户名返回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
    

    …我认为你也可以完全取消超级电话。不确定,但你可以测试一下。