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