新手问题 子类中怎么跳过父类的 validate 方法

bill_yang1016 · 2015年06月27日 · 最后由 42thcoder 回复于 2015年06月29日 · 2824 次阅读

我要跳过父类的 validate 方法,执行子类自己的 validate 方法。 这个怎么做到?

重写子类的方法

印象中不好跳过,validate 是作为匿名方法放到一个列表里的,虽然是可以过滤出来,但是代码很丑陋。

父类有的校验子类不需要做,那么这个继承关系是否有问题呢?

#1 楼 @chaucerling 嗯,但是 validate 的方法好几个,这么改比较丑。。但是也没好办法。

#2 楼 @rei 嗯,你说到重点了。。。

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)更简单

以及我也觉得你是不是某些地方没搞对,如果是某些验证在子类的行为不同,你可以把验证写成方法,然后在子类覆盖啊

#7 楼 @lolychee 其它地方应该没问题,但是 child.is_a? parent = true

#8 楼 @kikyous 直接用.class 判断就好

结合 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 < BaseB < Base,Base 没有校验。这样 A、B 逻辑是独立的,依然在同一个表。 如果需要共享方法,用 Concern(Module)。 如果 A,B 不需要在同一个表,只需要共享方法,那么不需要继承,只用 Concern(Module)。

用 context 区分 validate 喽

需要 登录 后方可回复, 如果你还没有账号请 注册新账号