I have a has many through relationship model like this:
class Physician < ApplicationRecord
has_many :appointments
has_many :patients, through: :appointments
end
class Appointment < ApplicationRecord
belongs_to :physician
belongs_to :patient
end
class Patient < ApplicationRecord
has_many :appointments
has_many :physicians, through: :appointments
end
I need to create a Physician which has many Patients, right? so on my test:
let!(:physician) { create(:physician) }
let!(:patients) { create_list(:patients, 2) }
and I did this:
before { physician.patients << patients }
I want to test the generated json with this
expect(physician.as_json).to eq({
"id" => physician.id,
"name" => physician.name,
"patients" => physician.patients
})
I am expecting it would pass but it failed because of this #<ActiveRecord::Associations::CollectionProxy>
I checked using binding.pry
by this:
physician.patients == patients
and the result was true
Would you mind helping me, am I missing something here?
To link physician and patients just pass the key to create_list
:
let!(:patients) { create_list(:patients, 2, physician: physician ) }
Or you can declare it as:
let(:physician) { create(:physician, patients: build_list(patients: 2)) }
But the test itself is still broken as mentioned by @TomLord. You need test the resulting hash - as including an association will cause it be converted to a serialized hash:
{
"id" => 1,
"name" => "Dr Suess",
"patients" => [
{
"id" => 1,
"name" => "The Cat in The Hat"
},
{
"id" => 2,
"name" => "The Grinch"
},
]
}
Testing the exact output with eq
is not optimal as each change to the serialization will break the test. Instead you can use the include
matcher to specify what must be present:
describe '#as_json' do
let!(:physician) { create(:physician) }
let!(:patients) { create_list(:patients, 2) }
subject(:serialized) { physician.as_json }
it { should include({
"id" => physician.id,
"name" => physician.name
}) }
it "includes the patients" do
expect(serialized["patients"].length).to eq patients.length
expect(serialized["patients"]).to include patients.first.as_json
expect(serialized["patients"]).to include patients.last.as_json
end
end
Unless you have overridden the as_json
method this spec should fail as you need to explicitly include associations with physician.as_json(include: :patients)
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.