Day 10: DB へ情報入力、ページに出力

/
#cebu#rails#mysql

from Qiita: マスターデータ(DBへ情報入力、ページに出力

Environment

仮想環境 OS: Ubuntu 18.04 Ruby:2.51 Rails:5.2.2

流れ

  1. 中間テーブルにデータ入力
  2. 性別の 0 or 1 の表記を、male or female に変更
  3. Student の show ページに、生徒ごとの試験結果など、データを出力

実段階

生徒データと関連付けするときは

undefined
1
student1 = Student.first
2
student1.clubs << Club.first
3
student1.save

データ入力

id1 から id100 までの生徒に、0 から 4 個の部活(選択肢は 13 部)に入ってもらう。

undefined
1
(1..100).each do |i|
2
student = Student.find(i)
3
1.upto(rand(0..4)) do
4
student.clubs << Club.find(rand(1..13))
5
student.save
6
end
7
end

生徒の試験結果情報 id100 までの生徒に、9 科目の試験を受けてもらう。

undefined
1
(1..100).each do |i|
2
student = Student.find(i)
3
1.upto(9) do |num|
4
sub = Subject.find(num)
5
exam_res = ExamResult.new
6
exam_res.name = "試験#{num}"
7
exam_res.score = rand(1..sub.max_score)
8
exam_res.subject = sub
9
student.exam_results << exam_res
10
student.save
11
end
12
end

Studentsのindexページの表記を変更

app/models/studetns.rb
1
enum gender: { male: 0 ,female: 1}
2
enum age: {"teen": 0, "twenty": 1}
app/views/_form.html.erb
1
<div class="field">
2
<%= form.label :gender %>
3
<%= form.radio_button :gender, 'male' %>男性
4
<%= form.radio_button :gender, 'female' %>女性
5
</div>
6
<div class="field">
7
<%= form.label :age %>
8
<%= form.radio_button :age, '20代' %>20代
9
<%= form.radio_button :age, '30代' %>30代
10
</div>

出力を考える

  • 学生ごとの show ページで表示したいもの
    • 生徒のデータ(name, mail, gender, age, opinion)
    • 生徒の教科ごとの試験結果点数
    • 性と全体の試験結果の平均点、最大点、最小点

MySQL上の出力

undefined
1
SELECT
2
subjects.name,
3
CAST(AVG(exam_results.score) as unsigned) as avg_score,
4
MAX(exam_results.score) as max_score,
5
MIN(exam_results.score) as min_score
6
FROM
7
students
8
INNER JOIN exam_results
9
ON students.id = exam_results.student_id
10
INNER JOIN subjects
11
ON exam_results.subject_id = subjects.id
12
GROUP BY subjects.id, subjects.name
13
14
-- =>
15
-- +--------+--------------+-----------+-------+-------+
16
-- | name | name | name | score | ratio |
17
-- +--------+--------------+-----------+-------+-------+
18
-- | taro-1 | 一次試験 | 数学 | 181 | 91 |
19
-- | taro-1 | 試験1 | 数学 | 61 | 31 |
20
-- | taro-1 | 一次試験 | 国語 | 146 | 73 |
21
-- ...

ページ上の出力

students_controllerのshowアクション編集
app/controllers/studetns_controller.rb
1
def show
2
@students =
3
Student.joins(:subjects)
4
.select('students.name, students.email, students.age, students.gender, students.opinion, subjects.id as subject_id')
5
.select('exam_results.name as exam_result_name, subjects.name as subject_name, exam_results.score')
6
.select('CAST((exam_results.score / subjects.max_score) * 100 as unsigned) as ratio')
7
.where(id: params[:id])
8
9
avg_result =
10
Student.joins(:subjects)
11
.select('subjects.id as subject_id')
12
.select('CAST(AVG(exam_results.score) as unsigned) as avg_score')
13
.select('MAX(exam_results.score) as max_score')
14
.select('MIN(exam_results.score) as min_score')
15
.group('subjects.id')
16
.order('subjects.id')
17
18
@score_hash = {}
19
20
avg_result.each do |avg_res|
21
h = Hash.new
22
h[:avg_score] = avg_res.avg_score
23
h[:max_score] = avg_res.max_score
24
h[:min_score] = avg_res.min_score
25
@score_hash[avg_res.subject_id] = h
26
end
27
end
showページのviewを編集
app/views/students/show.html.erb
1
<table border="1">
2
<tr>
3
<th>科目名</th>
4
<th>点数</th>
5
<th>平均</th>
6
<th>最高</th>
7
<th>最小</th>
8
</tr>
9
<% @students.each do |student| %>
10
<tr>
11
<td><%= student.subject_name %></td>
12
<td><%= student.score %></td>
13
<td><%= @score_hash[student.subject_id][:avg_score] %></td>
14
<td><%= @score_hash[student.subject_id][:max_score] %></td>
15
<td><%= @score_hash[student.subject_id][:min_score] %></td>
16
</tr>
17
<% end %>
18
</table>