# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1951 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
class Shoulda::Matchers::ActiveRecord::AssociationMatcher
@private
Constants
- MACROS
Attributes
Public Class Methods
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1398 def initialize(macro, name) @macro = macro @name = name @options = {} @submatchers = [] @missing = '' if macro == :belongs_to required(belongs_to_required_by_default?) end end
Public Instance Methods
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1474 def autosave(autosave) @options[:autosave] = autosave self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1484 def class_name(class_name) @options[:class_name] = class_name self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1464 def conditions(conditions) @options[:conditions] = conditions self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1437 def counter_cache(counter_cache = true) add_submatcher( AssociationMatchers::CounterCacheMatcher, counter_cache, name, ) self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1419 def dependent(dependent) add_submatcher( AssociationMatchers::DependentMatcher, dependent, name, ) self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1554 def description description = "#{macro_description} #{name}" if options.key?(:class_name) description += " class_name => #{options[:class_name]}" end [description, submatchers.map(&:description)].flatten.join(' ') end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1562 def failure_message "Expected #{expectation} (#{missing_options})" end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1566 def failure_message_when_negated "Did not expect #{expectation}" end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1479 def index_errors(index_errors) @options[:index_errors] = index_errors self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1446 def inverse_of(inverse_of) add_submatcher( AssociationMatchers::InverseOfMatcher, inverse_of, name, ) self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1544 def join_table(join_table_name) @options[:join_table_name] = join_table_name self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1592 def join_table_name options[:join_table_name] || reflector.join_table_name end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1570 def matches?(subject) @subject = subject association_exists? && macro_correct? && validate_inverse_of_through_association && (polymorphic? || class_exists?) && foreign_type_matches? && foreign_key_exists? && primary_key_exists? && query_constraints_exists? && class_name_correct? && join_table_correct? && autosave_correct? && index_errors_correct? && conditions_correct? && validate_correct? && touch_correct? && types_correct? && strict_loading_correct? && submatchers_match? end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1596 def option_verifier @_option_verifier ||= AssociationMatchers::OptionVerifier.new(reflector) end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1519 def optional(optional = true) remove_submatcher(AssociationMatchers::RequiredMatcher) add_submatcher( AssociationMatchers::OptionalMatcher, name, optional, ) self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1428 def order(order) add_submatcher( AssociationMatchers::OrderMatcher, order, name, ) self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1509 def required(required = true) remove_submatcher(AssociationMatchers::OptionalMatcher) add_submatcher( AssociationMatchers::RequiredMatcher, name, required, ) self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1455 def source(source) add_submatcher( AssociationMatchers::SourceMatcher, source, name, ) self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1539 def strict_loading(strict_loading = true) @options[:strict_loading] = strict_loading self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1410 def through(through) add_submatcher( AssociationMatchers::ThroughMatcher, through, name, ) self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1534 def touch(touch = true) @options[:touch] = touch self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1469 def types(types) @options[:types] = types self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1529 def validate(validate = true) @options[:validate] = validate self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1489 def with_foreign_key(foreign_key) @options[:foreign_key] = foreign_key self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1494 def with_foreign_type(foreign_type) @options[:foreign_type] = foreign_type self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1499 def with_primary_key(primary_key) @options[:primary_key] = primary_key self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1504 def with_query_constraints(query_constraints) @options[:query_constraints] = query_constraints self end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1549 def without_validating_presence remove_submatcher(AssociationMatchers::RequiredMatcher) self end
Protected Instance Methods
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1968 def actual_foreign_key return unless foreign_key_reflection if foreign_key_reflection.options[:foreign_key] foreign_key_reflection.options[:foreign_key] elsif foreign_key_reflection.respond_to?(:foreign_key) foreign_key_reflection.foreign_key else foreign_key_reflection.primary_key_name end end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1609 def add_submatcher(matcher_class, *args) remove_submatcher(matcher_class) submatchers << matcher_class.new(*args) end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1654 def association_exists? if reflection.nil? @missing = "no association called #{name}" false else true end end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1783 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
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1724 def belongs_foreign_key_missing? macro == :belongs_to && !class_has_foreign_key?(model_class) end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1728 def belongs_foreign_type_missing? macro == :belongs_to && !class_has_foreign_type?(model_class) end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 2011 def belongs_to_required_by_default? ::ActiveRecord::Base.belongs_to_required_by_default end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1775 def class_exists? associated_class true rescue NameError @missing = "#{reflection.class_name} does not exist" false end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1890 def class_has_foreign_key?(klass) @missing = validate_foreign_key(klass) @missing.nil? end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1904 def class_has_foreign_type?(klass) if options.key?(:foreign_type) && !foreign_type_correct? @missing = foreign_type_failure_message( klass, options[:foreign_type], ) false elsif !has_column?(klass, foreign_type) @missing = foreign_type_failure_message(klass, foreign_type) false else true end end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1742 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
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 2005 def column_names_for(klass) klass.column_names rescue ::ActiveRecord::StatementInvalid [] end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1816 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
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1624 def expectation expectation = "#{model_class.name} to have a #{macro} association called #{name}" if through? expectation << " through #{reflector.has_and_belongs_to_many_name}" end expectation end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1640 def failing_submatchers @_failing_submatchers ||= submatchers.reject do |matcher| matcher.matches?(subject) end end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1929 def foreign_key_correct? option_verifier.correct_for_string?( :foreign_key, options[:foreign_key], ) end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1691 def foreign_key_exists? !(belongs_foreign_key_missing? || has_foreign_key_missing?) end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1943 def foreign_key_failure_message(klass, foreign_key) "#{klass} does not have a #{foreign_key} foreign key." end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1980 def foreign_key_reflection if [:has_one, :has_many].include?(macro) && reflection.options.include?(:inverse_of) && reflection.options[:inverse_of] != false associated_class.reflect_on_association( reflection.options[:inverse_of], ) else reflection end end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1993 def foreign_type if [:has_one, :has_many].include?(macro) reflection.type else reflection.foreign_type end end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1936 def foreign_type_correct? option_verifier.correct_for_string?( :foreign_type, options[:foreign_type], ) end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1947 def foreign_type_failure_message(klass, foreign_type) "#{klass} does not have a #{foreign_type} foreign type." end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1695 def foreign_type_matches? !options.key?(:foreign_type) || ( !belongs_foreign_type_missing? && !has_foreign_type_missing? ) end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1687 def has_association_not_through? [:has_many, :has_one].include?(macro) && !through? end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1920 def has_column?(klass, column) case column when Array column.all? { |c| has_column?(klass, c.to_s) } else column_names_for(klass).include?(column.to_s) end end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1732 def has_foreign_key_missing? has_association_not_through? && !class_has_foreign_key?(associated_class) end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1737 def has_foreign_type_missing? has_association_not_through? && !class_has_foreign_type?(associated_class) end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1800 def index_errors_correct? return true unless options.key?(:index_errors) if option_verifier.correct_for_boolean?( :index_errors, options[:index_errors], ) true else @missing = "#{name} should have index_errors set to " + options[:index_errors].to_s false end end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1759 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
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1768 def join_table_matcher @_join_table_matcher ||= AssociationMatchers::JoinTableMatcher.new( self, reflector, ) end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1663 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
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1620 def macro_description MACROS[macro.to_s] end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1683 def macro_is_not_through? macro == :belongs_to || has_association_not_through? end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1635 def missing_options missing_options = [missing, missing_options_for_failing_submatchers] missing_options.flatten.select(&:present?).join(', ') end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1646 def missing_options_for_failing_submatchers if defined?(@_failing_submatchers) @_failing_submatchers.map(&:missing_option) else [] end end
Source
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1702 def primary_key_exists? !macro_is_not_through? || primary_key_correct?(model_class) end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1710 def query_constraints_correct? if options.key?(:query_constraints) if option_verifier.correct_for_string?(:query_constraints, options[:query_constraints]) true else @missing = "#{model_class} should have \:query_constraints"\ " options set to #{options[:query_constraints]}" false end else true end end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1706 def query_constraints_exists? !macro_is_not_through? || query_constraints_correct? end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1605 def reflector @_reflector ||= AssociationMatchers::ModelReflector.new(subject, name) end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1614 def remove_submatcher(matcher_class) submatchers.delete_if do |submatcher| submatcher.is_a?(matcher_class) end end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1875 def strict_loading_correct? return true unless options.key?(:strict_loading) if option_verifier.correct_for_boolean?(:strict_loading, options[:strict_loading]) return true end @missing = [ "#{name} should have strict_loading set to ", options[:strict_loading].to_s, ].join false end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 2001 def submatchers_match? failing_submatchers.empty? end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1842 def touch_correct? if option_verifier.correct_for_boolean?(:touch, options[:touch]) true else @missing = "#{name} should have touch: #{options[:touch]}" false end end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1851 def types_correct? if options.key?(:types) types = options[:types] correct = types.all? do |type| scope_name = type.tableize.tr('/', '_') singular = scope_name.singularize query = "#{singular}?" Object.const_defined?(type) && @subject.respond_to?(query) && @subject.respond_to?(singular) end if correct true else @missing = "#{name} should have types: #{options[:types]}" false end else true end end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1833 def validate_correct? if option_verifier.correct_for_boolean?(:validate, options[:validate]) true else @missing = "#{name} should have validate: #{options[:validate]}" false end end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1896 def validate_foreign_key(klass) if options.key?(:foreign_key) && !foreign_key_correct? foreign_key_failure_message(klass, options[:foreign_key]) elsif !has_column?(klass, actual_foreign_key) foreign_key_failure_message(klass, actual_foreign_key) end end
Source
# File lib/shoulda/matchers/active_record/association_matcher.rb, line 1675 def validate_inverse_of_through_association reflector.validate_inverse_of_through_association! true rescue ::ActiveRecord::ActiveRecordError => e @missing = e.message false end