Ruby 将收集/映射与表的属性结合使用

发布于 2024-11-19 20:35:26 字数 1047 浏览 5 评论 0原文

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

测试、学生、问题都是单独的表。

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_number”。我不知道如何使用这个属性来获得我想要的结果。

I have students who took 'tests', which have 5 'questions'. What I want to do is to show the max 'score' for each question for each test.

Test, Student, Question are all separate table.

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

The code that I have:

<% @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 %>

However, what this shows is the max score for the whole test.

example)

Math - 95
History - 98
Physics - 100

It does not return the max for each 'question_number' 1 to 5. I want to print the max score for each question for each test.

example)

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

In the Question table it has a column named 'question_number'. I don't know how to use this attribute to get the result I want.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半葬歌 2024-11-26 20:35:26

你的模型错了。玩这个:

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 %>

You have your models wrong. Play with this:

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

And the code should be something like this:

<% @tests.each do |test| %>
  <% test.questions.each do |question| %>
    test: <% test.name %>
    question: <%= question.name %>
    max score: <%= question.question_scores.maximum(:score) %>
  <% end %>
<% end %>
调妓 2024-11-26 20:35:26

如果,正如您的评论所暗示的,您无法改变您的类结构,那么它会有点难看。您仍然可以添加 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 %>

您的代码的一个问题是您仅输出每个测试一次。您希望每个问题都执行一次。更好的解决方案是编写范围。大致意思是:

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 %>

If, as your comment suggests, you're unable to alter your class structure then it's going to be a bit ugly. You can still add has_many :through to clean things up a little bit:

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

then you're going to have to nest iterators...

<% @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 %>

One issue with your code as it stands is that you're only outputting a <tr> once for each test. You want to do it once for each question. A better solution would be to write scopes. Something along the lines of:

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

Then you could do this, which looks nicer

<% @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 %>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文