2013-12-12 21:45:43 +00:00
|
|
|
require 'active_support/core_ext/module/delegation'
|
Refactor AssociationMatcher to use new OptionVerifier
When using an association matcher you may have qualifiers on that
matcher which let you make assertions on options passed to the
association method that you are testing. For instance, has_many has a
:dependent option and so in order to test this you say something like
it { should have_many(:people).dependent(:destroy) }
In order to test such an option we have to compare the option you passed
with what the actual value of that option is. This is usually obtained
by looking at the reflection object of the association in question,
although it can be obtained by other means too.
Anyway, the code that does this comparison isn't terrible, but there are
two problems with it. First, it involves typecasting both expected and
actual values. For instance, this:
has_many :people, dependent: :destroy
it { should have_many(:people).dependent(:destroy) }
should be equivalent to:
has_many :people, dependent: :destroy
it { should have_many(:people).dependent('destroy') }
should be equivalent to:
has_many :people, dependent: 'destroy'
it { should have_many(:people).dependent(:destroy) }
Second, we are a little screwed if the method of obtaining the actual
value of the option changes depending on which Rails version you're
using.
So, OptionVerifier attempts to address both of these issues. It's a
little crazy, but it works.
I also moved some methods from AssociationMatcher to ModelReflector
where they really belong.
2013-08-16 21:38:10 +00:00
|
|
|
|
2010-12-15 22:34:19 +00:00
|
|
|
module Shoulda # :nodoc:
|
|
|
|
module Matchers
|
|
|
|
module ActiveRecord # :nodoc:
|
|
|
|
# Ensure that the belongs_to relationship exists.
|
|
|
|
#
|
2012-04-11 16:45:52 +00:00
|
|
|
# Options:
|
2014-02-11 03:06:18 +00:00
|
|
|
# * <tt>class_name</tt> - tests that the association resolves to class_name.
|
|
|
|
# * <tt>validate</tt> - tests that the association makes use of the validate
|
2012-04-11 16:45:52 +00:00
|
|
|
# option.
|
2014-02-11 03:06:18 +00:00
|
|
|
# * <tt>touch</tt> - tests that the association makes use of the touch
|
2013-04-10 02:46:32 +00:00
|
|
|
# option.
|
2012-04-11 16:45:52 +00:00
|
|
|
#
|
|
|
|
# Example:
|
2010-12-15 22:34:19 +00:00
|
|
|
# it { should belong_to(:parent) }
|
2014-02-11 03:06:18 +00:00
|
|
|
# it { should belong_to(:parent).touch }
|
|
|
|
# it { should belong_to(:parent).validate }
|
|
|
|
# it { should belong_to(:parent).class_name("ModelClassName") }
|
2010-12-15 22:34:19 +00:00
|
|
|
#
|
|
|
|
def belong_to(name)
|
|
|
|
AssociationMatcher.new(:belongs_to, name)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Ensures that the has_many relationship exists. Will also test that the
|
|
|
|
# associated table has the required columns. Works with polymorphic
|
|
|
|
# associations.
|
|
|
|
#
|
|
|
|
# Options:
|
|
|
|
# * <tt>through</tt> - association name for <tt>has_many :through</tt>
|
|
|
|
# * <tt>dependent</tt> - tests that the association makes use of the
|
|
|
|
# dependent option.
|
2014-02-11 03:06:18 +00:00
|
|
|
# * <tt>class_name</tt> - tests that the association resoves to class_name.
|
|
|
|
# * <tt>autosave</tt> - tests that the association makes use of the
|
2014-01-22 20:40:38 +00:00
|
|
|
# autosave option.
|
2014-02-11 03:06:18 +00:00
|
|
|
# * <tt>validate</tt> - tests that the association makes use of the validate
|
2012-04-11 16:45:52 +00:00
|
|
|
# option.
|
2010-12-15 22:34:19 +00:00
|
|
|
#
|
|
|
|
# Example:
|
|
|
|
# it { should have_many(:friends) }
|
|
|
|
# it { should have_many(:enemies).through(:friends) }
|
|
|
|
# it { should have_many(:enemies).dependent(:destroy) }
|
2014-02-11 03:06:18 +00:00
|
|
|
# it { should have_many(:friends).autosave }
|
|
|
|
# it { should have_many(:friends).validate }
|
|
|
|
# it { should have_many(:friends).class_name("Friend") }
|
2010-12-15 22:34:19 +00:00
|
|
|
#
|
|
|
|
def have_many(name)
|
|
|
|
AssociationMatcher.new(:has_many, name)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Ensure that the has_one relationship exists. Will also test that the
|
|
|
|
# associated table has the required columns. Works with polymorphic
|
|
|
|
# associations.
|
|
|
|
#
|
|
|
|
# Options:
|
2014-02-11 03:06:18 +00:00
|
|
|
# * <tt>dependent</tt> - tests that the association makes use of the
|
2010-12-15 22:34:19 +00:00
|
|
|
# dependent option.
|
2014-02-11 03:06:18 +00:00
|
|
|
# * <tt>class_name</tt> - tests that the association resolves to class_name.
|
|
|
|
# * <tt>autosave</tt> - tests that the association makes use of the
|
2014-01-22 20:40:38 +00:00
|
|
|
# autosave option.
|
2014-02-11 03:06:18 +00:00
|
|
|
# * <tt>validate</tt> - tests that the association makes use of the validate
|
2012-04-11 16:45:52 +00:00
|
|
|
# option.
|
2010-12-15 22:34:19 +00:00
|
|
|
#
|
|
|
|
# Example:
|
|
|
|
# it { should have_one(:god) } # unless hindu
|
2014-02-11 03:06:18 +00:00
|
|
|
# it { should have_one(:god).dependent }
|
|
|
|
# it { should have_one(:god).autosave }
|
|
|
|
# it { should have_one(:god).validate }
|
|
|
|
# it { should have_one(:god).class_name("JHVH1") }
|
2010-12-15 22:34:19 +00:00
|
|
|
#
|
|
|
|
def have_one(name)
|
|
|
|
AssociationMatcher.new(:has_one, name)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Ensures that the has_and_belongs_to_many relationship exists, and that
|
|
|
|
# the join table is in place.
|
|
|
|
#
|
2012-04-11 16:45:52 +00:00
|
|
|
# Options:
|
2014-02-11 03:06:18 +00:00
|
|
|
# * <tt>class_name</tt> - tests that the association resolves to class_name.
|
|
|
|
# * <tt>validate</tt> - tests that the association makes use of the validate
|
2012-04-11 16:45:52 +00:00
|
|
|
# option.
|
|
|
|
#
|
|
|
|
# Example:
|
2010-12-15 22:34:19 +00:00
|
|
|
# it { should have_and_belong_to_many(:posts) }
|
2014-02-11 03:06:18 +00:00
|
|
|
# it { should have_and_belong_to_many(:posts).validate }
|
|
|
|
# it { should have_and_belong_to_many(:posts).class_name("Post") }
|
2010-12-15 22:34:19 +00:00
|
|
|
#
|
|
|
|
def have_and_belong_to_many(name)
|
|
|
|
AssociationMatcher.new(:has_and_belongs_to_many, name)
|
|
|
|
end
|
|
|
|
|
|
|
|
class AssociationMatcher # :nodoc:
|
Refactor AssociationMatcher to use new OptionVerifier
When using an association matcher you may have qualifiers on that
matcher which let you make assertions on options passed to the
association method that you are testing. For instance, has_many has a
:dependent option and so in order to test this you say something like
it { should have_many(:people).dependent(:destroy) }
In order to test such an option we have to compare the option you passed
with what the actual value of that option is. This is usually obtained
by looking at the reflection object of the association in question,
although it can be obtained by other means too.
Anyway, the code that does this comparison isn't terrible, but there are
two problems with it. First, it involves typecasting both expected and
actual values. For instance, this:
has_many :people, dependent: :destroy
it { should have_many(:people).dependent(:destroy) }
should be equivalent to:
has_many :people, dependent: :destroy
it { should have_many(:people).dependent('destroy') }
should be equivalent to:
has_many :people, dependent: 'destroy'
it { should have_many(:people).dependent(:destroy) }
Second, we are a little screwed if the method of obtaining the actual
value of the option changes depending on which Rails version you're
using.
So, OptionVerifier attempts to address both of these issues. It's a
little crazy, but it works.
I also moved some methods from AssociationMatcher to ModelReflector
where they really belong.
2013-08-16 21:38:10 +00:00
|
|
|
delegate :reflection, :model_class, :associated_class, :through?,
|
2014-04-12 20:49:01 +00:00
|
|
|
:join_table, :polymorphic?, to: :reflector
|
Refactor AssociationMatcher to use new OptionVerifier
When using an association matcher you may have qualifiers on that
matcher which let you make assertions on options passed to the
association method that you are testing. For instance, has_many has a
:dependent option and so in order to test this you say something like
it { should have_many(:people).dependent(:destroy) }
In order to test such an option we have to compare the option you passed
with what the actual value of that option is. This is usually obtained
by looking at the reflection object of the association in question,
although it can be obtained by other means too.
Anyway, the code that does this comparison isn't terrible, but there are
two problems with it. First, it involves typecasting both expected and
actual values. For instance, this:
has_many :people, dependent: :destroy
it { should have_many(:people).dependent(:destroy) }
should be equivalent to:
has_many :people, dependent: :destroy
it { should have_many(:people).dependent('destroy') }
should be equivalent to:
has_many :people, dependent: 'destroy'
it { should have_many(:people).dependent(:destroy) }
Second, we are a little screwed if the method of obtaining the actual
value of the option changes depending on which Rails version you're
using.
So, OptionVerifier attempts to address both of these issues. It's a
little crazy, but it works.
I also moved some methods from AssociationMatcher to ModelReflector
where they really belong.
2013-08-16 21:38:10 +00:00
|
|
|
|
2010-12-15 22:34:19 +00:00
|
|
|
def initialize(macro, name)
|
|
|
|
@macro = macro
|
2012-04-23 21:37:40 +00:00
|
|
|
@name = name
|
|
|
|
@options = {}
|
2013-06-07 14:14:27 +00:00
|
|
|
@submatchers = []
|
|
|
|
@missing = ''
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def through(through)
|
2013-06-14 15:34:22 +00:00
|
|
|
through_matcher = AssociationMatchers::ThroughMatcher.new(through, name)
|
2013-06-07 14:14:27 +00:00
|
|
|
add_submatcher(through_matcher)
|
2010-12-15 22:34:19 +00:00
|
|
|
self
|
|
|
|
end
|
|
|
|
|
|
|
|
def dependent(dependent)
|
2013-06-14 15:34:22 +00:00
|
|
|
dependent_matcher = AssociationMatchers::DependentMatcher.new(dependent, name)
|
2013-06-07 14:14:27 +00:00
|
|
|
add_submatcher(dependent_matcher)
|
2010-12-15 22:34:19 +00:00
|
|
|
self
|
|
|
|
end
|
|
|
|
|
2011-06-16 14:21:57 +00:00
|
|
|
def order(order)
|
2013-06-14 15:34:22 +00:00
|
|
|
order_matcher = AssociationMatchers::OrderMatcher.new(order, name)
|
2013-06-07 14:14:27 +00:00
|
|
|
add_submatcher(order_matcher)
|
2011-06-16 14:21:57 +00:00
|
|
|
self
|
2011-09-12 10:25:05 +00:00
|
|
|
end
|
2011-10-16 12:06:24 +00:00
|
|
|
|
2013-06-19 23:52:46 +00:00
|
|
|
def counter_cache(counter_cache = true)
|
|
|
|
counter_cache_matcher = AssociationMatchers::CounterCacheMatcher.new(counter_cache, name)
|
|
|
|
add_submatcher(counter_cache_matcher)
|
|
|
|
self
|
|
|
|
end
|
|
|
|
|
2014-03-19 03:13:28 +00:00
|
|
|
def inverse_of(inverse_of)
|
|
|
|
inverse_of_matcher =
|
|
|
|
AssociationMatchers::InverseOfMatcher.new(inverse_of, name)
|
|
|
|
add_submatcher(inverse_of_matcher)
|
|
|
|
self
|
|
|
|
end
|
|
|
|
|
2013-11-27 18:18:46 +00:00
|
|
|
def source(source)
|
|
|
|
source_matcher = AssociationMatchers::SourceMatcher.new(source, name)
|
|
|
|
add_submatcher(source_matcher)
|
|
|
|
self
|
|
|
|
end
|
|
|
|
|
2011-09-23 11:19:17 +00:00
|
|
|
def conditions(conditions)
|
2012-04-23 21:37:40 +00:00
|
|
|
@options[:conditions] = conditions
|
2011-09-23 11:19:17 +00:00
|
|
|
self
|
|
|
|
end
|
2011-06-16 14:21:57 +00:00
|
|
|
|
2014-01-22 20:40:38 +00:00
|
|
|
def autosave(autosave)
|
|
|
|
@options[:autosave] = autosave
|
|
|
|
self
|
|
|
|
end
|
|
|
|
|
2011-10-16 12:06:24 +00:00
|
|
|
def class_name(class_name)
|
2012-04-23 21:37:40 +00:00
|
|
|
@options[:class_name] = class_name
|
2011-10-16 12:06:24 +00:00
|
|
|
self
|
|
|
|
end
|
|
|
|
|
2012-08-24 05:48:17 +00:00
|
|
|
def with_foreign_key(foreign_key)
|
|
|
|
@options[:foreign_key] = foreign_key
|
|
|
|
self
|
|
|
|
end
|
|
|
|
|
2012-04-11 16:45:52 +00:00
|
|
|
def validate(validate = true)
|
2013-04-10 02:46:32 +00:00
|
|
|
@options[:validate] = validate
|
|
|
|
self
|
|
|
|
end
|
|
|
|
|
|
|
|
def touch(touch = true)
|
|
|
|
@options[:touch] = touch
|
2012-04-11 16:45:52 +00:00
|
|
|
self
|
|
|
|
end
|
|
|
|
|
2013-06-14 15:21:50 +00:00
|
|
|
def description
|
2013-06-14 15:34:22 +00:00
|
|
|
description = "#{macro_description} #{name}"
|
|
|
|
description += " class_name => #{options[:class_name]}" if options.key?(:class_name)
|
|
|
|
[description, submatchers.map(&:description)].flatten.join(' ')
|
2013-06-14 15:21:50 +00:00
|
|
|
end
|
|
|
|
|
2013-12-24 11:24:27 +00:00
|
|
|
def failure_message
|
2013-06-14 15:34:22 +00:00
|
|
|
"Expected #{expectation} (#{missing_options})"
|
2013-06-14 15:21:50 +00:00
|
|
|
end
|
2013-12-24 11:24:27 +00:00
|
|
|
alias failure_message_for_should failure_message
|
2013-06-14 15:21:50 +00:00
|
|
|
|
2013-12-24 11:24:27 +00:00
|
|
|
def failure_message_when_negated
|
2013-06-14 15:21:50 +00:00
|
|
|
"Did not expect #{expectation}"
|
|
|
|
end
|
2013-12-24 11:24:27 +00:00
|
|
|
alias failure_message_for_should_not failure_message_when_negated
|
2013-06-14 15:21:50 +00:00
|
|
|
|
2010-12-15 22:34:19 +00:00
|
|
|
def matches?(subject)
|
|
|
|
@subject = subject
|
|
|
|
association_exists? &&
|
|
|
|
macro_correct? &&
|
2014-04-12 20:49:01 +00:00
|
|
|
(polymorphic? || class_exists?) &&
|
2010-12-15 22:34:19 +00:00
|
|
|
foreign_key_exists? &&
|
2011-10-16 12:06:24 +00:00
|
|
|
class_name_correct? &&
|
2014-01-22 20:40:38 +00:00
|
|
|
autosave_correct? &&
|
2011-09-23 11:19:17 +00:00
|
|
|
conditions_correct? &&
|
2012-04-11 16:45:52 +00:00
|
|
|
join_table_exists? &&
|
2013-04-10 02:46:32 +00:00
|
|
|
validate_correct? &&
|
2013-06-07 14:14:27 +00:00
|
|
|
touch_correct? &&
|
|
|
|
submatchers_match?
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
|
2013-06-14 15:21:50 +00:00
|
|
|
private
|
|
|
|
|
2013-06-14 15:34:22 +00:00
|
|
|
attr_reader :submatchers, :missing, :subject, :macro, :name, :options
|
|
|
|
|
Refactor AssociationMatcher to use new OptionVerifier
When using an association matcher you may have qualifiers on that
matcher which let you make assertions on options passed to the
association method that you are testing. For instance, has_many has a
:dependent option and so in order to test this you say something like
it { should have_many(:people).dependent(:destroy) }
In order to test such an option we have to compare the option you passed
with what the actual value of that option is. This is usually obtained
by looking at the reflection object of the association in question,
although it can be obtained by other means too.
Anyway, the code that does this comparison isn't terrible, but there are
two problems with it. First, it involves typecasting both expected and
actual values. For instance, this:
has_many :people, dependent: :destroy
it { should have_many(:people).dependent(:destroy) }
should be equivalent to:
has_many :people, dependent: :destroy
it { should have_many(:people).dependent('destroy') }
should be equivalent to:
has_many :people, dependent: 'destroy'
it { should have_many(:people).dependent(:destroy) }
Second, we are a little screwed if the method of obtaining the actual
value of the option changes depending on which Rails version you're
using.
So, OptionVerifier attempts to address both of these issues. It's a
little crazy, but it works.
I also moved some methods from AssociationMatcher to ModelReflector
where they really belong.
2013-08-16 21:38:10 +00:00
|
|
|
def reflector
|
|
|
|
@reflector ||= AssociationMatchers::ModelReflector.new(subject, name)
|
|
|
|
end
|
|
|
|
|
|
|
|
def option_verifier
|
|
|
|
@option_verifier ||= AssociationMatchers::OptionVerifier.new(reflector)
|
|
|
|
end
|
|
|
|
|
2013-06-14 15:21:50 +00:00
|
|
|
def add_submatcher(matcher)
|
|
|
|
@submatchers << matcher
|
2013-06-07 14:14:27 +00:00
|
|
|
end
|
|
|
|
|
2013-06-14 15:21:50 +00:00
|
|
|
def macro_description
|
2013-06-14 15:34:22 +00:00
|
|
|
case macro.to_s
|
2013-06-14 15:21:50 +00:00
|
|
|
when 'belongs_to'
|
|
|
|
'belong to'
|
|
|
|
when 'has_many'
|
|
|
|
'have many'
|
|
|
|
when 'has_one'
|
|
|
|
'have one'
|
|
|
|
when 'has_and_belongs_to_many'
|
|
|
|
'have and belong to many'
|
|
|
|
end
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
|
2013-06-14 15:21:50 +00:00
|
|
|
def expectation
|
2013-06-14 15:34:22 +00:00
|
|
|
"#{model_class.name} to have a #{macro} association called #{name}"
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
|
2013-06-14 15:34:22 +00:00
|
|
|
def missing_options
|
|
|
|
[missing, failing_submatchers.map(&:missing_option)].flatten.join
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
|
2013-06-14 15:21:50 +00:00
|
|
|
def failing_submatchers
|
2013-06-14 15:34:22 +00:00
|
|
|
@failing_submatchers ||= submatchers.select do |matcher|
|
|
|
|
!matcher.matches?(subject)
|
2013-06-14 15:21:50 +00:00
|
|
|
end
|
|
|
|
end
|
2010-12-15 22:34:19 +00:00
|
|
|
|
|
|
|
def association_exists?
|
|
|
|
if reflection.nil?
|
2013-06-14 15:34:22 +00:00
|
|
|
@missing = "no association called #{name}"
|
2010-12-15 22:34:19 +00:00
|
|
|
false
|
|
|
|
else
|
|
|
|
true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def macro_correct?
|
2013-06-14 15:34:22 +00:00
|
|
|
if reflection.macro == macro
|
2010-12-15 22:34:19 +00:00
|
|
|
true
|
2013-12-31 19:54:21 +00:00
|
|
|
elsif reflection.macro == :has_many
|
|
|
|
macro == :has_and_belongs_to_many &&
|
|
|
|
reflection.name == @name
|
2010-12-15 22:34:19 +00:00
|
|
|
else
|
|
|
|
@missing = "actual association type was #{reflection.macro}"
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def foreign_key_exists?
|
|
|
|
!(belongs_foreign_key_missing? || has_foreign_key_missing?)
|
|
|
|
end
|
|
|
|
|
|
|
|
def belongs_foreign_key_missing?
|
2013-06-14 15:34:22 +00:00
|
|
|
macro == :belongs_to && !class_has_foreign_key?(model_class)
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def has_foreign_key_missing?
|
2013-06-14 15:34:22 +00:00
|
|
|
[:has_many, :has_one].include?(macro) &&
|
2010-12-15 22:34:19 +00:00
|
|
|
!through? &&
|
|
|
|
!class_has_foreign_key?(associated_class)
|
|
|
|
end
|
|
|
|
|
2011-10-16 12:06:24 +00:00
|
|
|
def class_name_correct?
|
2013-06-14 15:34:22 +00:00
|
|
|
if options.key?(:class_name)
|
Refactor AssociationMatcher to use new OptionVerifier
When using an association matcher you may have qualifiers on that
matcher which let you make assertions on options passed to the
association method that you are testing. For instance, has_many has a
:dependent option and so in order to test this you say something like
it { should have_many(:people).dependent(:destroy) }
In order to test such an option we have to compare the option you passed
with what the actual value of that option is. This is usually obtained
by looking at the reflection object of the association in question,
although it can be obtained by other means too.
Anyway, the code that does this comparison isn't terrible, but there are
two problems with it. First, it involves typecasting both expected and
actual values. For instance, this:
has_many :people, dependent: :destroy
it { should have_many(:people).dependent(:destroy) }
should be equivalent to:
has_many :people, dependent: :destroy
it { should have_many(:people).dependent('destroy') }
should be equivalent to:
has_many :people, dependent: 'destroy'
it { should have_many(:people).dependent(:destroy) }
Second, we are a little screwed if the method of obtaining the actual
value of the option changes depending on which Rails version you're
using.
So, OptionVerifier attempts to address both of these issues. It's a
little crazy, but it works.
I also moved some methods from AssociationMatcher to ModelReflector
where they really belong.
2013-08-16 21:38:10 +00:00
|
|
|
if option_verifier.correct_for_string?(:class_name, options[:class_name])
|
2012-04-23 21:37:40 +00:00
|
|
|
true
|
|
|
|
else
|
2013-06-14 15:34:22 +00:00
|
|
|
@missing = "#{name} should resolve to #{options[:class_name]} for class_name"
|
2012-04-23 21:37:40 +00:00
|
|
|
false
|
|
|
|
end
|
2011-10-16 12:06:24 +00:00
|
|
|
else
|
2012-04-23 21:37:40 +00:00
|
|
|
true
|
2011-10-16 12:06:24 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-01-10 17:25:14 +00:00
|
|
|
def class_exists?
|
|
|
|
associated_class
|
|
|
|
true
|
|
|
|
rescue NameError
|
|
|
|
@missing = "#{reflection.class_name} does not exist"
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
2014-01-22 20:40:38 +00:00
|
|
|
def autosave_correct?
|
|
|
|
if options.key?(:autosave)
|
|
|
|
if option_verifier.correct_for_boolean?(:autosave, options[:autosave])
|
|
|
|
true
|
|
|
|
else
|
|
|
|
@missing = "#{name} should have autosave set to #{options[:autosave]}"
|
|
|
|
false
|
|
|
|
end
|
|
|
|
else
|
|
|
|
true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-09-23 11:19:17 +00:00
|
|
|
def conditions_correct?
|
2013-06-14 15:34:22 +00:00
|
|
|
if options.key?(:conditions)
|
2013-05-14 02:42:12 +00:00
|
|
|
if option_verifier.correct_for_relation_clause?(:conditions, options[:conditions])
|
2012-04-23 21:37:40 +00:00
|
|
|
true
|
|
|
|
else
|
2013-06-14 15:34:22 +00:00
|
|
|
@missing = "#{name} should have the following conditions: #{options[:conditions]}"
|
2012-04-23 21:37:40 +00:00
|
|
|
false
|
|
|
|
end
|
2011-09-23 11:19:17 +00:00
|
|
|
else
|
2012-04-23 21:37:40 +00:00
|
|
|
true
|
2011-09-23 11:19:17 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-12-15 22:34:19 +00:00
|
|
|
def join_table_exists?
|
2013-06-14 15:34:22 +00:00
|
|
|
if macro != :has_and_belongs_to_many ||
|
2012-09-18 19:31:17 +00:00
|
|
|
model_class.connection.tables.include?(join_table)
|
2010-12-15 22:34:19 +00:00
|
|
|
true
|
|
|
|
else
|
|
|
|
@missing = "join table #{join_table} doesn't exist"
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-04-11 16:45:52 +00:00
|
|
|
def validate_correct?
|
Refactor AssociationMatcher to use new OptionVerifier
When using an association matcher you may have qualifiers on that
matcher which let you make assertions on options passed to the
association method that you are testing. For instance, has_many has a
:dependent option and so in order to test this you say something like
it { should have_many(:people).dependent(:destroy) }
In order to test such an option we have to compare the option you passed
with what the actual value of that option is. This is usually obtained
by looking at the reflection object of the association in question,
although it can be obtained by other means too.
Anyway, the code that does this comparison isn't terrible, but there are
two problems with it. First, it involves typecasting both expected and
actual values. For instance, this:
has_many :people, dependent: :destroy
it { should have_many(:people).dependent(:destroy) }
should be equivalent to:
has_many :people, dependent: :destroy
it { should have_many(:people).dependent('destroy') }
should be equivalent to:
has_many :people, dependent: 'destroy'
it { should have_many(:people).dependent(:destroy) }
Second, we are a little screwed if the method of obtaining the actual
value of the option changes depending on which Rails version you're
using.
So, OptionVerifier attempts to address both of these issues. It's a
little crazy, but it works.
I also moved some methods from AssociationMatcher to ModelReflector
where they really belong.
2013-08-16 21:38:10 +00:00
|
|
|
if option_verifier.correct_for_boolean?(:validate, options[:validate])
|
2013-04-10 02:46:32 +00:00
|
|
|
true
|
|
|
|
else
|
2014-01-17 20:20:44 +00:00
|
|
|
@missing = "#{name} should have validate: #{options[:validate]}"
|
2013-04-10 02:46:32 +00:00
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def touch_correct?
|
Refactor AssociationMatcher to use new OptionVerifier
When using an association matcher you may have qualifiers on that
matcher which let you make assertions on options passed to the
association method that you are testing. For instance, has_many has a
:dependent option and so in order to test this you say something like
it { should have_many(:people).dependent(:destroy) }
In order to test such an option we have to compare the option you passed
with what the actual value of that option is. This is usually obtained
by looking at the reflection object of the association in question,
although it can be obtained by other means too.
Anyway, the code that does this comparison isn't terrible, but there are
two problems with it. First, it involves typecasting both expected and
actual values. For instance, this:
has_many :people, dependent: :destroy
it { should have_many(:people).dependent(:destroy) }
should be equivalent to:
has_many :people, dependent: :destroy
it { should have_many(:people).dependent('destroy') }
should be equivalent to:
has_many :people, dependent: 'destroy'
it { should have_many(:people).dependent(:destroy) }
Second, we are a little screwed if the method of obtaining the actual
value of the option changes depending on which Rails version you're
using.
So, OptionVerifier attempts to address both of these issues. It's a
little crazy, but it works.
I also moved some methods from AssociationMatcher to ModelReflector
where they really belong.
2013-08-16 21:38:10 +00:00
|
|
|
if option_verifier.correct_for_boolean?(:touch, options[:touch])
|
2012-04-11 16:45:52 +00:00
|
|
|
true
|
|
|
|
else
|
2014-01-17 20:20:44 +00:00
|
|
|
@missing = "#{name} should have touch: #{options[:touch]}"
|
2012-04-11 16:45:52 +00:00
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-12-15 22:34:19 +00:00
|
|
|
def class_has_foreign_key?(klass)
|
2013-06-14 15:34:22 +00:00
|
|
|
if options.key?(:foreign_key)
|
2013-05-14 02:42:12 +00:00
|
|
|
option_verifier.correct_for_string?(:foreign_key, options[:foreign_key])
|
2010-12-15 22:34:19 +00:00
|
|
|
else
|
2012-08-24 05:48:17 +00:00
|
|
|
if klass.column_names.include?(foreign_key)
|
|
|
|
true
|
|
|
|
else
|
|
|
|
@missing = "#{klass} does not have a #{foreign_key} foreign key."
|
|
|
|
false
|
|
|
|
end
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def foreign_key
|
2012-03-23 23:50:08 +00:00
|
|
|
if foreign_key_reflection
|
|
|
|
if foreign_key_reflection.respond_to?(:foreign_key)
|
|
|
|
foreign_key_reflection.foreign_key.to_s
|
|
|
|
else
|
|
|
|
foreign_key_reflection.primary_key_name.to_s
|
|
|
|
end
|
2012-03-11 18:49:27 +00:00
|
|
|
end
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
|
2012-03-23 23:50:08 +00:00
|
|
|
def foreign_key_reflection
|
2013-06-14 15:34:22 +00:00
|
|
|
if [:has_one, :has_many].include?(macro) && reflection.options.include?(:inverse_of)
|
2012-03-23 23:50:08 +00:00
|
|
|
associated_class.reflect_on_association(reflection.options[:inverse_of])
|
|
|
|
else
|
|
|
|
reflection
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-06-14 15:21:50 +00:00
|
|
|
def submatchers_match?
|
|
|
|
failing_submatchers.empty?
|
2010-12-15 22:34:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|