문제

I have a class:

class Validator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless valid?(value)
      record.errors.add(attribute, attribute.to_sym, options.merge(value: value))
    end
  end
end

And I have a huge amount of subclasses(with just private valid? method), i.e

class KppValidator < Validator
  private

  def valid?(kpp)
    kpp.size == 9
  end
end

Is there any way to avoid writing private before each valid? method in descendant classes?

I tried to write 'private :valid?', in class Validator, but got an exception no such method 'valid?'

What I can do?

도움이 되었습니까?

해결책

I think your whole approach is a bit odd in the Ruby context. A more Rubyish and Railsy approach would be to write a macro and then use a block in your subclasses rather than a private method.

Something like this:

class Validator < ActiveModel::EachValidator
  def self.validate_using(&block)
    define_method :validate_each do |record, attribute, value|
      unless block[value]
        record.errors.add(attribute, attribute.to_sym, options.merge(value: value))
      end
    end
  end
end

class KppValidator < Validator
  validate_using { |kpp| kpp.size == 9 }
end

Since this defines the whole validate_each method, this even saves you a method call during validation (at the minor expense of a bit of extra work while initializing everything).

I don't know if this is worthwhile for just ten validators, I'll leave that up to you.

다른 팁

Writing private on its own can be inconvenient if you want to shift back to public for subsequent methods. Instead you could try:

class KppValidator < Validator
  def valid?(kpp)
    kpp.size == 9
  end
  private :valid?
end

As of Ruby 2.1.0 def returns the method name as a symbol, so you can streamline this as:

class KppValidator < Validator
  private def valid?(kpp)
    kpp.size == 9
  end
end

But you're right, even if you were to define valid? as a private method in the base class, it will become public in the subclass when you redefine it unless you explicitly make it private.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top