diff --git a/NEWS.md b/NEWS.md index 573d075a..a90c6a63 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # HEAD +* Changed the scope of AssociationMatcher methods from protected to private. + * Extracted `#order`, `#through`, and `#dependent` from AssociationMatcher as their own submatchers. diff --git a/lib/shoulda/matchers/active_record/association_matcher.rb b/lib/shoulda/matchers/active_record/association_matcher.rb index e41bf8ed..f7ffd2e7 100644 --- a/lib/shoulda/matchers/active_record/association_matcher.rb +++ b/lib/shoulda/matchers/active_record/association_matcher.rb @@ -98,24 +98,6 @@ module Shoulda # :nodoc: self end - def add_submatcher(matcher) - @submatchers << matcher - end - - def submatchers_match? - failing_submatchers.empty? - end - - def submatcher_failure_messages - failing_submatchers.map(&:failure_message_for_should) - end - - def failing_submatchers - @failing_submatchers ||= @submatchers.select do |matcher| - !matcher.matches?(@subject) - end - end - def conditions(conditions) @options[:conditions] = conditions self @@ -141,6 +123,20 @@ module Shoulda # :nodoc: self end + def description + description = "#{macro_description} #{@name}" + description += " class_name => #{@options[:class_name]}" if @options.key?(:class_name) + [description, @submatchers.map(&:description)].flatten.join(' ') + end + + def failure_message_for_should + "Expected #{expectation} (#{missing})" + end + + def failure_message_for_should_not + "Did not expect #{expectation}" + end + def matches?(subject) @subject = subject association_exists? && @@ -154,26 +150,39 @@ module Shoulda # :nodoc: submatchers_match? end - def failure_message_for_should - "Expected #{expectation} (#{missing})" + private + + def add_submatcher(matcher) + @submatchers << matcher + end + + 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 + + def expectation + "#{model_class.name} to have a #{@macro} association called #{@name}" end def missing - [[@missing] + failing_submatchers.map(&:missing_option)].compact.join + [@missing, failing_submatchers.map(&:missing_option)].flatten.join end - def failure_message_for_should_not - "Did not expect #{expectation}" + def failing_submatchers + @failing_submatchers ||= @submatchers.select do |matcher| + !matcher.matches?(@subject) + end end - def description - description = "#{macro_description} #{@name}" - description += " class_name => #{@options[:class_name]}" if @options.key?(:class_name) - [description, @submatchers.map(&:description)].flatten.join(' ') - end - - protected - def association_exists? if reflection.nil? @missing = "no association called #{@name}" @@ -183,6 +192,10 @@ module Shoulda # :nodoc: end end + def reflection + @reflection ||= model_class.reflect_on_association(@name) + end + def macro_correct? if reflection.macro == @macro true @@ -200,12 +213,24 @@ module Shoulda # :nodoc: @macro == :belongs_to && !class_has_foreign_key?(model_class) end + def model_class + @subject.class + end + def has_foreign_key_missing? [:has_many, :has_one].include?(@macro) && !through? && !class_has_foreign_key?(associated_class) end + def through? + reflection.options[:through] + end + + def associated_class + reflection.klass + end + def class_name_correct? if @options.key?(:class_name) if @options[:class_name].to_s == reflection.klass.to_s @@ -281,10 +306,6 @@ module Shoulda # :nodoc: end end - def model_class - @subject.class - end - def join_table if reflection.respond_to? :join_table reflection.join_table.to_s @@ -293,10 +314,6 @@ module Shoulda # :nodoc: end end - def associated_class - reflection.klass - end - def foreign_key if foreign_key_reflection if foreign_key_reflection.respond_to?(:foreign_key) @@ -307,14 +324,6 @@ module Shoulda # :nodoc: end end - def through? - reflection.options[:through] - end - - def reflection - @reflection ||= model_class.reflect_on_association(@name) - end - 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]) @@ -323,21 +332,8 @@ module Shoulda # :nodoc: end end - def expectation - "#{model_class.name} to have a #{@macro} association called #{@name}" - end - - 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 + def submatchers_match? + failing_submatchers.empty? end end end