2013-08-30 44 views
3

我在局部顯示一個學生各評價期間的平均得分的圖以下代碼:打印一個空表單元格,如果方法沒有返回數據

<tr class="<%= cycle("odd", "even", name: "students")%>"> 
    <td> 
    <%= link_to "#{student.name}", 
       student_path({student_group_id: student.student_group_id, id: student.id})%> 
    </td> 
    <% student.eval_count.times do |i| %> 
     <td class="center"><%= student.avg_for_eval(i) %></td> 
    <% end %> 
    <td class="center"><%= student.avg unless student.avg.nan? %></td> 
</tr> 

我使用在student.rb此方法生成平均分數,起初我無法弄清楚爲什麼我無法在沒有數據時無法生成空行。

def evals 
    evals = self.evaluations.order("eval_number").group_by(&:eval_number) 
end 

def eval_number_set(index) 
    numbers = Evaluation.where('student_id = ?', self.id).uniq.pluck(:eval_number) 
    numbers[index] 
end 

def avg_for_eval(i) 
    scores = [] 
    evals = self.evals.select { |k, v| k == self.eval_number_set(i) }.values.first 
    for eval in evals 
    scores << eval.score 
    end 
    evals.empty? #(scores.sum.to_f/scores.size).round(2) 
end 

我改變了方法的最後一行evals.empty?如上圖所示,並得到了這個瀏覽器:

browser

然後我意識到,因爲select任何評價學生不存在(對於新學生)不是我用來生成代碼的數據集的一部分。

從圖中可以看出,問題在於,只有最後一次評估數據的兩名學生沒有將他們的數據輸入到正確的列中 - 所有內容都向左移動,因爲沒有<td>由視圖代碼產生。

所以問題的話,是如何可以重寫方法的代碼,使得我得到同樣的輸出,但使得<td>在視圖印刷if scores.empty?的方法插入"""no data"或一些其它的佔位符?

更新

我明白現在好了一點。這種方法:

def eval_number_set(index) 
    numbers = Evaluation.where('student_id = ?', self.id).uniq.pluck(:eval_number) 
    numbers[index] 
end 

是返回評價號碼每個學生 - 因此,當這些數字在未來的方法是使用

def avg_for_eval(i) 
    scores = [] 
    evals = self.evals.select { |k, v| k == self.eval_number_set(i) }.values.first 
    for eval in evals 
    scores << eval.score 
    end 
    evals.empty? #(scores.sum.to_f/scores.size).round(2) 
end 

只能拉一個學生就一直存在評價對於。回到繪圖板現在...

更新2

我已經改變了類的方法如下:

#returns all 'eval_number's for a given group of students 
#as the first student will have been present for all evaluations 

def eval_number_set(index) 
    numbers = self.student_group.students.first.evals.keys 
    # numbers = Evaluation.where('student_id = ?', self.id).uniq.pluck(:eval_number) 
    numbers[index] 
end 

#attempts to match the first present 'eval_number' for a given student against 
#the first number in the set of all 'eval_number's and react accordingly 
def avg_for_eval(i) 
    scores = [] 
    if self.evals.keys[i] == self.eval_number_set(i) 
    "match" 
    else 
    "no_match" 
    end 
end 

此匹配的所有誰是目前每一個評價學生,但對錯過了一些學生的學生沒有任何評價。我改變了代碼以下

def avg_for_eval(i) 
    scores = [] 
    if self.evals.keys[i] == self.eval_number_set(i) 
     "#{self.evals.keys[i]} vs #{self.eval_number_set(i)}" 
    else 
     "#{self.evals.keys[i]} vs #{self.eval_number_set(i)}" 
    end   
    end 

並且退回它在瀏覽器中執行以下操作:

new problem

所以我試圖在添加計數器if語句,例如,如果語句匹配,這將增加正在嘗試的關鍵,否則會留在同一個鍵:

def avg_for_eval(i) 
    scores = [] 
    key_match = 0 
    if self.evals.keys[key_match] == self.eval_number_set(i) 
     "#{self.evals.keys[i]} vs #{self.eval_number_set(i)}" 
     key_match += 1 
    else 
     "#{self.evals.keys[i]} vs #{self.eval_number_set(i)}" 
    end 
    end 

產生這樣的:

enter image description here

和有意義 - 計數遞增不走的,因爲它被調用的方式任何實際效果。但是當我認爲我現在更接近我想要的效果時,我不知道如何讓它發生!

更新3

接近還是......我已經改變了,這樣的鍵反向閱讀,因此,所有的數據都被 - 但我還是很喜歡的數據是打印與最近的右邊(見下圖)。該模型方法的代碼現在看起來是這樣的:

def eval_number_set(index) 
    numbers = self.student_group.students.first.evals.keys.reverse 
    # numbers = Evaluation.where('student_id = ?', self.id).uniq.pluck(:eval_number) 
    numbers[index] 
    end 

    def avg_for_eval(i) 
    scores = [] 
    eval_number = self.eval_number_set(i) 
    if self.evals.keys.reverse[i] == eval_number 
     for eval in self.evals.values[i] 
     scores << eval.score if self.evals.values[i] 
     end 
     scores 
    else 
     "no data" 
    end 
    end 

返回;下面,我已經註釋,所以你可以理解它是什麼,我找了一下更清楚:

enter image description here

更新4

調用student.evals返回以下(學生與id 32):

{29=>[ 
    #<Evaluation id: 1949, score: 3, created_at: "2013-08-28 09:44:32", updated_at: "2013-08-28 09:44:32", student_id: 32, goal_id: 63, eval_number: 29>, 
    #<Evaluation id: 1950, score: 4, created_at: "2013-08-28 09:44:32", updated_at: "2013-08-28 09:44:32", student_id: 32, goal_id: 64, eval_number: 29>, 
    #<Evaluation id: 1951, score: 5, created_at: "2013-08-28 09:44:32", updated_at: "2013-08-28 09:44:32", student_id: 32, goal_id: 65, eval_number: 29>], 
30=>[ 
    #<Evaluation id: 1957, score: 3, created_at: "2013-08-28 09:44:43", updated_at: "2013-08-28 09:44:43", student_id: 32, goal_id: 65, eval_number: 30>, 
    #<Evaluation id: 1956, score: 2, created_at: "2013-08-28 09:44:43", updated_at: "2013-08-28 09:44:43", student_id: 32, goal_id: 64, eval_number: 30>, 
    #<Evaluation id: 1955, score: 1, created_at: "2013-08-28 09:44:43", updated_at: "2013-08-28 09:44:43", student_id: 32, goal_id: 63, eval_number: 30>], 
31=>[ 
    #<Evaluation id: 1968, score: 2, created_at: "2013-08-28 11:26:56", updated_at: "2013-08-28 11:26:56", student_id: 32, goal_id: 70, eval_number: 31>, 
    #<Evaluation id: 1967, score: 2, created_at: "2013-08-28 11:26:56", updated_at: "2013-08-28 11:26:56", student_id: 32, goal_id: 69, eval_number: 31>, 
    #<Evaluation id: 1966, score: 1, created_at: "2013-08-28 11:26:56", updated_at: "2013-08-28 11:26:56", student_id: 32, goal_id: 68, eval_number: 31>, 
    #<Evaluation id: 1965, score: 1, created_at: "2013-08-28 11:26:56", updated_at: "2013-08-28 11:26:56", student_id: 32, goal_id: 67, eval_number: 31>, 
    #<Evaluation id: 1964, score: 1, created_at: "2013-08-28 11:26:56", updated_at: "2013-08-28 11:26:56", student_id: 32, goal_id: 66, eval_number: 31>, 
    #<Evaluation id: 1963, score: 3, created_at: "2013-08-28 11:26:56", updated_at: "2013-08-28 11:26:56", student_id: 32, goal_id: 65, eval_number: 31>, 
    #<Evaluation id: 1962, score: 3, created_at: "2013-08-28 11:26:56", updated_at: "2013-08-28 11:26:56", student_id: 32, goal_id: 64, eval_number: 31>, 
    #<Evaluation id: 1961, score: 3, created_at: "2013-08-28 11:26:56", updated_at: "2013-08-28 11:26:56", student_id: 32, goal_id: 63, eval_number: 31>], 
32=>[ 
    #<Evaluation id: 1983, score: 3, created_at: "2013-08-29 19:31:48", updated_at: "2013-08-29 19:31:48", student_id: 32, goal_id: 69, eval_number: 32>, 
    #<Evaluation id: 1982, score: 2, created_at: "2013-08-29 19:31:48", updated_at: "2013-08-29 19:31:48", student_id: 32, goal_id: 68, eval_number: 32>, 
    #<Evaluation id: 1981, score: 3, created_at: "2013-08-29 19:31:48", updated_at: "2013-08-29 19:31:48", student_id: 32, goal_id: 67, eval_number: 32>, 
    #<Evaluation id: 1980, score: 4, created_at: "2013-08-29 19:31:48", updated_at: "2013-08-29 19:31:48", student_id: 32, goal_id: 66, eval_number: 32>, 
    #<Evaluation id: 1979, score: 4, created_at: "2013-08-29 19:31:48", updated_at: "2013-08-29 19:31:48", student_id: 32, goal_id: 65, eval_number: 32>, 
    #<Evaluation id: 1978, score: 3, created_at: "2013-08-29 19:31:48", updated_at: "2013-08-29 19:31:48", student_id: 32, goal_id: 64, eval_number: 32>, 
    #<Evaluation id: 1977, score: 3, created_at: "2013-08-29 19:31:48", updated_at: "2013-08-29 19:31:48", student_id: 32, goal_id: 63, eval_number: 32>, 
    #<Evaluation id: 1984, score: 3, created_at: "2013-08-29 19:31:48", updated_at: "2013-08-29 19:31:48", student_id: 32, goal_id: 70, eval_number: 32>] 
} 
+2

「link_to」#{student.name}「,student_path(...)」。這條線可能會重寫爲「link_to student.name,student_path(...)」 – hedgesky

+0

啊很好的捕獲,不知道爲什麼就是這樣的 – dax

+0

會像'def avg_for_eval(index) \t Evaluation.where('student_id =?和eval_number =?',self.id,index).sum() end' work? – Gonfva

回答

0

我最終用下面的代碼得到了這個工作 - 但如果有人能告訴我一個更好的方法來做到這一點,我很樂意給他們獎金。

_student_list.html.erb

<table class="fixed"> 
    <tbody>  
    <% group.students.each_with_index do |student, index| %> 
    <tr> 
     <th></th> 
     <% if index == 0 %> 
     <% student.eval_count.times do |i| %>            
      <th class="center">Evaluation <%= i + 1 %></th> 
     <% end %> 
     <th><%= "Student average" if student.eval_count > 0 %></th> 
     <% end %> 

    </tr> 
    <tr class="<%= cycle("odd", "even", name: "students")%>"> 
     <td> 
     <%= link_to student.name, student_path({student_group_id: student.student_group_id, id: student.id})%> 
     </td> 
     <% student.student_group.eval_count.times do |i| %> 
     <td class="center"><%= student.avg_for_eval(i) %></td> 
     <% end %> 
     <td class="center"><%= student.avg unless student.avg.nan? %></td> 
    </tr> 
    <% end %> 
    <% reset_cycle("students") %> 
    </tbody> 
</table> 

student.rb

def eval_number_set(index) 
    numbers = self.student_group.students.first.evals.keys 
    numbers[index] 
    end 

    def reverse_eval_number_set(index) 
    numbers = self.student_group.students.first.evals.keys.reverse 
    numbers[index] 
    end 

    def avg_for_eval(i) 
    scores = [] 
    eval_number = self.reverse_eval_number_set(i) 
    count_differential = (self.student_group.eval_count - self.eval_count) - i 
    if self.student_group.eval_count == self.eval_count 
     for eval in self.evals.values[i] 
     scores << eval.score 
     end 
     (scores.sum.to_f/scores.size).round(2) 
    else 
     if self.evals.values[count_differential] 
     for eval in self.evals.values[count_differential] 
      scores << eval.score 
     end 
     (scores.sum.to_f/scores.size).round(2) 
     else 
     "no data" 
     end 
    end 
    end 
+0

是'group'和'student.student_group'是同一個對象嗎? – j03w

+0

是的,在一些意見中有一個每塊student_group作爲'group' – dax

+1

遍歷的每個塊,那麼爲什麼你要調用'student.student_group.eval_count'而不是'group.eval_count'?另外,你可以舉一些什麼'evals'哈希請示例嗎? – j03w

3

UPDATE

你應該改變eval_count方法或者使用恆定的值,使4個細胞。例如,

4.times do |i| 
    <td class="center"><%= student.avg_for_eval(i) %></td> 
end 

結束時更新

,你可以試試這個辦法:分數數組初始化

def avg_for_eval(i) 
    scores = Array.new(4) 
    evals = self.evals.select { |k, v| k == self.eval_number_set(i) }.values.first 
    evals.each_with_index do |eval, i| 
    scores[i] = eval.score 
    end 
    (scores.sum.to_f/scores.size).round(2) 
end 

留意。在這種方法中,最初創建了[無,零,零,零]。對於只有兩個分數的學生,分數將等於[first_score,second_score,nil,nil]。

它導致可能的錯誤:方法的結果將是

(first_score + second_score)/4 
+0

我喜歡這個想法,但它仍然不工作的原因 - 我想我需要一種方法,而不是選擇。 – dax

+0

也許,_map_? http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-map – hedgesky

+0

請檢查我的更新。我想,我發現錯誤的原因。 – hedgesky

0

你上一次更新後,修改這樣的觀點:

<tr class="<%= cycle("odd", "even", name: "students")%>"> 
<td> 
<%= link_to "#{student.name}", 
      student_path({student_group_id: student.student_group_id, id: student.id})%> 
</td> 
<% student.eval_count.times do |i| %> 
    <td class="center"><%= student.avg_for_eval(student.eval_count - i) %></td> 
<% end %> 
<td class="center"><%= student.avg unless student.avg.nan? %></td> 
</tr> 

基本上,顯示他們在翻領訂購

+0

這本身並沒有回答我的問題,但它是最好的答案,它使我朝着最正確的方向發展。 – dax

0

假設group.eval_counteval_count最大數量。

查看

<table class="fixed"> 
    <thead>  
    <tr> 
     <th></th> 
     <% group.eval_count.times do |i| %>            
     <th class="center">Evaluation <%= i + 1 %></th> 
     <% end %> 
     <th><%= "Student average" if group.eval_count > 0 %></th> 
    </tr> 
    </thead> 
    <tbody> 
    <% group.students.each do |student| %> 
    <tr class="<%= cycle("odd", "even", name: "students")%>"> 
     <td> 
     <%= link_to student.name, 
        student_path({ 
         student_group_id: student.student_group_id, 
         id: student.id 
         })%> 
     </td> 
     <% group.eval_count.times do |i| %> 
     <td class="center"><%= student.avg_for_eval(i+1) %></td> 
     <% end %> 
     <td class="center"><%= student.avg unless student.avg.nan? %></td> 
    </tr> 
    <% end %> 
    <% reset_cycle("students") %> 
    </tbody> 
</table> 

如果你不想通過所有的評估數字迭代(即有從29開始),然後使用範圍像(min..group.eval_count).each你也可以做反向(min..max).to_a.reverse.each。從數據中找出maxmin應該相當平凡。

student.rb

def avg_for_eval(i) 
    # nil evaluated as false hence this works... 
    if evaluations_with_sum[i] 
    (evaluations_with_sum[i].sum/evaluations_with_sum[i].size).round(2) 
    else 
    'no data' 
    end 
end 

private 
def evaluations_with_sum 
    # memoize as hash using instance variable 
    # 'order' does work with symbol and the sorting will be ASC 
    @evals ||= self.evaluations.order(:eval_number).inject({}) do |hash, evaluation| 
    hash[evaluation.eval_number] ||= [] 
    hash[evaluation.eval_number] << evaluation.score 
    hash 
    end 
end 

其實我覺得self.evaluations.order(:eval_number).average(:score).group(:eval_number)應該給你eval_number關鍵和總和score作爲價值哈希,但我也不太清楚,你可以嘗試一下...

0

要打印一個空的表格單元格,請在單元格內放置一個不間斷的空格。

<td>&nbsp;</td> 
相關問題