class ActiveAttr::Matchers::HaveAttributeMatcher

Verifies that an ActiveAttr-based model has an attribute matching the given criteria. See {Matchers#have_attribute}

@since 0.2.0

Attributes

attribute_name[R]

Public Class Methods

new(attribute_name) click to toggle source

@param [Symbol, String, to_sym] attribute_name @private

# File lib/active_attr/matchers/have_attribute_matcher.rb, line 32
def initialize(attribute_name)
  raise TypeError, "can't convert #{attribute_name.class} into Symbol" unless attribute_name.respond_to? :to_sym
  @attribute_name = attribute_name.to_sym
  @attribute_options = {}
  @description = "attribute named #{attribute_name}"
  @expected_ancestors = ["ActiveAttr::Attributes"]
  @attribute_expectations = [lambda { actual_attribute_definition }]
end

Public Instance Methods

description() click to toggle source

@return [String] Description @private

# File lib/active_attr/matchers/have_attribute_matcher.rb, line 85
def description
  "have #{@description}"
end
failure_message() click to toggle source

@return [String] Failure message @private

# File lib/active_attr/matchers/have_attribute_matcher.rb, line 97
def failure_message
  if missing_ancestors.any?
    "expected #{@model_class.name} to include #{missing_ancestors.first}"
  elsif actual_attribute_definition
    "expected: #{expected_attribute_definition.inspect}\n" +
    "     got: #{actual_attribute_definition.inspect}"
  else
    "expected #{@model_class.name} to have #{@description}"
  end
end
failure_message_when_negated() click to toggle source

@return [String] Negative failure message @private

# File lib/active_attr/matchers/have_attribute_matcher.rb, line 110
def failure_message_when_negated
  "expected not: #{expected_attribute_definition.inspect}\n" +
  "         got: #{actual_attribute_definition.inspect}"
end
Also aliased as: negative_failure_message
matches?(model_or_model_class) click to toggle source

@private

# File lib/active_attr/matchers/have_attribute_matcher.rb, line 90
def matches?(model_or_model_class)
  @model_class = Class === model_or_model_class ? model_or_model_class : model_or_model_class.class
  missing_ancestors.none? && @attribute_expectations.all? { | expectation| expectation.call }
end
negative_failure_message()
of_type(type) click to toggle source

Specify that the attribute should have the given type

@example Person's first name should be a String

describe Person do
  it { should have_attribute(:first_name).of_type(String) }
end

@param [Class] type The expected type

@return [HaveAttributeMatcher] The matcher

@since 0.5.0

# File lib/active_attr/matchers/have_attribute_matcher.rb, line 53
def of_type(type)
  @attribute_options[:type] = type
  @description << " of type #{type}"
  @expected_ancestors << "ActiveAttr::TypecastedAttributes"
  @attribute_expectations << lambda { @model_class._attribute_type(attribute_name) == type }
  self
end
with_default_value_of(default_value) click to toggle source

Specify that the attribute should have the given default value

@example Person's first name should default to John

describe Person do
  it do
    should have_attribute(:first_name).with_default_value_of("John")
  end
end

@param [Object] default_value The expected default value

@return [HaveAttributeMatcher] The matcher

@since 0.5.0

# File lib/active_attr/matchers/have_attribute_matcher.rb, line 75
def with_default_value_of(default_value)
  @attribute_options[:default] = default_value
  @description << " with a default value of #{default_value.inspect}"
  @expected_ancestors << "ActiveAttr::AttributeDefaults"
  @attribute_expectations << lambda { @model_class.allocate.send(:_attribute_default, @attribute_name) == default_value }
  self
end

Private Instance Methods

actual_attribute_definition() click to toggle source
# File lib/active_attr/matchers/have_attribute_matcher.rb, line 118
def actual_attribute_definition
  @model_class.attributes[attribute_name]
end
expected_attribute_definition() click to toggle source
# File lib/active_attr/matchers/have_attribute_matcher.rb, line 122
def expected_attribute_definition
  AttributeDefinition.new @attribute_name, @attribute_options
end
missing_ancestors() click to toggle source
# File lib/active_attr/matchers/have_attribute_matcher.rb, line 126
def missing_ancestors
  model_ancestor_names = @model_class.ancestors.map(&:name)

  @expected_ancestors.reject do |ancestor_name|
    model_ancestor_names.include? ancestor_name
  end
end