mirror of
https://github.com/thoughtbot/shoulda-matchers.git
synced 2022-11-09 12:01:38 -05:00
Add with_primary_key
to AssociationMatchers
This commit is contained in:
parent
a009c83943
commit
0f34231d08
3 changed files with 137 additions and 0 deletions
3
NEWS.md
3
NEWS.md
|
@ -27,11 +27,14 @@
|
|||
* Tweak `allow_value` failure message so that it reads a bit nicer when listing
|
||||
existing errors.
|
||||
|
||||
* Add ability to test `:primary_key` option on associations. ([#597])
|
||||
|
||||
[#591]: https://github.com/thoughtbot/shoulda-matchers/pull/591
|
||||
[#592]: https://github.com/thoughtbot/shoulda-matchers/pull/592
|
||||
[#588]: https://github.com/thoughtbot/shoulda-matchers/pull/588
|
||||
[#584]: https://github.com/thoughtbot/shoulda-matchers/pull/584
|
||||
[#593]: https://github.com/thoughtbot/shoulda-matchers/pull/593
|
||||
[#597]: https://github.com/thoughtbot/shoulda-matchers/pull/597
|
||||
|
||||
# 2.7.0
|
||||
|
||||
|
|
|
@ -100,6 +100,28 @@ module Shoulda
|
|||
# should belong_to(:ancient_city).class_name('City')
|
||||
# end
|
||||
#
|
||||
# ##### with_primary_key
|
||||
#
|
||||
# Use `with_primary_key` to test usage of the `:primary_key` option.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# belongs_to :great_country, primary_key: 'country_id'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should belong_to(:great_country).
|
||||
# with_primary_key('country_id')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should belong_to(:great_country).
|
||||
# with_primary_key('country_id')
|
||||
# end
|
||||
#
|
||||
# ##### with_foreign_key
|
||||
#
|
||||
# Use `with_foreign_key` to test usage of the `:foreign_key` option.
|
||||
|
@ -295,6 +317,24 @@ module Shoulda
|
|||
# should have_many(:hopes).class_name('Dream')
|
||||
# end
|
||||
#
|
||||
# ##### with_primary_key
|
||||
#
|
||||
# Use `with_primary_key` to test usage of the `:primary_key` option.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_many :worries, primary_key: 'worrier_id'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_many(:worries).with_primaryu_key('worrier_id') }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_many(:worries).with_primary_key('worrier_id')
|
||||
# end
|
||||
#
|
||||
# ##### with_foreign_key
|
||||
#
|
||||
# Use `with_foreign_key` to test usage of the `:foreign_key` option.
|
||||
|
@ -511,6 +551,24 @@ module Shoulda
|
|||
# should have_one(:contract).dependent(:nullify)
|
||||
# end
|
||||
#
|
||||
# ##### with_primary_key
|
||||
#
|
||||
# Use `with_primary_key` to test usage of the `:primary_key` option.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_one :job, primary_key: 'worker_id'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_one(:job).with_primary_key('worker_id') }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_one(:job).with_primary_key('worker_id')
|
||||
# end
|
||||
#
|
||||
# ##### with_foreign_key
|
||||
#
|
||||
# Use `with_foreign_key` to test usage of the `:foreign_key` option.
|
||||
|
@ -814,6 +872,11 @@ module Shoulda
|
|||
self
|
||||
end
|
||||
|
||||
def with_primary_key(primary_key)
|
||||
@options[:primary_key] = primary_key
|
||||
self
|
||||
end
|
||||
|
||||
def validate(validate = true)
|
||||
@options[:validate] = validate
|
||||
self
|
||||
|
@ -846,6 +909,7 @@ module Shoulda
|
|||
macro_correct? &&
|
||||
(polymorphic? || class_exists?) &&
|
||||
foreign_key_exists? &&
|
||||
primary_key_exists? &&
|
||||
class_name_correct? &&
|
||||
join_table_correct? &&
|
||||
autosave_correct? &&
|
||||
|
@ -928,10 +992,19 @@ module Shoulda
|
|||
end
|
||||
end
|
||||
|
||||
def macro_supports_primary_key?
|
||||
macro == :belongs_to ||
|
||||
([:has_many, :has_one].include?(macro) && !through?)
|
||||
end
|
||||
|
||||
def foreign_key_exists?
|
||||
!(belongs_foreign_key_missing? || has_foreign_key_missing?)
|
||||
end
|
||||
|
||||
def primary_key_exists?
|
||||
!macro_supports_primary_key? || primary_key_correct?(model_class)
|
||||
end
|
||||
|
||||
def belongs_foreign_key_missing?
|
||||
macro == :belongs_to && !class_has_foreign_key?(model_class)
|
||||
end
|
||||
|
@ -1034,6 +1107,19 @@ module Shoulda
|
|||
end
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
def foreign_key
|
||||
if foreign_key_reflection
|
||||
if foreign_key_reflection.respond_to?(:foreign_key)
|
||||
|
|
|
@ -29,6 +29,22 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
|
|||
expect(Child.new).to belong_to(:parent)
|
||||
end
|
||||
|
||||
it 'accepts an association using an existing custom primary key' do
|
||||
define_model :parent
|
||||
define_model :child, parent_id: :integer, custom_primary_key: :integer do
|
||||
belongs_to :parent, primary_key: :custom_primary_key
|
||||
end
|
||||
expect(Child.new).to belong_to(:parent).with_primary_key(:custom_primary_key)
|
||||
end
|
||||
|
||||
it 'rejects an association with a bad :primary_key option' do
|
||||
matcher = belong_to(:parent).with_primary_key(:custom_primary_key)
|
||||
|
||||
expect(belonging_to_parent).not_to matcher
|
||||
|
||||
expect(matcher.failure_message).to match(/Child does not have a custom_primary_key primary key/)
|
||||
end
|
||||
|
||||
it 'accepts a polymorphic association' do
|
||||
define_model :child, parent_type: :string, parent_id: :integer do
|
||||
belongs_to :parent, polymorphic: true
|
||||
|
@ -288,6 +304,22 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
|
|||
expect(Parent.new).not_to have_many(:children)
|
||||
end
|
||||
|
||||
it 'accepts an association using an existing custom primary key' do
|
||||
define_model :child, parent_id: :integer
|
||||
define_model :parent, custom_primary_key: :integer do
|
||||
has_many :children, primary_key: :custom_primary_key
|
||||
end
|
||||
expect(Parent.new).to have_many(:children).with_primary_key(:custom_primary_key)
|
||||
end
|
||||
|
||||
it 'rejects an association with a bad :primary_key option' do
|
||||
matcher = have_many(:children).with_primary_key(:custom_primary_key)
|
||||
|
||||
expect(having_many_children).not_to matcher
|
||||
|
||||
expect(matcher.failure_message).to match(/Parent does not have a custom_primary_key primary key/)
|
||||
end
|
||||
|
||||
it 'rejects an association with a bad :as option' do
|
||||
define_model :child, caretaker_type: :string,
|
||||
caretaker_id: :integer
|
||||
|
@ -537,6 +569,22 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
|
|||
expect(Person.new).to have_one(:detail).with_foreign_key(:detailed_person_id)
|
||||
end
|
||||
|
||||
it 'accepts an association using an existing custom primary key' do
|
||||
define_model :detail, person_id: :integer
|
||||
define_model :person, custom_primary_key: :integer do
|
||||
has_one :detail, primary_key: :custom_primary_key
|
||||
end
|
||||
expect(Person.new).to have_one(:detail).with_primary_key(:custom_primary_key)
|
||||
end
|
||||
|
||||
it 'rejects an association with a bad :primary_key option' do
|
||||
matcher = have_one(:detail).with_primary_key(:custom_primary_key)
|
||||
|
||||
expect(having_one_detail).not_to matcher
|
||||
|
||||
expect(matcher.failure_message).to match(/Person does not have a custom_primary_key primary key/)
|
||||
end
|
||||
|
||||
it 'rejects an association with a bad :as option' do
|
||||
define_model :detail, detailable_id: :integer,
|
||||
detailable_type: :string
|
||||
|
|
Loading…
Reference in a new issue