Ruby использует коллекцию / карту с атрибутом таблицы - PullRequest
0 голосов
/ 12 июля 2011

У меня есть студенты, которые сдали «тесты», у которых есть 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 '.Я не знаю, как использовать этот атрибут, чтобы получить желаемый результат.

Ответы [ 2 ]

3 голосов
/ 13 июля 2011

У вас неправильные модели.Поиграйте с этим:

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 %>
0 голосов
/ 13 июля 2011

Если, как следует из вашего комментария, вы не можете изменить структуру своего класса, то это будет немного уродливо. Вы все еще можете добавить 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 %>

Одна проблема с вашим кодом в его нынешнем виде заключается в том, что вы выводите <tr> только один раз для каждого теста. Вы хотите сделать это один раз для каждого вопроса. Лучшее решение было бы написать области. Что-то вроде:

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