我要跳过父类的 validate 方法,执行子类自己的 validate 方法。 这个怎么做到?
validates_presence_of :name, if: -> { false }
类似这样传入一个 if 的 option 让里面永远等于 false 是不是就可以跳过校验了?
#2 楼 @rei #4 楼 @bill_yang1016 我之前就是读取列表然后过滤,真心丑陋,但是没办法,因为是 gem 里边的代码声明了 validation,但是我又一定要跳过验证,也就只能霸王硬上弓了。
class Parent < ActiveRecord::Base
with_options if: :is_a_parent? do
validates :name, presence: true
validates :age, presence: true
end
def is_a_parent?
is_a?(Parent)
end
end
class Child < Parent
# do nothing
end
我没跑过,感觉应该可以
如果是跳过全部验证,用record.save(validate: false)
更简单
以及我也觉得你是不是某些地方没搞对,如果是某些验证在子类的行为不同,你可以把验证写成方法,然后在子类覆盖啊
结合 Github,整理了一份:
skip_validation.rb
module SkipValidation
extend ActiveSupport::Concern
module ClassMethods
def can_skip_validation_for(*args)
args.each do |attr|
send(:attr_accessor, "skip_#{attr}_validation")
send(:define_method, "skip_#{attr}_validation?") { send("skip_#{attr}_validation") }
end
end
end
def skip_validation_for(*args)
args.each { |attr| send("skip_#{attr}_validation=", true) }
end
end
user.rb
class User < AR
include SkipValidation
validates :mobile, uniqueness: true, unless: :skip_mobile_validation?
end
users_controller.rb
class UsersController < ApplicationController
def update
@user.skip_validation_for(:id_number, :mobile)
@user.save
end
end
另一条路:
将 B < A
改成 A < Base
,B < Base
,Base 没有校验。这样 A、B 逻辑是独立的,依然在同一个表。
如果需要共享方法,用 Concern(Module)。
如果 A,B 不需要在同一个表,只需要共享方法,那么不需要继承,只用 Concern(Module)。