2013-06-18 2 views
0

나는 아주 간단하게하려고합니다. 두 가지 모델, 사용자 및 그룹 있습니다. 단순화하기를 들어, 그들은 다음과 같이 가정 해 봅시다 :HABTM 연결에서 레코드 삭제

class User < ActiveRecord::Base 
    has_and_belongs_to_many :groups 
end 

class Group < ActiveRecord::Base 
    has_and_belongs_to_many :users 
end 

자, 어떤 이유로, 나는 두 번 같은 그룹이있는 사용자가 있습니다. 레일즈 콘솔에서 :

user = User.find(1000) 

=> #<User id: 1000, first_name: "John", last_name: "Doe", active: true, created_at: 
"2013-01-02 16:52:36", updated_at: "2013-06-17 16:21:09"> 

groups = user.groups 

=> [#<Group id: 1, name: "student", is_active: true, created_at: "2012-12-24 15:08:59", 
updated_at: "2012-12-24 15:08:59">, #<Group id: 1, name: "student", is_active: true, 
created_at: "2012-12-24 15:08:59", updated_at: "2012-12-24 15:08:59">] 

user.groups = groups.uniq 

=> [#<Group id: 1, name: "student", is_active: true, created_at: "2012-12-24 15:08:59", 
updated_at: "2012-12-24 15:08:59">] 

user.save 

=> true 

그리고 내가 침묵 한 일부 SQL 출력이 있습니다. 나는 모든 것이 다 설정되어야한다고 생각 하겠지만 그렇지 않다. 그룹은 업데이트되지 않으며 해당 사용자는 여전히 둘 다 있습니다. 내가 조인 테이블에 가서 수동으로 중복을 제거 할 수 있지만, 그것은 cludgy 및 총과 불필요한 것 같습니다. 여기서 내가 뭘 잘못하고 있니?

내가 레일 3.2.11과 루비를 실행 해요 1.9.3p392

추가 참고 : 나는 더에, user.update_attributes을 사용하고 대신 자신 그룹의 group_ids를 사용하여 포함이 여러 가지 방법을 시도하지했습니다 이익.

+0

콘솔에서 변수 이름의 일관성을 유지하는 것은 오타였습니다. – BSprague

+0

생각하기 쉬운 것들을 먼저 확인하겠습니다. ;-) – pjmorse

+0

'uniq : true'를 관계 배송에 추가하면 uniq 레코드를 '가져 오는'데 도움이되지만 중복 양식을 만드는 양식은 중단되지 않습니다. http://stackoverflow.com/questions/1129781/has-and-belongs-to-many-avoiding-dupes-in-the-join-table –

답변

1

이것이 작동하지 않는 이유는 ActiveRecord가 habtm 연결에서 유효하지 않은 복제 상태 (또는 그 문제에 대해서는 CollectionAssociation)를 처리하지 않았기 때문입니다. 새로 할당 된 배열에 포함되지 않은 id은 삭제되지만이 경우에는 아무 것도 없습니다. 관련 코드 :

전달되는 '대상'은 할당 된 레코드의 배열입니다. delete(target - new_target)에 대한 호출이 delete(user.groups - user.groups.uniq)과 동등한 경우 (비교는 각 레코드의 id 속성을 기반으로하므로) 빈 배열이 전달됩니다.

대신, 당신은 다시 하나의 그룹을 연관을 취소하고 재 할당해야합니다 :

group = user.groups.first 
user.groups.clear 
user.groups << group 
0

이 될 수 정리하는 방법을 그 중복 (이 중복 협회의 그룹의 수를 처리) :

user = User.find(1000) 

user.groups << user.groups.group_by(&:id).values.find_all {|v| v.size > 1}.each {|duplicates| duplicates.uniq_by! {|obj| obj.id}}.flatten.each {|duplicate| user.groups.delete(duplicate)}