Class: ActiveRecord::Import::Validator

Inherits:
Object
  • Object
show all
Defined in:
lib/activerecord-import/import.rb

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Validator

Returns a new instance of Validator.



27
28
29
# File 'lib/activerecord-import/import.rb', line 27

def initialize(options = {})
  @options = options
end

Instance Method Details

#valid_model?(model) ⇒ Boolean

Returns:

  • (Boolean)


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/activerecord-import/import.rb', line 31

def valid_model?(model)
  validation_context = @options[:validate_with_context]
  validation_context ||= (model.new_record? ? :create : :update)

  current_context = model.send(:validation_context)
  begin
    model.send(:validation_context=, validation_context)
    model.errors.clear

    validate_callbacks = model._validate_callbacks.dup
    associations = model.class.reflect_on_all_associations(:belongs_to).map(&:name)

    model._validate_callbacks.each do |callback|
      filter = callback.raw_filter
      if filter.is_a?(ActiveRecord::Validations::UniquenessValidator) ||
         (defined?(ActiveRecord::Validations::PresenceValidator) && filter.is_a?(ActiveRecord::Validations::PresenceValidator) && associations.include?(filter.attributes.first))
        validate_callbacks.delete(callback)
      end
    end

    model.run_callbacks(:validation) do
      if defined?(ActiveSupport::Callbacks::Filters::Environment) # ActiveRecord >= 4.1
        runner = validate_callbacks.compile
        env = ActiveSupport::Callbacks::Filters::Environment.new(model, false, nil)
        if runner.respond_to?(:call) # ActiveRecord < 5.1
          runner.call(env)
        else # ActiveRecord 5.1
          # Note that this is a gross simplification of ActiveSupport::Callbacks#run_callbacks.
          # It's technically possible for there to exist an "around" callback in the
          # :validate chain, but this would be an aberration, since Rails doesn't define
          # "around_validate". Still, rather than silently ignoring such callbacks, we
          # explicitly raise a RuntimeError, since activerecord-import was asked to perform
          # validations and it's unable to do so.
          #
          # The alternative here would be to copy-and-paste the bulk of the
          # ActiveSupport::Callbacks#run_callbacks method, which is undesirable if there's
          # no real-world use case for it.
          raise "The :validate callback chain contains an 'around' callback, which is unsupported" unless runner.final?
          runner.invoke_before(env)
          runner.invoke_after(env)
        end
      elsif validate_callbacks.method(:compile).arity == 0 # ActiveRecord = 4.0
        model.instance_eval validate_callbacks.compile
      else # ActiveRecord 3.x
        model.instance_eval validate_callbacks.compile(nil, model)
      end
    end

    model.errors.empty?
  ensure
    model.send(:validation_context=, current_context)
  end
end