class Shoulda::Matchers::ActiveRecord::DefineEnumForMatcher

@private

Attributes

attribute_name[R]
failure_message_continuation[R]
options[R]
record[R]

Public Class Methods

new(attribute_name) click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 198
def initialize(attribute_name)
  @attribute_name = attribute_name
  @options = { expected_enum_values: [], scopes: true }
end

Public Instance Methods

backed_by_column_of_type(expected_column_type) click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 248
def backed_by_column_of_type(expected_column_type)
  options[:expected_column_type] = expected_column_type
  self
end
description() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 203
def description
  description = "#{simple_description} backed by "
  description << Shoulda::Matchers::Util.a_or_an(expected_column_type)

  if expected_enum_values.any?
    description << ' with values '
    description << Shoulda::Matchers::Util.inspect_value(
      expected_enum_values,
    )
  end

  if options[:prefix]
    description << ", prefix: #{options[:prefix].inspect}"
  end

  if options[:suffix]
    description << ", suffix: #{options[:suffix].inspect}"
  end

  description
end
failure_message() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 268
def failure_message
  message =
    if enum_defined?
      "Expected #{model} to #{expectation}. "
    else
      "Expected #{model} to #{expectation}, but "
    end

  message << "#{failure_message_continuation}."

  Shoulda::Matchers.word_wrap(message)
end
failure_message_when_negated() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 281
def failure_message_when_negated
  message = "Expected #{model} not to #{expectation}, but it did."
  Shoulda::Matchers.word_wrap(message)
end
matches?(subject) click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 258
def matches?(subject)
  @record = subject

  enum_defined? &&
    enum_values_match? &&
    column_type_matches? &&
    enum_value_methods_exist? &&
    scope_presence_matches?
end
with(expected_enum_values) click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 230
def with(expected_enum_values)
  Shoulda::Matchers.warn_about_deprecated_method(
    'The `with` qualifier on `define_enum_for`',
    '`with_values`',
  )
  with_values(expected_enum_values)
end
with_prefix(expected_prefix = true) click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 238
def with_prefix(expected_prefix = true)
  options[:prefix] = expected_prefix
  self
end
with_suffix(expected_suffix = true) click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 243
def with_suffix(expected_suffix = true)
  options[:suffix] = expected_suffix
  self
end
with_values(expected_enum_values) click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 225
def with_values(expected_enum_values)
  options[:expected_enum_values] = expected_enum_values
  self
end
without_scopes() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 253
def without_scopes
  options[:scopes] = false
  self
end

Private Instance Methods

actual_enum_values() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 367
def actual_enum_values
  model.send(attribute_name.to_s.pluralize)
end
column() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 412
def column
  key = attribute_name.to_s
  column_name = model.attribute_alias(key) || key

  model.columns_hash[column_name]
end
column_type_matches?() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 396
def column_type_matches?
  if column.type == expected_column_type.to_sym
    true
  else
    @failure_message_continuation =
      "However, #{attribute_name.inspect} is "\
      "#{Shoulda::Matchers::Util.a_or_an(column.type)}"\
      ' column'
    false
  end
end
enum_defined?() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 371
def enum_defined?
  if model.defined_enums.include?(attribute_name.to_s)
    true
  else
    @failure_message_continuation =
      "no such enum exists on #{model}"
    false
  end
end
enum_value_methods_exist?() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 423
def enum_value_methods_exist?
  if instance_methods_exist?
    true
  else
    message = missing_methods_message

    message << " (we can't tell which)"

    @failure_message_continuation = message

    false
  end
end
enum_values_match?() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 381
def enum_values_match?
  passed =
    expected_enum_values.empty? ||
    normalized_actual_enum_values == normalized_expected_enum_values

  if passed
    true
  else
    @failure_message_continuation =
      "However, #{attribute_name.inspect} actually maps " +
      presented_enum_mapping(normalized_actual_enum_values)
    false
  end
end
exclude_scopes?() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 540
def exclude_scopes?
  !options[:scopes]
end
expectation() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 291
def expectation # rubocop:disable Metrics/MethodLength
  if enum_defined?
    expectation = "#{simple_description} backed by "
    expectation << Shoulda::Matchers::Util.a_or_an(expected_column_type)

    if expected_enum_values.any?
      expectation << ', mapping '
      expectation << presented_enum_mapping(
        normalized_expected_enum_values,
      )
    end

    if expected_prefix
      expectation <<
        if expected_suffix
          ', '
        else
          ' and '
        end

      expectation << 'prefixing accessor methods with '
      expectation << "#{expected_prefix}_".inspect
    end

    if expected_suffix
      expectation <<
        if expected_prefix
          ', and '
        else
          ' and '
        end

      expectation << 'suffixing accessor methods with '
      expectation << "_#{expected_suffix}".inspect
    end

    if exclude_scopes?
      expectation << ' with no scopes'
    end

    expectation
  else
    simple_description
  end
end
expected_column_type() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 408
def expected_column_type
  options[:expected_column_type] || :integer
end
expected_enum_value_names() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 355
def expected_enum_value_names
  to_array(expected_enum_values)
end
expected_enum_values() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 359
def expected_enum_values
  options[:expected_enum_values]
end
expected_instance_methods() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 508
def expected_instance_methods
  methods = expected_enum_value_names.map do |name|
    [expected_prefix, name, expected_suffix].
      select(&:present?).
      join('_')
  end

  methods.flat_map do |m|
    ["#{m}?".to_sym, "#{m}!".to_sym]
  end
end
expected_prefix() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 520
def expected_prefix
  if options.include?(:prefix)
    if options[:prefix] == true
      attribute_name
    else
      options[:prefix]
    end
  end
end
expected_singleton_methods() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 499
def expected_singleton_methods
  expected_enum_value_names.map do |name|
    [expected_prefix, name, expected_suffix].
      select(&:present?).
      join('_').
      to_sym
  end
end
expected_suffix() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 530
def expected_suffix
  if options.include?(:suffix)
    if options[:suffix] == true
      attribute_name
    else
      options[:suffix]
    end
  end
end
instance_methods_exist?() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 493
def instance_methods_exist?
  expected_instance_methods.all? do |method|
    record.methods.include?(method)
  end
end
missing_methods_message() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 467
def missing_methods_message
  message = "#{attribute_name.inspect} does map to these "
  message << 'values, but the enum is '

  if expected_prefix
    if expected_suffix
      message << 'configured with either a different prefix or '
      message << 'suffix, or no prefix or suffix at all'
    else
      message << 'configured with either a different prefix or no '
      message << 'prefix at all'
    end
  elsif expected_suffix
    message << 'configured with either a different suffix or no '
    message << 'suffix at all'
  else
    ''
  end
end
model() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 419
def model
  record.class
end
normalized_actual_enum_values() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 363
def normalized_actual_enum_values
  to_hash(actual_enum_values)
end
normalized_expected_enum_values() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 351
def normalized_expected_enum_values
  to_hash(expected_enum_values)
end
presented_enum_mapping(enum_values) click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 341
def presented_enum_mapping(enum_values)
  enum_values.
    map { |output_to_input|
      output_to_input.
        map(&Shoulda::Matchers::Util.method(:inspect_value)).
        join(' to ')
    }.
    to_sentence
end
scope_presence_matches?() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 437
def scope_presence_matches?
  if exclude_scopes?
    if singleton_methods_exist?
      message = "#{attribute_name.inspect} does map to these values "
      message << 'but class scope methods were present'

      @failure_message_continuation = message

      false
    else
      true
    end
  elsif singleton_methods_exist?
    true
  else
    if enum_defined?
      message = 'But the class scope methods are not present'
    else
      message = missing_methods_message

      message << 'or the class scope methods are not present'
      message << " (we can't tell which)"
    end

    @failure_message_continuation = message

    false
  end
end
simple_description() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 337
def simple_description
  "define :#{attribute_name} as an enum"
end
singleton_methods_exist?() click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 487
def singleton_methods_exist?
  expected_singleton_methods.all? do |method|
    model.singleton_methods.include?(method)
  end
end
to_array(value) click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 554
def to_array(value)
  if value.is_a?(Array)
    value.map(&:to_s)
  else
    value.keys.map(&:to_s)
  end
end
to_hash(value) click to toggle source
# File lib/shoulda/matchers/active_record/define_enum_for_matcher.rb, line 544
def to_hash(value)
  if value.is_a?(Array)
    value.each_with_index.inject({}) do |hash, (item, index)|
      hash.merge(item.to_s => index)
    end
  else
    value.stringify_keys
  end
end