A more elegant way to skip checks in Rails?

In my User model, I have the usual email suspects, first_name, last_name, password, etc.

I have several cases where I need to skip all or some of the checks.

I currently have a condition that looks something like this:

  validates :first_name, presence: :true, etc..., unless: :skip_first_name_validation?
  validates :last_name, presence: :true, etc..., unless: :skip_last_name_validation?
  validates :email, presence: :true, etc..., unless: :skip_email_validation?

Of course I also have:

  attr_accessor :skip_first_name_validation, :skip_last_name_validation, etc.

And then I use private methods to check the status of each of them:

  def skip_first_name_validation?
    skip_first_name_validation
  end

  def skip_last_name_validation?
    skip_last_name_validation
  end

  def skip_email_validation?
    skip_email_validation
  end

  etc..

From there, when I need to skip checks, I just assign each of these guys a value truein my controller.


So, while all this works great, I wonder if there is a more elegant way?

Ideally, it would be nice if I could use a simple conditional attribute for each attribute in my models:

:skip_validation?

And in my controllers just do something like:

skip_validation(:first_name, :last_name, :password) = true

- , ? gem/library, , . .

+5
2

private 
def self.skip_validations_for(*args)

  # this block dynamically defines a setter method 'set_validations' 
  # e.g.
  #   set_validations(true, :email, :last_name, :first_name)
  #   set_validations(false, :email, :last_name, :first_name)
  define_method('set_validations') do |value, *params|
    params.each do |var|
      self.send("skip_#{var.to_s}_validations=", value)
    end
  end

  # this block walks through the passed in fields and defines a checker
  # method `skip_[field_name]_validation?
  args.each do |arg|
    if self.method_defined? arg
      send :define_method, "skip_#{attr.to_s}_validation?" do 
        send "skip_#{attr.to_s}_validation"  
      end
    end
  end
end

, , , :

Class Foo < ActiveRecord::Base
  validate :bar, :presence => true
  validate :baz, :length_of => 10

  skip_validations_for :bar, :baz
end

set_validations(true, :bar, :baz)

skip_bar_validation? 

:

?

, . , . Module, , Module lib/ , . , .

?

_validations , ActiveRecord, ( → ActiveRecord:: Validation). . Rails'ish, .

+1

, , - .

class User < ActiveRecord::Base
  ...
  %w(email first_name last_name).each do |attr|
    self.send :attr_accessor, "skip_#{attr}_validation".to_sym
    self.send :alias, "skip_#{attr}_validation?".to_sym, "skip_#{attr}_validation".to_sym
    self.send :validates_presence_of, attr, { unless: "skip_#{attr}_validation?".to_sym }
  end

  def skip_validation_for(*attrs)
    attrs.map{|attr| send "skip_#{attr}_validation=", true }
  end
end

, , , - :

class User < ActiveRecord::Base
  include SkipValidations
  skip_validations :email, :first_name, :last_name
end
0

All Articles