2014-07-04 210 views
0

我想获得一些嵌套查询来获取一些对象。下面是一些代码rails每个迭代器迭代两次

stream_controller.rb

def show 
    @rank = Rank.where(user_id: Application.where(stream_id: @stream.id)) 
end 

show.html.erb

<% i = 1 %> 
<% @rank.each do |f| %> 
    <tr> 
    <td><%= i %></td> 
    <td><%= f.user_id %></td> 
    <td><%= User.find(f.user_id.to_i).name %></td> 
    <td><%= f.rank %></td> 
    <tr><br> 
    <% i += 1 %> 
<% end %> 

的问题是输出为:

Sr User id  Name Rank 
1 15 a16 2 
2 7 a7 a71 4 
3 8 a8 a81 6 
4 13 a14 a41 8 
5 1 a1 13 
6 4 sm 14 
7 15 a16 2 
8 7 a7 a71 4 
9 8 a8 a81 6 
10 13 a14 a41 8 
11 1 a1 13 
12 4 sm 14 

这就是它的迭代两次为什么会发生?以及如何防止?

+0

我刚刚编辑您的HTML使其更具可读性。你能说出你期望在第一行看到什么吗? –

+1

您可以使用很多'where'调用,只需使用关联即可。例如,而不是'User.find(f.user_id.to_i).name'你不能做'f.user.name'吗? –

+0

而你的变量命名真的让人困惑:如果@ rank是一个Rank对象的集合,为什么不把它叫做'@ ranking'而不是'@ rank'呢?然后当你遍历它时,你引用每个成员为'f'(为什么??),然后让它更加混乱,你在循环中说'f.rank'! “Rank”类是否具有“排名”实例方法? –

回答

0

试试这个:

@rank = Rank.where(user_id: Application.where(stream_id: @stream.id)).uniq 

的.uniq(在该行的结尾)将删除您的查询返回的重复行。

1

我不是100%肯定,你想要做什么,但你的代码可以收拾了不少。这是一个更好的方法来做你的循环:因为@rank是一个集合变量,我已将其重命名为@ranks符合惯例。

<% @ranks.each_with_index do |rank, i| %> 
    <tr> 
    <td><%= i + 1 %></td> 
    <td><%= rank.user_id %></td> 
    <td><%= rank.user.name %></td> 
    <td><%= rank.rank %></td> 
    <tr><br> 
<% end %> 
+1

我会添加'.includes(:用户)',以防止从'n + 1'查询和急于加载用户 – MrYoshiji

+0

我正要尝试重写控制器代码,但是我不清楚模式是什么。 –

0

我写了一个SQL语句,它解决了我的问题,并把在模型文件,并把它称为从按钮控制器点击它解决了我的问题

def self.generate_result(stream_id) 
sql = "select distinct user_id, rank from ranks where 
     user_id = any(
     select user_id from applications where stream_id = 
     #{stream_id} 
     and verified = true) 
     order by rank asc" 
ActiveRecord::Base.connection.execute(sql) 

+0

Rank.where(user_id:Application.where(stream_id:@stream.id))不会生成所需的sql – SouravMoitra