How to remove validation using instance_eval clause in Rails?

后端 未结 18 1829
情话喂你
情话喂你 2021-02-01 02:11

I would like to enhance existing class using instance_eval. There original definition contains validation, which require presence of certain fields, ie:

class Du         


        
相关标签:
18条回答
  • 2021-02-01 02:38

    I found a solution, not sure how solid it is, but it works well in my case. @aVenger was actually close with his answer. It's just that the _validators accessor contains only information used for reflection, but not the actual validator callbacks! They are contained in the _validate_callbacks accessor, not to be confused with _validations_callbacks.

    Dummy.class_eval do
      _validators.reject!{ |key, _| key == :field }
    
      _validate_callbacks.reject! do |callback|
        callback.raw_filter.attributes == [:field]
      end
    end
    

    This will remove all validators for :field. If you want to be more precise, you can reject the specific validator for _validators which is the same as the raw_filter accessor of validate callbacks.

    0 讨论(0)
  • If you can edit the constraint on the original model to put an :if => :some_function on it, you can easily change the behavior of the function it calls to return false. I tested this and it works pretty easily:

    class Foo < ActiveRecord::Base
    
      validates :field, :presence => true, :if => :stuff
    
    
      attr_accessor :field
    
      def stuff
          return true;
      end
    
    end
    

    and then somewhere else:

    Foo.class_eval {
      def stuff
        false
      end
    }
    
    0 讨论(0)
  • 2021-02-01 02:40

    As I was trying to do this to remove the phone validation from the spree Address model, below is the code I got to work. I added the type check for callback.raw_filter because I only wanted to remove the presence validator on the phone field. I also had to add it because it would fail when trying to run against one of the other validators specified in the Spree::Address model that did not have an 'attributes' key for callback.raw_filter, thus an exception was thrown.

    Spree::Address.class_eval do
    
       # Remove the requirement on :phone being present.
      _validators.reject!{ |key, _| key == :phone }
    
      _validate_callbacks.each do |callback|
        callback.raw_filter.attributes.delete :phone if callback.raw_filter.is_a?(ActiveModel::Validations::PresenceValidator)
      end
    
    end
    
    0 讨论(0)
  • 2021-02-01 02:44

    Why not use @dummy.save_without_validation method to skip validations altogether? I prefer do something like this:

    if @dummy.valid?
      @dummy.save # no problem saving a valid record
    else
      if @dummy.errors.size == 1 and @dummy.errors.on(:field)
        # skip validations b/c we have exactly one error and it is the validation that we want to skip
        @dummy.save_without_validation 
      end
    end
    

    You could put this code in your model or in the controller, depending on your needs.

    0 讨论(0)
  • 2021-02-01 02:45

    If you really want to do this then here would be a good place to start digging: https://github.com/rails/rails/blob/ed7614aa7de2eaeba16c9af11cf09b4fd7ed6819/activemodel/lib/active_model/validations/validates.rb#L82

    However, to be honest, inside of ActiveModel is not where I'd be poking with a stick.

    0 讨论(0)
  • 2021-02-01 02:50

    I had a similar problem and was able to get past it using:

    class MyModel << Dummy
      # erase the validations defined in the plugin/gem because they interfere with our own
      Dummy.reset_callbacks(:validate)
      ...
    end
    

    This is under Rails 3.0. The caveat: It does remove ALL validations, so if there are others you want to keep you could try Dummy.skip_callback(...), but I could not figure out the right incantation of arguments to make that work.

    0 讨论(0)
提交回复
热议问题