【问题标题】:Ruby use collect/map with an attribute of a tableRuby 使用带有表属性的 collect/map
【发布时间】:2011-07-12 19:54:02
【问题描述】:

我有学生参加了“测试”,其中有 5 个“问题”。我想要做的是显示每个测试每个问题的最大“分数”。

Test、Student、Question 都是单独的表。

class Test < ActiveRecord::Base
  has_many :students
end

class Student < ActiveRecord::Base
  belongs_to :test
  has_many :questions
end

class Question < ActiveRecord::Base
  belongs_to :students
end

我拥有的代码:

<% @tests.each do |test| %>
<% max_score = [] %>
    <% test.students.collect {|s| s.questions.collect {|q| max_score << q.score}}%>

    <tr>
      <th><%= test.name %></th>
      <th><%= max_score.max %></th
    </tr>
<% end %>

但是,这显示的是整个测试的最高分数。

示例)

Math - 95
History - 98
Physics - 100

它不会返回每个 'question_number' 1 到 5 的最大值。我想打印每个测试的每个问题的最高分数。

示例)

Math - 1 - 90
Math - 2 - 100
Math - 3 - 88
Math - 4 - 79
Math - 5 - 98
History - 1 - 80
History - 2 - 95
..and so on...

在 Question 表中有一个名为“question_number”的列。我不知道如何使用这个属性来得到我想要的结果。

【问题讨论】:

  • 在我看来,您需要另一个循环并遍历所有问题对象,输出问题的编号和分数属性。您现在描述它的方式根本不想使用 max 方法。
  • 检查我的答案。另请注意,您的收集完全错误,它不应该被强制使用(在谷歌中搜索“功能红宝石”)

标签: ruby map collect


【解决方案1】:

你的模型错了。玩这个:

class Test < ActiveRecord::Base
  has_many :questions
end

class Question < ActiveRecord::Base
  belongs_to :test
  has_many :question_scores
  has_many :students, :through => :question_scores
end

class Student < ActiveRecord::Base
  has_many :question_scores
  has_many :questions, :through => :question_scores
end

class QuestionScore < ActiveRecord::Base
  belongs_to :student
  belongs_to :question
end

代码应该是这样的:

<% @tests.each do |test| %>
  <% test.questions.each do |question| %>
    test: <% test.name %>
    question: <%= question.name %>
    max score: <%= question.question_scores.maximum(:score) %>
  <% end %>
<% end %>

【讨论】:

  • 感谢您的回答。我看到它可以如何改变,它更有意义。但是,目前没有办法改变结构。
【解决方案2】:

如果正如您的评论所暗示的那样,您无法更改您的班级结构,那么它会有点难看。您仍然可以添加has_many :through 来稍微清理一下:

class Test < ActiveRecord::Base
  has_many :students
  has_many :questions, :through => :students
end

class Student < ActiveRecord::Base
  belongs_to :test
  has_many :questions
end

class Question < ActiveRecord::Base
  belongs_to :students
end

那么你将不得不嵌套迭代器......

<% @tests.each do |test| %>
  <% 1.upto(5) do |index|
    max = test.questions.select {|q| 
            q.question_number == index }.max_by {|q| q.score } %>
    <tr>
      <td><%= test.name %></td>
      <td><%= index %></td>
      <td><%= max.score %></td>
    </tr>
  <% end %>
<% end %>

您的代码存在的一个问题是您只为每个测试输出一次&lt;tr&gt;。你想为每个问题做一次。更好的解决方案是编写范围。大致如下:

class Test < ActiveRecord::Base
  has_many :students
  has_many :questions, :through => :students
end

class Student < ActiveRecord::Base
  belongs_to :test
  has_many :questions
end

class Question < ActiveRecord::Base
  belongs_to :student

  scope :max_score_by_question_number, lambda {|num| where(:question_number => num).maximum(:score) }
end

然后你可以这样做,看起来更好

<% @tests.each do |test| %>
  <% 1.upto(5) do |index|
    max = test.questions.max_score_by_question_number(index) %>
      <tr>
        <td><%= test.name %></td>
        <td><%= index %></td>
        <td><%= max.score %></td>
      </tr>
    <% end %>
  <% end %>

【讨论】:

    猜你喜欢
    • 2012-04-12
    • 2016-12-19
    • 1970-01-01
    • 2014-01-29
    • 2012-12-18
    • 2017-04-15
    • 2014-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多