我在部分 View 中使用以下代码来显示每个评估期的学生平均分数:
<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?如上所示,并在浏览器中得到:
然后我意识到因为select学生未参加的任何评估(对于新学生而言)都不是我用来生成代码的数据集的一部分。
问题,正如您在图片中看到的那样,只有最后一次评估的数据的两个学生没有将他们的数据放在正确的列中 - 所有内容都向左移动,因为没有 <td>由 View 代码生成。
那么问题是,我如何重写方法代码以获得相同的输出,但是 if scores.empty?方法插入""或 "no data"或其他一些占位符,以便 <td>打印在 View 中?
我现在明白发生了什么事了。这个方法:
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
它只能提取学生出席的评估。现在回到绘图板...
我已经将类方法更改如下:
#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
它在浏览器中返回了以下内容:
所以我尝试在 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
产生这个:
并且有道理 - 由于调用方式的原因,计数递增不会产生任何实际影响。但是虽然我认为我现在更接近我想要的效果,但我不确定如何实现它!
更近一点......我已经改变了一些东西,以便反向读取 key ,所以所有数据都被读取 - 但我仍然希望数据是打印最新的在右边(见下图)。模型方法代码现在看起来像这样:
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
它返回以下内容,我已经对其进行了注释,因此您可以更清楚地理解我正在寻找的是什么:
调用 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>]
}
最佳答案
更新
您应该更改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
注意scores 数组初始化。在这个方法中 [nil,nil,nil,nil] 最初被创建。对于只有两个分数的学生,分数将等于 [first_score, second_score, nil, nil]。
这可能会导致错误:方法的结果将是
(first_score + second_score) / 4
关于html - 如果方法没有返回数据,打印一个空的表格单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18532284/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何