2016-09-01 2 views
0

... 아니면 그냥 알 수 없습니다.레일 4 : 무작위 목록에서 오프셋을 사용하면 예기치 않은 결과가 발생합니다.

TL; DR - 전 중복으로 완전히 무작위로 결과를 얻습니다. 이유는 모르겠다.

다음은 문제입니다. - 나는 대회용 대괄호를 생성하는 레일 앱을 만들려고합니다. 사용자는 대괄호 생성시 팀 목록을 무작위로 지정할지 또는 나중에 팀을 직접 지정할지 여부를 선택할 수 있습니다.

내가 후자의 옵션을 선택하고 ID가 갈수록 괄호를 생성하면 모든 것이 정상입니다. 목록을 무작위로 선택하면 목록 자체가 문제가되지 않지만 이후 특정 팀을 특정 경기 (루프)에 할당 할 때 해당 팀은 완전히 조직되지 않고 예상치 못한 (적어도 나에게) 예.

대신
대전 1 팀 대 팀 1 2
대전 2 팀 4
등 대 팀 3 나 자주 중복 완전히 임의의 것을 얻을

(통상적으로 생성 된 것 같이) 같은 :
1 경기 : 팀 1 팀 대 1
2 경기 : 팀 대 팀 1 9

다음
if @seed = 'random' 
    @team_list = @tournament.teams.order("RAND()") 
else 
    @team_list = @tournament.teams.order(:id) 
end 

하는 방법 등이다 팀에 서명하십시오. 나사를 모두 "오프셋"부분 인 것처럼 보이며, 이해하지 못합니다. 이유는 무엇입니까?

@match.team_a = @team_list.offset((2*match_number)-2).limit(1).first    
@match.team_b = @team_list.offset((2*match_number)-1).limit(1).first 

EDIT : @team_list 데이터

샘플을 요청한다. 그것은 무작위로 추출한 것입니다.

#<ActiveRecord::AssociationRelation 
[#<Team id: 2, team_name: "test_team_a", reputation: 0, created_at: "2016-08-25 09:29:20", updated_at: "2016-08-26 11:08:21", team_leader_id: 2>, 
#<Team id: 9, team_name: "test_team_b", reputation: 0, created_at: "2016-08-30 23:01:17", updated_at: "2016-08-30 23:01:17", team_leader_id: 2>, 
#<Team id: 3, team_name: "test_team_c", reputation: 0, created_at: "2016-08-30 22:59:16", updated_at: "2016-08-30 22:59:16", team_leader_id: 2>, 
#<Team id: 7, team_name: "test_team_d", reputation: 0, created_at: "2016-08-30 23:00:35", updated_at: "2016-08-30 23:00:35", team_leader_id: 2>, 
#<Team id: 5, team_name: "test_team_e", reputation: 0, created_at: "2016-08-30 23:00:07", updated_at: "2016-08-30 23:00:07", team_leader_id: 2>, 
#<Team id: 6, team_name: "test_team_f", reputation: 0, created_at: "2016-08-30 23:00:23", updated_at: "2016-08-30 23:00:23", team_leader_id: 2>, 
#<Team id: 4, team_name: "test_team_g", reputation: 0, created_at: "2016-08-30 22:59:41", updated_at: "2016-08-30 22:59:41", team_leader_id: 2>, 
#<Team id: 8, team_name: "test_team_h", reputation: 0, created_at: "2016-08-30 23:00:46", updated_at: "2016-08-30 23:00:46", team_leader_id: 2>]> 
+0

@team_list에 데이터 샘플을 추가 할 수 있습니까? –

+0

지금 추가됨 : – user3758208

답변

1

같은

시도 뭔가 그냥 당신이 @team_list = @tournaments.teams.order("RAND()")을 수행 할 때, 즉 않습니다, 위의 대답에 (아마도 SQL에서)이 쿼리를 좀 더 되거하기 팀이 토너먼트에 속해 있지만 내 점수를 얻는다.)

그리고 @team_list.offset(x).limit(1)을 실행하면 다음 쿼리가 수행됩니다.

SELECT teams.* FROM teams ORDER BY RAND() LIMIT 1 OFFSET x 

ActiveRecord 관계로 인해 새로운 일을 할 때마다 쿼리가 수행됩니다. 이것을 레일 콘솔에서 테스트 할 수 있습니다. 쿼리를 통해 알 수 있습니다.

편집 :

그냥 배열 첫 번째 쿼리의 결과를 변환 그대로 코드를 사용하려는/제한 오프셋 사용하지 않는 경우

.그래서 :

@team_list = @tournaments.teams.order("RAND()").to_a 
... 
@match.team_a = @team_list[2 * match_number - 2] 
@match.team_b = @team_list[2 * match_number - 1] 

이 한 번에 팀의 모든로드된다는 것을 의미합니다 (생각)과 액티브 관계는 당신이 할 수있는 것처럼 유유히을로드 할 수 없습니다.

+0

당신은 아마 맞을 것입니다. 나는 여전히 그것이 작동하는 방식을 이해하지 못하는 것 같아서 묻는 중입니다. 콘솔에서 시도하고 @team_list를 시도 할 때마다 동일한 결과를 얻을 수 있지만 오프셋을 사용할 때 결과는 임의적입니다. 나는 왜 첫 번째 경우에는 결과가 무작위가 아닌지 이해하지 못합니다. – user3758208

+0

솔직히 말해서, 저는 ActiveRecord 관계가 작동하는 방식에 대한 전문가가 아니므로, 제가 제공 한 설명이 기술적으로 정확할 지 확신하지 못합니다. 그러나 내 생각 엔 쿼리의 결과에'@ team_list'를 할당하면 릴레이션은 순서를 변수에 저장하지만 여전히 그것과 동등한 쿼리를 전달합니다. 대안을 포함하도록 내 대답을 업데이트하겠습니다. –

+0

네 답이 옳다. 그 점에 대해 감사드립니다. – user3758208

1

오프셋을 사용하고 있기 때문입니다. match_number를 변경할 때마다 새로운 쿼리 (order_by rand() 호출이 포함됨)가 끝납니다. @team_list를 데이터베이스 쿼리의 결과로 만든 다음 다른 방식으로 일치 항목을 구성하여 데이터베이스를 반복적으로 조회하지 않아야합니다. 또한 성능이 크게 향상됩니다. 내가 아는 (

SELECT teams.* FROM teams ORDER BY RAND() 

:

@team_list.each_slice(2) do |team_a, team_b| 
end 
+0

나는 그것을 상쇄 할 필요가 있다고 생각한다. 왜냐하면이 방법은 오직 나의 이해에서 각 시합에 처음 두 팀만 할당하기 때문이다. 그래서 내가 처음에는 오프셋을 사용했습니다. 어쩌면 당신은 다른 방법으로 그것을 해결할 생각을 가지고 있습니까? 어쩌면 여전히 잘못 이해하고 있지만 콘솔에서 매번 내가 시도해도 @team_list를 시도 할 때 결과가 같고 (무작위로 쿼리되지 않음), 그렇지만 오프셋이 사용되면, 결과는 무작위로 추출됩니다. – user3758208

+0

['each_slice' 문서] (http://ruby-doc.org/core-2.3.1/Enumerable.html#method-i-each_slice)를 참조하십시오. 팀이 [1, 2, 3, 4]라면,'each_slice (2)'는 첫 반복에서 [1, 2]를, 다음번에는 [3, 4]를 줄 것입니다. –

+0

@ user3758208 이것은 루프 부분을 대체하기위한 것일 뿐이며, if seed 부분을 원한다면 그렇지 않습니다. 그렇지 않으면 무작위 화되지 않습니다. 현재 진행중인 문제는 오프셋을 사용하여 팀을 지정할 때마다 이전 팀과 완전히 다른 순서로 목록에서 n 번째 팀을 얻는 것입니다. – user3334690

관련 문제