2013-04-25 3 views
0

Я получил эти модели:Rails 3: Удаление ассоциации дубликатов из базы данных

class Relationship < ActiveRecord::Base 
    belongs_to :student 
    belongs_to :guardian 
end 

class Student < ActiveRecord::Base 
    has_many :relationships 
    has_many :guardians, through: :relationships 
end 

class Guardian < ActiveRecord::Base 
    has_many :relationships 
    has_many :students, through: :relationships 
end 

Я не хочу опекуны быть много раз, связанных с одним студентом. Это можно предотвратить с помощью проверки, но, допустим, слишком поздно, и есть случаи, когда это происходит. Например, когда g является опекуном:

g.relationships 

[ 
    [0] #<Relationship:0x0000000bc33650> { 
          :id => 40321, 
     :relationship_type_id => 2, 
        :student_id => 41700, 
       :guardian_id => 45820, 
        :created_at => Tue, 23 Apr 2013 17:44:29 UTC +00:00, 
        :updated_at => Tue, 23 Apr 2013 17:44:29 UTC +00:00, 
    }, 
    [1] #<Relationship:0x0000000bc32e80> { 
          :id => 40923, 
     :relationship_type_id => 2, 
        :student_id => 41700, 
       :guardian_id => 45820, 
        :created_at => Tue, 23 Apr 2013 18:58:46 UTC +00:00, 
        :updated_at => Tue, 23 Apr 2013 18:58:46 UTC +00:00, 
    } 
] 

Как вы можете видеть, эти два отношения один и тот же student_id. Я хочу узнать, есть ли способ удалить из базы данных дублированные отношения. Я пробовал следующие строки кода безрезультатно:

g.relationships.uniq!(&:student_id) 
g.update_attributes(relatioships: g.relationships.uniq!(&:student_id)) 

Как решить эту проблему. Благодаря!

+0

Существуют ли какие-либо правила о том, какой из дубликатов должен оставаться (самое последнее, самое раннее, что-то еще), или это не имеет большого значения? Кроме того, вам нужен код SQL или ruby ​​для этого? – PinnyM

+0

Нет правил, если есть два одинаковых типа, любой из них будет работать для меня – sauronnikko

ответ

0
subquery = Relationship.select("student_id, guardian_id"). 
      group(:student_id, :guardian_id). 
      having("count(*) > 1").to_sql 
groups = Relationship.joins("JOIN (#{subquery}) sub ON relationships.student_id = sub.student_id AND relationships.guardian_id = sub.guardian_id"). 
         group_by{|r| [r.student_id, r.guardian_id] } 

groups.values.each do |duplicates| 
    duplicates.drop(1).each(&:destroy) 
end