skip to Main Content

I have this table called Group.

class Group < ApplicationRecord
  belongs_to :admin, class_name: "User", foreign_key: :admin_id
  has_many :memberships, dependent: :destroy
  has_many :users, through: :memberships
  has_many :tasks, dependent: :destroy
  has_many :tags, dependent: :destroy
  has_many :invitations, dependent: :destroy
end

I am creating some tests for when I delete a group. After deleting a group I want to check that the group is deleted and that the associated records are deleted as well.

it "deletes the group" do
  expect(Group.find(group.id)).to_not be_present
end

it "deletes the group's dependent associations" do
  expect(Task.where(group: group).count).to eq 0
  expect(Tag.where(group: group).count).to eq 0
  expect(Invitation.where(group: group).count).to eq 0
  expect(Membership.where(group: group).count).to eq 0
end

I wrote it like that but it feels really repetitive. I was wondering if there is another way to create a query to get all the associated records in an array and check if the array is empty.

I tried with connected where like this:

Task.where(group: g).and(Tag.where(group: g)).and(Membership.where(group: g)).and(Invitation.where(group: g))

But it is throwing the following error: (Object doesn't support #inspect)

I read about joins but couldn’t understand it properly so I am not sure if it is the right direction to go to.

Any help would be appreciated. Thank you!

PD: I am using PostgreSQL for the db

4

Answers


  1. This is not a task for table joining since these tables have nothing to be joined on when the group is deleted.

    You can remove the repetition by calling the expect in a loop:

    it "deletes the group's dependent associations" do
      [Task, Tag, Invitation, Membership].each do |klass|
        expect(klass.where(group: group).count).to eq 0
      end
    end
    
    Login or Signup to reply.
  2. I would not test this behavior because it only tests the implementation provided by Ruby on Rails and Rails methods are already tested in the framework internally.

    When you really want to test your implementation, then I would suggest adding the shoulda-matcher gem and test that the associations are configured as expected, like this:

    RSpec.describe Group do
      describe 'associations' do
        it { is_expected.to have_many(:invitations).dependent(:destroy) }
        it { is_expected.to have_many(:tags).dependent(:destroy) }
        it { is_expected.to have_many(:tasks).dependent(:destroy) }
        it { is_expected.to have_many(:users).dependent(:destroy) }
      end
    end
    
    Login or Signup to reply.
  3. To test behavior, I believe it’s best to test one by one. But, in general, following good practices, instead of an it with several expectations, the best thing is an it for each expectation.

    RSpec.describe Group do
      context 'when to destroy' do
        let(:group) { create(:group) }
    
        before { group.destroy }
    
        it { expect(group).to be_destroyed }
    
        describe 'associations' do
          it { expect(group.invitations.exists?).to be false }
          it { expect(group.tags.exists?).to be false }
          it { expect(group.tasks.exists?).to be false }
          it { expect(group.users.exists?).to be false }
        end
      end
    end
    
    Login or Signup to reply.
  4. You can use below to get all associations on record class

    Group.reflect_on_all_associations

    It will give you an array of associations. Sample association-

     #<ActiveRecord::Reflection::HasManyReflection:0x00007f7752b24578    
      @active_record=Group (call 'Group.connection' to establish a connection),
      @klass=nil,                                                        
      @name=:users,                                                      
      @options={},                                             
      @plural_name="users",                                    
      @scope=nil>
    

    You can also use the reflect_on_association method to fetch details for a specific association

    Group.reflect_on_association(:users)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search