5

I recently found a problem in a Rails app related to duplicate entries in a join table. The app is educational, and includes models for Students and Exercises. The join table keeps track of which exercises have been assigned to which students. It doesn't make sense for an exercise to be assigned to a student more than once (i.e. duplicate entries in the join table shouldn't be allowed).

I partially fixed the problem by adding a uniqueness validation to the join table (see the last line of code, below). This validation will prevent any new duplicate entries from being created in the future. I'm still faced with the problem, however, of addressing the existing duplicates in the table.

Is there a way to run the new validation against the entire existing database, to retrieve all the records that are no longer valid?

class Student < ActiveRecord::Base
  has_many :student_exercise_assignments
  has_many :exercises, :through => :student_exercise_assignments
end

class Exercise < ActiveRecord::Base
  has_many :student_exercise_assignments
  has_many :students, :through => :student_exercise_assignments
end

class StudentExerciseAssignment < ActiveRecord::Base
    belongs_to :student
    belongs_to :exercise
    validates :exercise_id, :uniqueness => { :scope => :student_id, :message => "An exercise can only be assigned to a student once" }

UPDATE

Shioyama's answer below gives exactly the information I was looking for. Being a Rails newbie, though, I was a bit confused by his use of & in &:invalid?. If anyone needs an primer of the & operator in Ruby, there's a good one here.

Community
  • 1
  • 1
dB'
  • 7,838
  • 15
  • 58
  • 101

1 Answers1

10

How about just:

invalid_assignments = StudentExerciseAssignment.select(&:invalid?)

This will select all assignments which return true when called with the invalid? method. You can then do whatever you need to do to fix them.

As a side note, I would also suggest adding a uniqueness constraint to your database. See this answer for reasons why: Rails: Validation in model vs migration

Community
  • 1
  • 1
Chris Salzberg
  • 27,099
  • 4
  • 75
  • 82