Rails中ActiveRecord是一套强大的ORM工具,今天介绍一下在其中自定义一个校验的方法。
自定义validate方法
请思考这样一个问题,Rails中自带的Validations能满足你所有的要求么?
如果不能,你可能需要自定义一些 validate 的方法。
我在实际写代码的过程中遇到这样一个情况,是有一张表叫做configs,其中两个字段:user_id, device_id,不同同时和另外一条记录的这两个字段相同。也就是说,我不能 validate_uniqueness_of :user_id, :device_id
,因为这样只会单独检查user_id 和 device_id 是否有过重复,而不是检查是否同时重复。
所以我自定义了一个validate。代码大致如下:
# app/models/config.rb
validate :customed_validation, on: :create
def customed_validation
if self.class.find_by(user_id: user_id, device_id: device_id)
errors.add(:user_id, 'a customizable error message')
end
end
这段代码是什么意思呢?首先 在 create 的过程中加入 validate,这个validate叫做 customed_validation ,然后我们在下面定义这个 customed_validation
。
在 customed_validation
中,如果验证不通过,就往 errors 中加入一个自定义的报错信息。然后,当这个报错真的被加进来的时候,你就可以通过 self.errors
来打印这个错误信息。就像你 validates :title, presence: true
一样。如果没有title,前端会打印 title is blank 这样的错误。只不过这里打印的错误是你自己定义的。剩下的就跟你常用的 validation 们(比如 presence, numericality)一样了。
其他定义方法
当然,如果你没有用 ActiveRecord,就不能直接用这样的validation,需要mix in一个ActiveModel::Validation
的模块。这里不做更多说明(因为我也没有用过这种,哭哭),有需要的看这里。另外,我这里用的是自定义 validate 方法,你还可以自定义一个 validator (一种 ActiveModel::Validation
的子类),这样就你就可以到处引用这个validator了。
后话
我在这里想讨论的是谁在调用validate中自定义的方法。
就拿我刚才给出的示例代码为例,在这个方法中,self
是个 Config 的一个实例(但是这个对象没有存储到数据库中,是个刚刚初始化过的数据,一个证据是没有id。但他依然是一个Config实例化的对象)。所以在示例代码中的 errors
就相当于是 self.errors
。也从这里可以看出来,这是一个实例方法(请定义的格式来看也是实例方法),不是类方法。
另外,你把这个方法变成private的实例方法依然没有问题。然而,并不是所有的实例方法都能放在private中。这个实例方法能,是因为没有在外部调用。如果你想在外部调用,或者,哪怕在这个model内部,用self来调用都是有问题的。如果你用了(在外部用Config的实例调用,或者在内部用self调用),Rails都会抛出异常说private方法被调用。对于钱一种情况,好理解,private方法嘛,就当它顾名思义了,虽然具体怎么实现的我还不知道;但是后一种怎么回事呢,我将在以后的ActiveRecord的文章中讨论。
Recall
- 引入validate
- 定义validate的具体方法
validate :a_method, on: [:create]
private
def a_method
if something?
errors.add(:attribute, 'message')
end
end
网友评论