Association matchers now support :source option
This commit is contained in:
parent
5c86571182
commit
803c06b0b0
5
NEWS.md
5
NEWS.md
|
@ -13,11 +13,14 @@
|
|||
* The `ensure_inclusion_of` matcher now works with a decimal column.
|
||||
|
||||
* Fix association matchers on Rails 3 so they work when used in conjunction with
|
||||
a submatcher such as #order and an association that has :include on it.
|
||||
a submatcher such as #order and an association that has `:include` on it.
|
||||
|
||||
* Fix a bug where `validate_uniqueness_of` would fail if the attribute under
|
||||
test had a limit of fewer than 16 characters.
|
||||
|
||||
* You can now test that your `has_many :through` or `has_one :through`
|
||||
associations are defined with a `:source` option.
|
||||
|
||||
# v 2.4.0
|
||||
|
||||
* Fix a bug with the `validate_numericality_of` matcher that would not allow the
|
||||
|
|
|
@ -618,6 +618,7 @@ The `have_many` matcher tests your `has_many` and `has_many :through` associatio
|
|||
class Person < ActiveRecord::Base
|
||||
has_many :friends
|
||||
has_many :acquaintances, through: :friends
|
||||
has_many :job_offers, through: :friends, source: :opportunities
|
||||
has_many :coins, -> { where(condition: 'mint') }
|
||||
has_many :shirts, -> { order('color') }
|
||||
has_many :hopes, class_name: 'Dream'
|
||||
|
@ -632,6 +633,7 @@ end
|
|||
describe Person do
|
||||
it { should have_many(:friends) }
|
||||
it { should have_many(:acquaintances).through(:friends) }
|
||||
it { should have_many(:job_offers).through(:friends).source(:opportunities) }
|
||||
it { should have_many(:coins).conditions(condition: 'mint') }
|
||||
it { should have_many(:shirts).order('color') }
|
||||
it { should have_many(:hopes).class_name('Dream') }
|
||||
|
@ -646,6 +648,7 @@ end
|
|||
class PersonTest < ActiveSupport::TestCase
|
||||
should have_many(:friends)
|
||||
should have_many(:acquaintances).through(:friends)
|
||||
should have_many(:job_offers).through(:friends).source(:opportunities)
|
||||
should have_many(:coins).conditions(condition: 'mint')
|
||||
should have_many(:shirts).order('color')
|
||||
should have_many(:hopes).class_name('Dream')
|
||||
|
@ -665,6 +668,7 @@ The `have_one` matcher tests your `has_one` and `has_one :through` associations.
|
|||
class Person < ActiveRecord::Base
|
||||
has_one :partner
|
||||
has_one :life, through: :partner
|
||||
has_one :car, through: :partner, source: :vehicle
|
||||
has_one :pet, -> { where('weight < 80') }
|
||||
has_one :focus, -> { order('priority desc') }
|
||||
has_one :chance, class_name: 'Opportunity'
|
||||
|
@ -677,6 +681,7 @@ end
|
|||
describe Person do
|
||||
it { should have_one(:partner) }
|
||||
it { should have_one(:life).through(:partner) }
|
||||
it { should have_one(:car).through(:partner).source(:vehicle) }
|
||||
it { should have_one(:pet).conditions('weight < 80') }
|
||||
it { should have_one(:focus).order('priority desc') }
|
||||
it { should have_one(:chance).class_name('Opportunity') }
|
||||
|
|
|
@ -3,6 +3,7 @@ require 'shoulda/matchers/active_record/association_matchers/counter_cache_match
|
|||
require 'shoulda/matchers/active_record/association_matchers/order_matcher'
|
||||
require 'shoulda/matchers/active_record/association_matchers/through_matcher'
|
||||
require 'shoulda/matchers/active_record/association_matchers/dependent_matcher'
|
||||
require 'shoulda/matchers/active_record/association_matchers/source_matcher'
|
||||
require 'shoulda/matchers/active_record/association_matchers/model_reflector'
|
||||
require 'shoulda/matchers/active_record/association_matchers/model_reflection'
|
||||
require 'shoulda/matchers/active_record/association_matchers/option_verifier'
|
||||
|
|
|
@ -109,6 +109,12 @@ module Shoulda # :nodoc:
|
|||
self
|
||||
end
|
||||
|
||||
def source(source)
|
||||
source_matcher = AssociationMatchers::SourceMatcher.new(source, name)
|
||||
add_submatcher(source_matcher)
|
||||
self
|
||||
end
|
||||
|
||||
def conditions(conditions)
|
||||
@options[:conditions] = conditions
|
||||
self
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Matchers
|
||||
module ActiveRecord # :nodoc:
|
||||
module AssociationMatchers
|
||||
class SourceMatcher
|
||||
attr_accessor :missing_option
|
||||
|
||||
def initialize(source, name)
|
||||
@source = source
|
||||
@name = name
|
||||
@missing_option = ''
|
||||
end
|
||||
|
||||
def description
|
||||
"source => #{source}"
|
||||
end
|
||||
|
||||
def matches?(subject)
|
||||
self.subject = ModelReflector.new(subject, name)
|
||||
|
||||
if option_verifier.correct_for_string?(:source, source)
|
||||
true
|
||||
else
|
||||
self.missing_option = "#{name} should have #{source} as source option"
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_accessor :subject, :source, :name
|
||||
|
||||
def option_verifier
|
||||
@option_verifier ||= OptionVerifier.new(subject)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -282,6 +282,19 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
|
|||
matcher.failure_message_for_should.should =~ /children should have destroy dependency/
|
||||
end
|
||||
|
||||
it 'accepts an association with a valid :source option' do
|
||||
having_many_children(:source => :user).
|
||||
should have_many(:children).source(:user)
|
||||
end
|
||||
|
||||
it 'rejects an association with a bad :source option' do
|
||||
matcher = have_many(:children).source(:user)
|
||||
|
||||
having_many_children.should_not matcher
|
||||
|
||||
matcher.failure_message_for_should.should =~ /children should have user as source option/
|
||||
end
|
||||
|
||||
it 'accepts an association with a valid :order option' do
|
||||
having_many_children(:order => :id).
|
||||
should have_many(:children).order(:id)
|
||||
|
|
Loading…
Reference in New Issue