This file is indexed.

/usr/lib/ruby/vendor_ruby/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb is in ruby-shoulda-matchers 1.0.0~beta2-1build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 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
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
module Shoulda # :nodoc:
  module Matchers
    module ActiveRecord # :nodoc:

      # Ensures that the model is invalid if the given attribute is not unique.
      #
      # Internally, this uses values from existing records to test validations,
      # so this will always fail if you have not saved at least one record for
      # the model being tested, like so:
      #
      #   describe User do
      #     before(:each) { User.create!(:email => 'address@example.com') }
      #     it { should validate_uniqueness_of(:email) }
      #   end
      #
      # Options:
      #
      # * <tt>with_message</tt> - value the test expects to find in
      #   <tt>errors.on(:attribute)</tt>. <tt>Regexp</tt> or <tt>String</tt>.
      #   Defaults to the translation for <tt>:taken</tt>.
      # * <tt>scoped_to</tt> - field(s) to scope the uniqueness to.
      # * <tt>case_insensitive</tt> - ensures that the validation does not
      #   check case. Off by default. Ignored by non-text attributes.
      #
      # Examples:
      #   it { should validate_uniqueness_of(:keyword) }
      #   it { should validate_uniqueness_of(:keyword).with_message(/dup/) }
      #   it { should validate_uniqueness_of(:email).scoped_to(:name) }
      #   it { should validate_uniqueness_of(:email).
      #                 scoped_to(:first_name, :last_name) }
      #   it { should validate_uniqueness_of(:keyword).case_insensitive }
      #
      def validate_uniqueness_of(attr)
        ValidateUniquenessOfMatcher.new(attr)
      end

      class ValidateUniquenessOfMatcher < ValidationMatcher # :nodoc:
        include Helpers

        def initialize(attribute)
          @attribute = attribute
        end

        def scoped_to(*scopes)
          @scopes = [*scopes].flatten
          self
        end

        def with_message(message)
          @expected_message = message
          self
        end

        def case_insensitive
          @case_insensitive = true
          self
        end

        def description
          result = "require "
          result << "case sensitive " unless @case_insensitive
          result << "unique value for #{@attribute}"
          result << " scoped to #{@scopes.join(', ')}" unless @scopes.blank?
          result
        end

        def matches?(subject)
          @subject = subject.class.new
          @expected_message ||= :taken
          find_existing &&
            set_scoped_attributes &&
            validate_attribute &&
            validate_after_scope_change
        end

        private

        def find_existing
          if @existing = @subject.class.find(:first)
            true
          else
            @failure_message = "Can't find first #{class_name}"
            false
          end
        end

        def set_scoped_attributes
          unless @scopes.blank?
            @scopes.each do |scope|
              setter = :"#{scope}="
              unless @subject.respond_to?(setter)
                @failure_message =
                  "#{class_name} doesn't seem to have a #{scope} attribute."
                return false
              end
              @subject.send("#{scope}=", @existing.send(scope))
            end
          end
          true
        end

        def validate_attribute
          disallows_value_of(existing_value, @expected_message)
        end

        # TODO:  There is a chance that we could change the scoped field
        # to a value that's already taken.  An alternative implementation
        # could actually find all values for scope and create a unique
        def validate_after_scope_change
          if @scopes.blank?
            true
          else
            @scopes.all? do |scope|
              previous_value = @existing.send(scope)

              # Assume the scope is a foreign key if the field is nil
              previous_value ||= 0

              next_value = previous_value.next

              @subject.send("#{scope}=", next_value)

              if allows_value_of(existing_value, @expected_message)
                @negative_failure_message <<
                  " (with different value of #{scope})"
                true
              else
                @failure_message << " (with different value of #{scope})"
                false
              end
            end
          end
        end

        def class_name
          @subject.class.name
        end

        def existing_value
          value = @existing.send(@attribute)
          value.swapcase! if @case_insensitive && value.respond_to?(:swapcase!)
          value
        end
      end

    end
  end
end