Shoulda belongs_to with class_name and foreign_key
Asked Answered
H

5

24

I know you can easily test a belongs to relationship using Shoulda:

describe Dog dog
  it { should belong_to(:owner) }
end

Is it possible to test a more complicated belongs_to relationship using Shoulda? Something like this:

class Dog < ActiveRecord::Base
  belongs_to :owner, :class_name => "Person", :foreign_key => "person_id"
end
Housewife answered 2/9, 2012 at 8:15 Comment(0)
R
27

You should be able to use:

it { should belong_to(:owner).class_name('Person') }

Shoulda's belong_to matcher always reads the foreign_key from the association and tests that it is a valid field name, so you don't need to do anything more.

(See Shoulda::Matchers::ActiveRecord::AssociationMatcher#foreign_key_exists? and associated methods)

Rummel answered 2/9, 2012 at 9:9 Comment(0)
D
16

Now it's possible to test custom foreign keys:

it { should belong_to(:owner).class_name('Person').with_foreign_key('person_id') }

See : https://github.com/thoughtbot/shoulda-matchers/blob/master/lib/shoulda/matchers/active_record/association_matcher.rb#L122

Defalcate answered 28/8, 2013 at 7:44 Comment(0)
O
4

if association like

belongs_to :custom_profile, class_name: 'User', foreign_key: :custom_user_id, optional: true

then rspec should be

it { should belong_to(:custom_profile).class_name('User').with_foreign_key('custom_user_id').optional }

here optional used for optional: true, you can also remove it if optional true not required in your association

Orola answered 11/3, 2020 at 7:9 Comment(0)
I
3

So the should-matchers README is pretty light on the details, just having some examples. I found there is a lot more information in the RDoc of the classes, in the case of belongs_to take a look at association_matcher.rb. The first method is for belongs_to with the Rdoc

  # Ensure that the belongs_to relationship exists.
  #
  # Options:
  # * <tt>:class_name</tt> - tests that the association makes use of the class_name option.
  # * <tt>:validate</tt> - tests that the association makes use of the validate
  # option.
  #
  # Example:
  #   it { should belong_to(:parent) }
  #
  def belong_to(name)

So belongs_to only support tests for :class_name and :validate.

Invert answered 2/9, 2012 at 8:58 Comment(0)
P
3

I know I'm a bit late to the party, so my solution might require an up to date version of shoulda.

At the time of writing I'm at v 2.4.0.

I did not need class_name or with_foreign_key in my spec.

Make sure you specified class_name and foreign_key in your model.

# model.rb:  
belongs_to :owner, inverse_of: :properties, class_name: "User", foreign_key: :owner_id

# spec.rb:  
it { should belong_to(:owner) }

resulting output:

should belong to owner
Powerhouse answered 5/11, 2013 at 12:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.