<commit_before>require 'rspec'

module Specstar
  module Models
    module Matchers
      def properties_to_sentence(hash)
        " of " + hash.map { |key, value| "#{key} #{value}" }.to_sentence if hash.present?
      end

      RSpec::Matchers.define :have_attribute do |attr|
        attr = attr.to_s

        @extras = nil
        chain :with do |extras|
          @extras = extras
        end

        match do |target|
          result = target.attributes.include? attr

          if result && @extras
            properties = target.class.columns_hash[attr]
            @extras.each_pair do |property, value|
              result = false && break unless properties.send(property) == value
            end
          end

          result
        end

        failure_message_for_should do |target|
          "Expected #{target.class} to have an attribute '#{attr}'#{properties_to_sentence @extras}."
        end

        description do
          "have an attribute '#{attr}'#{properties_to_sentence @extras}."
        end
      end

      def has_attribute?(model, attr, extras={})
        attr = attr.to_s

        result = model.attributes.include? attr

        if result && extras.any?
          properties = model.class.columns_hash[attr]
          extras.each_pair do |property, value|
            result = false && break unless properties.send(property) == value
          end
        end

        result
      end

      def has_association?(model, association)
        model.class.reflect_on_all_associations.map { |a| a.name }.include? association.to_sym
      end

      RSpec::Matchers.define :validate_presence_of do |attr|
        match do |model|
          (has_attribute?(model, attr) || has_association?(model, attr)) &&
              model._validators[attr].select { |validator| validator.instance_of? ActiveModel::Validations::PresenceValidator }.size > 0
        end

        failure_message_for_should do |model|
          if has_attribute?(model, attr) || has_association?(model, attr)
            "expected #{model.class} to validate presence of #{attr}."
          else
            "expected #{model.class} to have an attribute or association #{attr}."
          end
        end
      end

      RSpec::Matchers.define :validate_uniqueness_of do |attr|
        match do |model|
          (has_attribute?(model, attr) || has_association?(model, attr)) &&
              model._validators[attr].select { |validator| validator.instance_of? ActiveRecord::Validations::UniquenessValidator }.size > 0
        end

        failure_message_for_should do |model|
          if has_attribute?(model, attr) || has_association?(model, attr)
            "expected #{model.class} to validate uniqueness of #{attr}."
          else
            "expected #{model.class} to have an attribute or association #{attr}."
          end
        end
      end

      RSpec::Matchers.define :validate_inclusion_of do |attr, options|
        match do |model|
          (has_attribute?(model, attr) || has_association?(model, attr)) &&
              model._validators[attr].select do |validator|
                validator.instance_of?(ActiveModel::Validations::InclusionValidator) && validator.options.merge(options) == validator.options
              end.size > 0
        end

        failure_message_for_should do |model|
          if has_attribute?(model, attr) || has_association?(model, attr)
            "expected #{model.class} to validate inclusion of #{attr} in [#{options.delete(:in).map(&:to_s).join(', ')}]."
          else
            "expected #{model.class} to have an attribute or association #{attr}."
          end
        end
      end

      RSpec::Matchers.define :validate_numericality_of do |attr, options|
        match do |model|
          (has_attribute?(model, attr) || has_association?(model, attr)) &&
              model._validators[attr].select do |validator|
                validator.instance_of?(ActiveModel::Validations::NumericalityValidator) && validator.options.merge(options) == validator.options
              end.size > 0
        end

        failure_message_for_should do |model|
          if has_attribute?(model, attr) || has_association?(model, attr)
            "expected #{model.class} to validate numericality of #{attr} in [#{options.delete(:in).map(&:to_s).join(', ')}]."
          else
            "expected #{model.class} to have an attribute or association #{attr}."
          end
        end
      end
    end
  end
end
<commit_msg>Fix: validate_numericality_of should not crash even if options are not specified.<commit_after>require 'rspec'

module Specstar
  module Models
    module Matchers
      def properties_to_sentence(hash)
        " of " + hash.map { |key, value| "#{key} #{value}" }.to_sentence if hash.present?
      end

      RSpec::Matchers.define :have_attribute do |attr|
        attr = attr.to_s

        @extras = nil
        chain :with do |extras|
          @extras = extras
        end

        match do |target|
          result = target.attributes.include? attr

          if result && @extras
            properties = target.class.columns_hash[attr]
            @extras.each_pair do |property, value|
              result = false && break unless properties.send(property) == value
            end
          end

          result
        end

        failure_message_for_should do |target|
          "Expected #{target.class} to have an attribute '#{attr}'#{properties_to_sentence @extras}."
        end

        description do
          "have an attribute '#{attr}'#{properties_to_sentence @extras}."
        end
      end

      def has_attribute?(model, attr, extras={})
        attr = attr.to_s

        result = model.attributes.include? attr

        if result && extras.any?
          properties = model.class.columns_hash[attr]
          extras.each_pair do |property, value|
            result = false && break unless properties.send(property) == value
          end
        end

        result
      end

      def has_association?(model, association)
        model.class.reflect_on_all_associations.map { |a| a.name }.include? association.to_sym
      end

      RSpec::Matchers.define :validate_presence_of do |attr|
        match do |model|
          (has_attribute?(model, attr) || has_association?(model, attr)) &&
              model._validators[attr].select { |validator| validator.instance_of? ActiveModel::Validations::PresenceValidator }.size > 0
        end

        failure_message_for_should do |model|
          if has_attribute?(model, attr) || has_association?(model, attr)
            "expected #{model.class} to validate presence of #{attr}."
          else
            "expected #{model.class} to have an attribute or association #{attr}."
          end
        end
      end

      RSpec::Matchers.define :validate_uniqueness_of do |attr|
        match do |model|
          (has_attribute?(model, attr) || has_association?(model, attr)) &&
              model._validators[attr].select { |validator| validator.instance_of? ActiveRecord::Validations::UniquenessValidator }.size > 0
        end

        failure_message_for_should do |model|
          if has_attribute?(model, attr) || has_association?(model, attr)
            "expected #{model.class} to validate uniqueness of #{attr}."
          else
            "expected #{model.class} to have an attribute or association #{attr}."
          end
        end
      end

      RSpec::Matchers.define :validate_inclusion_of do |attr, options|
        match do |model|
          (has_attribute?(model, attr) || has_association?(model, attr)) &&
              model._validators[attr].select do |validator|
                validator.instance_of?(ActiveModel::Validations::InclusionValidator) && validator.options.merge(options) == validator.options
              end.size > 0
        end

        failure_message_for_should do |model|
          if has_attribute?(model, attr) || has_association?(model, attr)
            "expected #{model.class} to validate inclusion of #{attr} in [#{options.delete(:in).map(&:to_s).join(', ')}]."
          else
            "expected #{model.class} to have an attribute or association #{attr}."
          end
        end
      end

      RSpec::Matchers.define :validate_numericality_of do |attr, options|
        options = options || {}

        match do |model|
          (has_attribute?(model, attr) || has_association?(model, attr)) &&
              model._validators[attr].select do |validator|
                validator.instance_of?(ActiveModel::Validations::NumericalityValidator) && validator.options.merge(options) == validator.options
              end.size > 0
        end

        failure_message_for_should do |model|
          if has_attribute?(model, attr) || has_association?(model, attr)
            "expected #{model.class} to validate numericality of #{attr} in [#{options.delete(:in).map(&:to_s).join(', ')}]."
          else
            "expected #{model.class} to have an attribute or association #{attr}."
          end
        end
      end
    end
  end
end

{'fraction_non_alphanumeric': 0.10853994490358126, 'fraction_numerical': 0.0008815426997245179, 'mean_word_length': 2.29796511627907, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1513041', 'n_tokens_mistral': 2514, 'n_tokens_neox': 2488, 'n_words': 642}