0

I am working on a Ruby script to address users accidentally deleted from the app, which clones a User record and the UserGroups right before deletion.

I'm looping through both objects, and now trying to figure how to assert that the attributes match.

I tried

assert_equal archived_user_groups, deleted_user_groups

but that is asserting the objects not the attributes, so it fails.

I am trying to loop through the array and check that attributes (user_id, group_id) are the same for every object at the same index (0, 1, 2, ...). Is each_with_index suitable for this, and how would it be implemented?

archived_user_groups_test.rb:

def test_user_with_user_groups
    user = users(:employee_bb)
    deleted_user_groups = user.user_groups.sort_by{ |u| [u.user_id, u.group_id] }

    user.archive!

    archived_user_groups = ArchivedUserGroup.where(user_id: user.id).sort_by{ |u| [u.user_id, u.group_id] }

    deleted_user_groups.each do |ug|
        archived_user_groups.find do |attribute_names, attribute_values|
        assert_equal archived_user_groups, deleted_user_groups
      end
    end

  end
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
VegaStudios
  • 378
  • 1
  • 4
  • 22

1 Answers1

1

The include matcher is versatile and can be used for strings, arrays, hashes, etc.

In this case you could iterate over the records and compare their attribute hashes:

archived_user_groups.each_with_index do |archived_user, idx|
  expect(archived_user.attributes).to include(deleted_user_groups[idx].attributes)
end

However this test might fail if you have different created_at, updated_at, id, etc. for the archive vs. deleted records. In that case you could be more explicit about which attributes you're testing against. There are many ways to do this but for example:

archived_user_groups.each_with_index do |archived_user, idx|
  expect(
    archived_user.attributes.values_at("id", "email")
 ).to match_array(
    deleted_user_groups[idx].attributes.values_at("id", "email")
 )
end

I admit this seems verbose for what could potentially be a one-liner. This might be a good use-case for writing a custom matcher.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
max pleaner
  • 26,189
  • 9
  • 66
  • 118
  • Is `archived_user` supposed to be `archived_user_groups`? Because `archived_user` isn't defined anywhere. This is a little over my head so I'm trying to break it down, but at a glance it is throwing undefined method `attributes'. – VegaStudios Mar 24 '17 at 16:02
  • @VegaStudios my bad there was a typo in there Remove the array around `archived_user_groups` – max pleaner Mar 24 '17 at 16:18
  • Does Minitest use `expect`, or is that an RSpec method? – VegaStudios Mar 24 '17 at 16:22
  • @VegaStudios good point, I neglected to notice you weren't usin rspec. In that case you replace `expect` with `assert_equal` and simply use `==` to compare hashes rather than `include` - see http://stackoverflow.com/questions/4928789/how-do-i-compare-two-hashes – max pleaner Mar 24 '17 at 16:24
  • So something along the lines of, `assert_equal archived_user.attributes == deleted_user_groups[idx].attributes`. That creates an ArgumentError: wrong number of arguments (1 for 2..3), so I'll have to dig a little deeper – VegaStudios Mar 24 '17 at 16:33
  • @VegaStudios, no, it would be `assert_equal archived_user.attributes, deleted_user_groups[idx].attributes` – max pleaner Mar 24 '17 at 16:33