class Shoulda::Matchers::ActiveRecord::AssociationMatcher

@private

Attributes

macro[R]
missing[R]
name[R]
options[R]
subject[R]
submatchers[R]

Public Class Methods

new(macro, name) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 888
def initialize(macro, name)
  @macro = macro
  @name = name
  @options = {}
  @submatchers = []
  @missing = ''
end

Public Instance Methods

autosave(autosave) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 938
def autosave(autosave)
  @options[:autosave] = autosave
  self
end
class_name(class_name) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 943
def class_name(class_name)
  @options[:class_name] = class_name
  self
end
conditions(conditions) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 933
def conditions(conditions)
  @options[:conditions] = conditions
  self
end
counter_cache(counter_cache = true) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 914
def counter_cache(counter_cache = true)
  counter_cache_matcher = AssociationMatchers::CounterCacheMatcher.new(counter_cache, name)
  add_submatcher(counter_cache_matcher)
  self
end
dependent(dependent) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 902
def dependent(dependent)
  dependent_matcher = AssociationMatchers::DependentMatcher.new(dependent, name)
  add_submatcher(dependent_matcher)
  self
end
description() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 973
def description
  description = "#{macro_description} #{name}"
  description += " class_name => #{options[:class_name]}" if options.key?(:class_name)
  [description, submatchers.map(&:description)].flatten.join(' ')
end
failure_message() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 979
def failure_message
  "Expected #{expectation} (#{missing_options})"
end
failure_message_when_negated() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 983
def failure_message_when_negated
  "Did not expect #{expectation}"
end
inverse_of(inverse_of) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 920
def inverse_of(inverse_of)
  inverse_of_matcher =
    AssociationMatchers::InverseOfMatcher.new(inverse_of, name)
  add_submatcher(inverse_of_matcher)
  self
end
join_table(join_table_name) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 968
def join_table(join_table_name)
  @options[:join_table_name] = join_table_name
  self
end
join_table_name() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1003
def join_table_name
  options[:join_table_name] || reflector.join_table_name
end
matches?(subject) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 987
def matches?(subject)
  @subject = subject
  association_exists? &&
    macro_correct? &&
    (polymorphic? || class_exists?) &&
    foreign_key_exists? &&
    primary_key_exists? &&
    class_name_correct? &&
    join_table_correct? &&
    autosave_correct? &&
    conditions_correct? &&
    validate_correct? &&
    touch_correct? &&
    submatchers_match?
end
option_verifier() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1007
def option_verifier
  @option_verifier ||= AssociationMatchers::OptionVerifier.new(reflector)
end
order(order) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 908
def order(order)
  order_matcher = AssociationMatchers::OrderMatcher.new(order, name)
  add_submatcher(order_matcher)
  self
end
source(source) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 927
def source(source)
  source_matcher = AssociationMatchers::SourceMatcher.new(source, name)
  add_submatcher(source_matcher)
  self
end
through(through) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 896
def through(through)
  through_matcher = AssociationMatchers::ThroughMatcher.new(through, name)
  add_submatcher(through_matcher)
  self
end
touch(touch = true) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 963
def touch(touch = true)
  @options[:touch] = touch
  self
end
validate(validate = true) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 958
def validate(validate = true)
  @options[:validate] = validate
  self
end
with_foreign_key(foreign_key) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 948
def with_foreign_key(foreign_key)
  @options[:foreign_key] = foreign_key
  self
end
with_primary_key(primary_key) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 953
def with_primary_key(primary_key)
  @options[:primary_key] = primary_key
  self
end

Protected Instance Methods

add_submatcher(matcher) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1019
def add_submatcher(matcher)
  @submatchers << matcher
end
association_exists?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1059
def association_exists?
  if reflection.nil?
    @missing = "no association called #{name}"
    false
  else
    true
  end
end
autosave_correct?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1138
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
belongs_foreign_key_missing?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1093
def belongs_foreign_key_missing?
  macro == :belongs_to && !class_has_foreign_key?(model_class)
end
class_exists?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1130
def class_exists?
  associated_class
  true
rescue NameError
  @missing = "#{reflection.class_name} does not exist"
  false
end
class_has_foreign_key?(klass) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1182
def class_has_foreign_key?(klass)
  if options.key?(:foreign_key)
    option_verifier.correct_for_string?(:foreign_key, options[:foreign_key])
  elsif column_names_for(klass).include?(foreign_key)
    true
  else
    @missing = "#{klass} does not have a #{foreign_key} foreign key."
    false
  end
end
class_name_correct?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1103
def class_name_correct?
  if options.key?(:class_name)
    if option_verifier.correct_for_constant?(:class_name, options[:class_name])
      true
    else
      @missing = "#{name} should resolve to #{options[:class_name]} for class_name"
      false
    end
  else
    true
  end
end
column_names_for(klass) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1227
def column_names_for(klass)
  klass.column_names
rescue ::ActiveRecord::StatementInvalid
  []
end
conditions_correct?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1151
def conditions_correct?
  if options.key?(:conditions)
    if option_verifier.correct_for_relation_clause?(:conditions, options[:conditions])
      true
    else
      @missing = "#{name} should have the following conditions: #{options[:conditions]}"
      false
    end
  else
    true
  end
end
expectation() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1036
def expectation
  "#{model_class.name} to have a #{macro} association called #{name}"
end
failing_submatchers() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1045
def failing_submatchers
  @failing_submatchers ||= submatchers.reject do |matcher|
    matcher.matches?(subject)
  end
end
foreign_key() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1206
def foreign_key
  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
  end
end
foreign_key_exists?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1085
def foreign_key_exists?
  !(belongs_foreign_key_missing? || has_foreign_key_missing?)
end
foreign_key_reflection() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1216
def foreign_key_reflection
  if [:has_one, :has_many].include?(macro) && reflection.options.include?(:inverse_of)
    associated_class.reflect_on_association(reflection.options[:inverse_of])
  else
    reflection
  end
end
has_foreign_key_missing?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1097
def has_foreign_key_missing?
  [:has_many, :has_one].include?(macro) &&
    !through? &&
    !class_has_foreign_key?(associated_class)
end
join_table_correct?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1116
def join_table_correct?
  if macro != :has_and_belongs_to_many || join_table_matcher.matches?(@subject)
    true
  else
    @missing = join_table_matcher.failure_message
    false
  end
end
join_table_matcher() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1125
def join_table_matcher
  @join_table_matcher ||=
    AssociationMatchers::JoinTableMatcher.new(self, reflector)
end
macro_correct?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1068
def macro_correct?
  if reflection.macro == macro
    true
  elsif reflection.macro == :has_many
    macro == :has_and_belongs_to_many &&
      reflection.name == @name
  else
    @missing = "actual association type was #{reflection.macro}"
    false
  end
end
macro_description() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1023
def macro_description
  case macro.to_s
  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
end
macro_supports_primary_key?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1080
def macro_supports_primary_key?
  macro == :belongs_to ||
    ([:has_many, :has_one].include?(macro) && !through?)
end
missing_options() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1040
def missing_options
  missing_options = [missing, missing_options_for_failing_submatchers]
  missing_options.flatten.compact.join(', ')
end
missing_options_for_failing_submatchers() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1051
def missing_options_for_failing_submatchers
  if defined?(@failing_submatchers)
    @failing_submatchers.map(&:missing_option)
  else
    []
  end
end
primary_key_correct?(klass) click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1193
def primary_key_correct?(klass)
  if options.key?(:primary_key)
    if option_verifier.correct_for_string?(:primary_key, options[:primary_key])
      true
    else
      @missing = "#{klass} does not have a #{options[:primary_key]} primary key"
      false
    end
  else
    true
  end
end
primary_key_exists?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1089
def primary_key_exists?
  !macro_supports_primary_key? || primary_key_correct?(model_class)
end
reflector() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1015
def reflector
  @reflector ||= AssociationMatchers::ModelReflector.new(subject, name)
end
submatchers_match?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1224
def submatchers_match?
  failing_submatchers.empty?
end
touch_correct?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1173
def touch_correct?
  if option_verifier.correct_for_boolean?(:touch, options[:touch])
    true
  else
    @missing = "#{name} should have touch: #{options[:touch]}"
    false
  end
end
validate_correct?() click to toggle source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1164
def validate_correct?
  if option_verifier.correct_for_boolean?(:validate, options[:validate])
    true
  else
    @missing = "#{name} should have validate: #{options[:validate]}"
    false
  end
end