2014-01-23 18:07:36 +00:00
|
|
|
module Shoulda
|
2010-12-15 22:34:19 +00:00
|
|
|
module Matchers
|
2014-01-23 18:07:36 +00:00
|
|
|
module ActiveModel
|
|
|
|
# The `allow_value` matcher is used to test that an attribute of a model
|
|
|
|
# can or cannot be set to a particular value or values. It is most
|
|
|
|
# commonly used in conjunction with the `validates_format_of` validation.
|
|
|
|
#
|
|
|
|
# #### should
|
|
|
|
#
|
|
|
|
# In the positive form, `allow_value` asserts that an attribute can be
|
|
|
|
# set to one or more values, succeeding if none of the values cause the
|
|
|
|
# record to be invalid:
|
|
|
|
#
|
|
|
|
# class UserProfile
|
|
|
|
# include ActiveModel::Model
|
|
|
|
# attr_accessor :website_url
|
|
|
|
#
|
|
|
|
# validates_format_of :website_url, with: URI.regexp
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# # RSpec
|
|
|
|
# describe UserProfile do
|
|
|
|
# it do
|
|
|
|
# should allow_value('http://foo.com', 'http://bar.com/baz').
|
|
|
|
# for(:website_url)
|
|
|
|
# end
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# # Test::Unit
|
|
|
|
# class UserProfileTest < ActiveSupport::TestCase
|
|
|
|
# should allow_value('http://foo.com', 'http://bar.com/baz').
|
|
|
|
# for(:website_url)
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# #### should_not
|
|
|
|
#
|
|
|
|
# In the negative form, `allow_value` asserts that an attribute cannot be
|
|
|
|
# set to one or more values, succeeding if the *first* value causes the
|
|
|
|
# record to be invalid.
|
|
|
|
#
|
|
|
|
# **This can be surprising** so in this case if you need to check that
|
|
|
|
# *all* of the values are invalid, use separate assertions:
|
|
|
|
#
|
|
|
|
# class UserProfile
|
|
|
|
# include ActiveModel::Model
|
|
|
|
# attr_accessor :website_url
|
|
|
|
#
|
|
|
|
# validates_format_of :website_url, with: URI.regexp
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# describe UserProfile do
|
|
|
|
# # One assertion: 'buz' and 'bar' will not be tested
|
|
|
|
# it { should_not allow_value('fiz', 'buz', 'bar').for(:website_url) }
|
|
|
|
#
|
|
|
|
# # Three assertions, all tested separately
|
|
|
|
# it { should_not allow_value('fiz').for(:website_url) }
|
|
|
|
# it { should_not allow_value('buz').for(:website_url) }
|
|
|
|
# it { should_not allow_value('bar').for(:website_url) }
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# #### Qualifiers
|
|
|
|
#
|
|
|
|
# ##### on
|
|
|
|
#
|
|
|
|
# Use `on` if your validation applies only under a certain context.
|
|
|
|
#
|
|
|
|
# class UserProfile
|
|
|
|
# include ActiveModel::Model
|
|
|
|
# attr_accessor :birthday_as_string
|
|
|
|
#
|
|
|
|
# validates_format_of :birthday_as_string,
|
|
|
|
# with: /^(\d+)-(\d+)-(\d+)$/,
|
|
|
|
# on: :create
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# # RSpec
|
|
|
|
# describe UserProfile do
|
|
|
|
# it do
|
|
|
|
# should allow_value('2013-01-01').
|
|
|
|
# for(:birthday_as_string).
|
|
|
|
# on(:create)
|
|
|
|
# end
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# # Test::Unit
|
|
|
|
# class UserProfileTest < ActiveSupport::TestCase
|
|
|
|
# should allow_value('2013-01-01').
|
|
|
|
# for(:birthday_as_string).
|
|
|
|
# on(:create)
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# ##### with_message
|
|
|
|
#
|
|
|
|
# Use `with_message` if you are using a custom validation message.
|
|
|
|
#
|
|
|
|
# class UserProfile
|
|
|
|
# include ActiveModel::Model
|
|
|
|
# attr_accessor :state
|
|
|
|
#
|
|
|
|
# validates_format_of :state,
|
|
|
|
# with: /^(open|closed)$/,
|
|
|
|
# message: 'State must be open or closed'
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# # RSpec
|
|
|
|
# describe UserProfile do
|
|
|
|
# it do
|
|
|
|
# should allow_value('open', 'closed').
|
|
|
|
# for(:state).
|
|
|
|
# with_message('State must be open or closed')
|
|
|
|
# end
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# # Test::Unit
|
|
|
|
# class UserProfileTest < ActiveSupport::TestCase
|
|
|
|
# should allow_value('open', 'closed').
|
|
|
|
# for(:state).
|
|
|
|
# with_message('State must be open or closed')
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# Use `with_message` with the `:against` option if the attribute the
|
|
|
|
# validation message is stored under is different from the attribute
|
|
|
|
# being validated.
|
|
|
|
#
|
|
|
|
# class UserProfile
|
|
|
|
# include ActiveModel::Model
|
|
|
|
# attr_accessor :sports_team
|
|
|
|
#
|
|
|
|
# validate :sports_team_must_be_valid
|
|
|
|
#
|
|
|
|
# private
|
|
|
|
#
|
|
|
|
# def sports_team_must_be_valid
|
|
|
|
# if sports_team !~ /^(Broncos|Titans)$/i
|
|
|
|
# self.errors.add :chosen_sports_team,
|
|
|
|
# 'Must be either a Broncos fan or a Titans fan'
|
|
|
|
# end
|
|
|
|
# end
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# # RSpec
|
|
|
|
# describe UserProfile do
|
|
|
|
# it do
|
|
|
|
# should allow_value('Broncos', 'Titans').
|
|
|
|
# for(:sports_team).
|
|
|
|
# with_message('Must be either a Broncos or Titans fan',
|
|
|
|
# against: :chosen_sports_team
|
|
|
|
# )
|
|
|
|
# end
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# # Test::Unit
|
|
|
|
# class UserProfileTest < ActiveSupport::TestCase
|
|
|
|
# should allow_value('Broncos', 'Titans').
|
|
|
|
# for(:sports_team).
|
|
|
|
# with_message('Must be either a Broncos or Titans fan',
|
|
|
|
# against: :chosen_sports_team
|
|
|
|
# )
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# @return [AllowValueMatcher]
|
2010-12-15 22:34:19 +00:00
|
|
|
#
|
2010-09-05 15:33:32 +00:00
|
|
|
def allow_value(*values)
|
2012-03-23 14:10:08 +00:00
|
|
|
if values.empty?
|
2012-12-20 05:04:27 +00:00
|
|
|
raise ArgumentError, 'need at least one argument'
|
2012-03-23 14:10:08 +00:00
|
|
|
else
|
|
|
|
AllowValueMatcher.new(*values)
|
|
|
|
end
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
|
2014-01-23 18:07:36 +00:00
|
|
|
# @private
|
|
|
|
class AllowValueMatcher
|
allow_value: Raise error if attr sets value differently
`allow_value` will now raise a CouldNotSetAttribute error if the
attribute in question cannot be changed from a non-nil value to a nil
value, or vice versa. In other words, these are the exact cases in which
the error will occur:
* If you're testing whether the attribute allows `nil`, but the
attribute detects and ignores nil. (For instance, you have a model
that `has_secure_password`. This will add a #password= method to your
model that is defined in a such a way that you cannot clear the
password by setting it to nil -- nothing happens.)
* If you're testing whether the attribute allows a non-nil value, but
the attribute fails to set that value. (For instance, you have an
ActiveRecord model. If ActiveRecord cannot typecast the value in the
context of the column, then it will do nothing, and the attribute will be
effectively set to nil.)
What's the reasoning behind this change? Simply put, if you are assuming
that the attribute is changing but in fact it is not, then the test
you're writing isn't the test that actually gets run. We feel that this
is dishonest and produces an invalid test.
2013-11-22 20:46:59 +00:00
|
|
|
# @private
|
|
|
|
class CouldNotSetAttributeError < Shoulda::Matchers::Error
|
|
|
|
def self.create(model, attribute, expected_value, actual_value)
|
|
|
|
super(
|
|
|
|
model: model,
|
|
|
|
attribute: attribute,
|
|
|
|
expected_value: expected_value,
|
|
|
|
actual_value: actual_value
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
attr_accessor :model, :attribute, :expected_value, :actual_value
|
|
|
|
|
|
|
|
def message
|
|
|
|
"Expected #{model.class} to be able to set #{attribute} to #{expected_value.inspect}, but got #{actual_value.inspect} instead."
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-12-15 22:34:19 +00:00
|
|
|
include Helpers
|
|
|
|
|
2013-07-24 21:46:01 +00:00
|
|
|
attr_accessor :attribute_with_message
|
2013-03-28 18:48:45 +00:00
|
|
|
attr_accessor :options
|
|
|
|
|
2010-09-05 15:33:32 +00:00
|
|
|
def initialize(*values)
|
2013-03-28 18:48:45 +00:00
|
|
|
self.values_to_match = values
|
|
|
|
self.options = {}
|
2014-04-16 06:24:02 +00:00
|
|
|
self.after_setting_value_callback = -> {}
|
2015-01-21 22:46:26 +00:00
|
|
|
self.validator = Validator.new
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def for(attribute)
|
2013-07-24 21:46:01 +00:00
|
|
|
self.attribute_to_set = attribute
|
|
|
|
self.attribute_to_check_message_against = attribute
|
2010-12-15 22:34:19 +00:00
|
|
|
self
|
|
|
|
end
|
|
|
|
|
2013-03-04 03:34:38 +00:00
|
|
|
def on(context)
|
2015-01-21 22:46:26 +00:00
|
|
|
validator.context = context
|
2013-03-04 03:34:38 +00:00
|
|
|
self
|
|
|
|
end
|
|
|
|
|
2013-07-24 21:46:01 +00:00
|
|
|
def with_message(message, options={})
|
2013-03-28 18:48:45 +00:00
|
|
|
self.options[:expected_message] = message
|
2014-04-26 15:10:17 +00:00
|
|
|
self.options[:expected_message_values] = options.fetch(:values, {})
|
|
|
|
|
2013-07-24 21:46:01 +00:00
|
|
|
if options.key?(:against)
|
|
|
|
self.attribute_to_check_message_against = options[:against]
|
|
|
|
end
|
2014-04-26 15:10:17 +00:00
|
|
|
|
2010-12-15 22:34:19 +00:00
|
|
|
self
|
|
|
|
end
|
|
|
|
|
2012-09-11 22:40:39 +00:00
|
|
|
def strict
|
2015-01-21 22:46:26 +00:00
|
|
|
validator.strict = true
|
2012-09-11 22:40:39 +00:00
|
|
|
self
|
|
|
|
end
|
|
|
|
|
2014-07-24 04:03:51 +00:00
|
|
|
def _after_setting_value(&callback)
|
2014-04-16 06:24:02 +00:00
|
|
|
self.after_setting_value_callback = callback
|
|
|
|
end
|
|
|
|
|
2010-12-15 22:34:19 +00:00
|
|
|
def matches?(instance)
|
2013-03-28 18:48:45 +00:00
|
|
|
self.instance = instance
|
2014-10-22 07:18:54 +00:00
|
|
|
values_to_match.all? { |value| value_matches?(value) }
|
|
|
|
end
|
2013-03-26 22:16:04 +00:00
|
|
|
|
2014-10-22 07:18:54 +00:00
|
|
|
def does_not_match?(instance)
|
|
|
|
self.instance = instance
|
|
|
|
values_to_match.all? { |value| !value_matches?(value) }
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
|
2013-12-24 11:24:27 +00:00
|
|
|
def failure_message
|
2015-01-21 22:46:26 +00:00
|
|
|
"Did not expect #{expectation},\ngot#{error_description}"
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
2013-12-24 11:24:27 +00:00
|
|
|
alias failure_message_for_should failure_message
|
2010-12-15 22:34:19 +00:00
|
|
|
|
2013-12-24 11:24:27 +00:00
|
|
|
def failure_message_when_negated
|
Tweak allow_value failure_message
This commit changes the failure message that `allow_value` generates so
that it reads a bit nicer.
When a call to #valid? resulted in validation messages, `allow_value`
formerly failed with this message:
Expected errors to include "the message" when attr is set to "some value", got errors: ["another message (attribute: \"attr\", value: \"some value\")", "some other message (attribute: \"attr2\", value: \"some other value\")"]
Now it fails with this message:
Expected errors to include "the message" when attr is set to "some value",
got errors:
* "another message" (attribute: attr, value: "some value")
* "some other message" (attribute: attr2, value: "some other value")
Similarly, when a call to #valid resulted in an exception, `allow_value`
formerly failed with this message:
Expected errors to include "the message" when attr is set to "some value", got: some message
Now it fails with this message:
Expected errors to include "the message" when attr is set to "some value",
got: "some message"
2014-10-12 02:19:23 +00:00
|
|
|
"Expected #{expectation},\ngot#{error_description}"
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
2013-12-24 11:24:27 +00:00
|
|
|
alias failure_message_for_should_not failure_message_when_negated
|
2010-12-15 22:34:19 +00:00
|
|
|
|
|
|
|
def description
|
2015-01-21 22:46:26 +00:00
|
|
|
validator.allow_description(allowed_values)
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
|
2014-06-24 15:57:52 +00:00
|
|
|
protected
|
2010-12-15 22:34:19 +00:00
|
|
|
|
2014-10-22 07:18:54 +00:00
|
|
|
attr_reader :instance, :attribute_to_check_message_against
|
|
|
|
attr_accessor :values_to_match, :attribute_to_set, :value,
|
2015-01-21 22:46:26 +00:00
|
|
|
:matched_error, :after_setting_value_callback, :validator
|
2013-11-22 20:46:59 +00:00
|
|
|
|
2014-10-22 07:18:54 +00:00
|
|
|
def instance=(instance)
|
|
|
|
@instance = instance
|
|
|
|
validator.record = instance
|
|
|
|
end
|
|
|
|
|
2015-01-21 22:46:26 +00:00
|
|
|
def attribute_to_check_message_against=(attribute)
|
|
|
|
@attribute_to_check_message_against = attribute
|
|
|
|
validator.attribute = attribute
|
|
|
|
end
|
|
|
|
|
2014-10-22 07:18:54 +00:00
|
|
|
def value_matches?(value)
|
|
|
|
self.value = value
|
|
|
|
set_attribute(value)
|
|
|
|
!(errors_match? || any_range_error_occurred?)
|
|
|
|
end
|
|
|
|
|
2015-01-21 22:46:26 +00:00
|
|
|
def set_attribute(value)
|
|
|
|
set_attribute_ignoring_range_errors(value)
|
2014-04-16 06:24:02 +00:00
|
|
|
after_setting_value_callback.call
|
2013-11-22 20:46:59 +00:00
|
|
|
end
|
|
|
|
|
2015-01-21 22:46:26 +00:00
|
|
|
def set_attribute_ignoring_range_errors(value)
|
|
|
|
instance.__send__("#{attribute_to_set}=", value)
|
allow_value: Raise error if attr sets value differently
`allow_value` will now raise a CouldNotSetAttribute error if the
attribute in question cannot be changed from a non-nil value to a nil
value, or vice versa. In other words, these are the exact cases in which
the error will occur:
* If you're testing whether the attribute allows `nil`, but the
attribute detects and ignores nil. (For instance, you have a model
that `has_secure_password`. This will add a #password= method to your
model that is defined in a such a way that you cannot clear the
password by setting it to nil -- nothing happens.)
* If you're testing whether the attribute allows a non-nil value, but
the attribute fails to set that value. (For instance, you have an
ActiveRecord model. If ActiveRecord cannot typecast the value in the
context of the column, then it will do nothing, and the attribute will be
effectively set to nil.)
What's the reasoning behind this change? Simply put, if you are assuming
that the attribute is changing but in fact it is not, then the test
you're writing isn't the test that actually gets run. We feel that this
is dishonest and produces an invalid test.
2013-11-22 20:46:59 +00:00
|
|
|
ensure_that_attribute_has_been_changed_to_or_from_nil!(value)
|
2015-01-21 22:46:26 +00:00
|
|
|
rescue RangeError => exception
|
|
|
|
# Have to reset the attribute so that we don't get a RangeError the
|
|
|
|
# next time we attempt to write the attribute (ActiveRecord seems to
|
|
|
|
# set the attribute to the "bad" value anyway)
|
|
|
|
reset_attribute
|
|
|
|
validator.capture_range_error(exception)
|
|
|
|
end
|
|
|
|
|
|
|
|
def reset_attribute
|
|
|
|
instance.send(:raw_write_attribute, attribute_to_set, nil)
|
|
|
|
end
|
|
|
|
|
allow_value: Raise error if attr sets value differently
`allow_value` will now raise a CouldNotSetAttribute error if the
attribute in question cannot be changed from a non-nil value to a nil
value, or vice versa. In other words, these are the exact cases in which
the error will occur:
* If you're testing whether the attribute allows `nil`, but the
attribute detects and ignores nil. (For instance, you have a model
that `has_secure_password`. This will add a #password= method to your
model that is defined in a such a way that you cannot clear the
password by setting it to nil -- nothing happens.)
* If you're testing whether the attribute allows a non-nil value, but
the attribute fails to set that value. (For instance, you have an
ActiveRecord model. If ActiveRecord cannot typecast the value in the
context of the column, then it will do nothing, and the attribute will be
effectively set to nil.)
What's the reasoning behind this change? Simply put, if you are assuming
that the attribute is changing but in fact it is not, then the test
you're writing isn't the test that actually gets run. We feel that this
is dishonest and produces an invalid test.
2013-11-22 20:46:59 +00:00
|
|
|
def ensure_that_attribute_has_been_changed_to_or_from_nil!(expected_value)
|
|
|
|
actual_value = instance.__send__(attribute_to_set)
|
|
|
|
|
|
|
|
if expected_value.nil? != actual_value.nil?
|
|
|
|
raise CouldNotSetAttributeError.create(
|
|
|
|
instance.class,
|
|
|
|
attribute_to_set,
|
|
|
|
expected_value,
|
|
|
|
actual_value
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-03-29 20:10:01 +00:00
|
|
|
def errors_match?
|
|
|
|
has_messages? && errors_for_attribute_match?
|
2013-03-26 22:16:04 +00:00
|
|
|
end
|
|
|
|
|
2013-03-29 20:10:01 +00:00
|
|
|
def has_messages?
|
2015-01-21 22:46:26 +00:00
|
|
|
validator.has_messages?
|
2012-09-11 22:40:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def errors_for_attribute_match?
|
|
|
|
if expected_message
|
2013-03-28 18:48:45 +00:00
|
|
|
self.matched_error = errors_match_regexp? || errors_match_string?
|
2012-09-11 22:40:39 +00:00
|
|
|
else
|
|
|
|
errors_for_attribute.compact.any?
|
2010-09-05 15:23:09 +00:00
|
|
|
end
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
|
2012-03-23 14:10:08 +00:00
|
|
|
def errors_for_attribute
|
2015-01-21 22:46:26 +00:00
|
|
|
validator.formatted_messages
|
2012-09-11 22:40:39 +00:00
|
|
|
end
|
|
|
|
|
2010-12-15 22:34:19 +00:00
|
|
|
def errors_match_regexp?
|
2012-03-23 14:10:08 +00:00
|
|
|
if Regexp === expected_message
|
2012-05-07 14:25:46 +00:00
|
|
|
errors_for_attribute.detect { |e| e =~ expected_message }
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def errors_match_string?
|
2012-03-23 14:10:08 +00:00
|
|
|
if errors_for_attribute.include?(expected_message)
|
2012-05-07 14:25:46 +00:00
|
|
|
expected_message
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-01-21 22:46:26 +00:00
|
|
|
def any_range_error_occurred?
|
|
|
|
validator.captured_range_error?
|
|
|
|
end
|
|
|
|
|
2010-12-15 22:34:19 +00:00
|
|
|
def expectation
|
2014-10-22 07:17:58 +00:00
|
|
|
parts = [
|
2015-01-21 22:46:26 +00:00
|
|
|
expected_messages_description,
|
2014-10-22 07:17:58 +00:00
|
|
|
"when #{attribute_to_set} is set to #{value.inspect}"
|
|
|
|
]
|
|
|
|
|
|
|
|
parts.join(' ').squeeze(' ')
|
|
|
|
end
|
|
|
|
|
2015-01-21 22:46:26 +00:00
|
|
|
def expected_messages_description
|
|
|
|
validator.expected_messages_description(expected_message)
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def error_description
|
2015-01-21 22:46:26 +00:00
|
|
|
validator.messages_description
|
2012-09-11 22:40:39 +00:00
|
|
|
end
|
|
|
|
|
2012-03-23 14:10:08 +00:00
|
|
|
def allowed_values
|
2013-03-28 18:48:45 +00:00
|
|
|
if values_to_match.length > 1
|
|
|
|
"any of [#{values_to_match.map(&:inspect).join(', ')}]"
|
2012-03-23 14:10:08 +00:00
|
|
|
else
|
2013-03-28 18:48:45 +00:00
|
|
|
values_to_match.first.inspect
|
2012-03-23 14:10:08 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def expected_message
|
2013-03-28 18:48:45 +00:00
|
|
|
if options.key?(:expected_message)
|
|
|
|
if Symbol === options[:expected_message]
|
2012-09-12 00:53:21 +00:00
|
|
|
default_expected_message
|
2012-03-23 14:10:08 +00:00
|
|
|
else
|
2013-03-28 18:48:45 +00:00
|
|
|
options[:expected_message]
|
2012-03-23 14:10:08 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-09-12 00:53:21 +00:00
|
|
|
def default_expected_message
|
2015-01-21 22:46:26 +00:00
|
|
|
validator.expected_message_from(default_attribute_message)
|
2012-09-12 00:53:21 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def default_attribute_message
|
2013-02-14 22:25:46 +00:00
|
|
|
default_error_message(
|
2013-03-28 18:48:45 +00:00
|
|
|
options[:expected_message],
|
2014-04-26 15:10:17 +00:00
|
|
|
default_attribute_message_values
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
def default_attribute_message_values
|
|
|
|
defaults = {
|
2014-01-17 20:20:44 +00:00
|
|
|
model_name: model_name,
|
|
|
|
instance: instance,
|
2014-10-15 06:13:17 +00:00
|
|
|
attribute: attribute_to_check_message_against,
|
2014-04-26 15:10:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
defaults.merge(options[:expected_message_values])
|
2012-09-12 00:53:21 +00:00
|
|
|
end
|
|
|
|
|
2012-03-23 14:10:08 +00:00
|
|
|
def model_name
|
2013-03-28 18:48:45 +00:00
|
|
|
instance.class.to_s.underscore
|
2012-03-23 14:10:08 +00:00
|
|
|
end
|
|
|
|
end
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|