module ThoughtBot::Shoulda::ActiveRecord::Assertions

def assert_bad_value(object_or_klass, attribute, value,

assert_bad_value(Product, :price, "0")
@product = Product.new(:tangible => true)

assert_bad_value(User, :email, "invalid")

instead.
the same name as the class (underscored), that object will be used
instantiated before the assertion. If an instance variable exists with
If a class is passed as the first argument, a new object will be

assert_bad_value(User.new, :ssn, "123", /length/)
assert_bad_value(User.new, :email, "invalid")

contained within the list of errors for that attribute.
value by making sure the error_message_to_expect is
Asserts that an Active Record model invalidates the passed
def assert_bad_value(object_or_klass, attribute, value,
                     error_message_to_expect = DEFAULT_ERROR_MESSAGES[:invalid])
  object = get_instance_of(object_or_klass)
  object.send("#{attribute}=", value)
  assert !object.valid?, "#{object.class} allowed #{value.inspect} as a value for #{attribute}"
  assert object.errors.on(attribute), "There are no errors on #{attribute} after being set to #{value.inspect}"
  assert_contains(object.errors.on(attribute), error_message_to_expect, "when set to #{value.inspect}")
end

def assert_good_value(object_or_klass, attribute, value, error_message_to_avoid = //)

assert_good_value(Product, :price, "0")
@product = Product.new(:tangible => false)

assert_good_value(User, :email, "user@example.com")

instead.
the same name as the class (underscored), that object will be used
instantiated before the assertion. If an instance variable exists with
If a class is passed as the first argument, a new object will be

assert_good_value(User.new, :ssn, "123456789", /length/)
assert_good_value(User.new, :email, "user@example.com")

contained within the list of errors for that attribute.
value by making sure the error_message_to_avoid is not
Asserts that an Active Record model validates with the passed
def assert_good_value(object_or_klass, attribute, value, error_message_to_avoid = //)
  object = get_instance_of(object_or_klass)
  object.send("#{attribute}=", value)
  object.valid?
  assert_does_not_contain(object.errors.on(attribute), error_message_to_avoid, "when set to #{value.inspect}")
end

def assert_save(obj)

assert_save User.new(params)

Asserts that the given object can be saved
def assert_save(obj)
  assert obj.save, "Errors: #{pretty_error_messages obj}"
  obj.reload
end

def assert_valid(obj)

assert_valid User.new(params)

Asserts that the given object is valid
def assert_valid(obj)
  assert obj.valid?, "Errors: #{pretty_error_messages obj}"
end

def get_instance_of(object_or_klass)

def get_instance_of(object_or_klass)
  if object_or_klass.is_a?(Class)
    klass = object_or_klass
    instance_variable_get("@#{klass.to_s.underscore}") || klass.new
  else
    object_or_klass
  end
end

def pretty_error_messages(obj)

def pretty_error_messages(obj)
  obj.errors.map { |a, m| "#{a} #{m} (#{obj.send(a).inspect})" }
end