学生が科目選択してホゲホゲするアプリの雛形である.手順を以下に示す.なお「Ruby on Railsにおける多対多モデルの実装」も参照のこと.
準備
まず,Railsでdeviseを用いてユーザ管理するところ,ログイン後にマイページを表示させるようにして,自分以外のマイページにはアクセスできないようにする,そのような機能を備えたところまで作り込んだテンプレートを GitHub にアップロードしておいたので,そこからダウンロードすると,簡単だろう.
$ git clone https://github.com/iiojun/ulexample.git
Railsの環境を整える.なお,Rubyのバージョンが違う!とエラーになるときは,Gemfile を弄ってバージョンを揃えるか,rbenv を使っている人は適切なバージョンをインストールしておくこと.
$ bundle install
...
$ bin/rails webpacker:install
...
$ bin/rails db:create
...
$ bin/rails db:migrate
...
以上の手続きをして,環境を整える.コンソールを1つサーバ起動用に用意して,サーバはずっと起動させておくとよい.
$ bin/rails s
ブラウザから localhost:3000/mypage/ にアクセスすると,Mypage#home が表示されるはず.sign up のためのリンクがあるのでそこをクリックしてユーザアカウントをsign up,ログインできるかどうか確認せよ.ログインできると Mypage#show が表示されるはずである.
Lectureの導入
Lecture モデルを作成し,Lecture コントローラの雛形を作る.Lecture は,タイトルと教員と教室のデータを持つものとする.実際には曜日だの何限だのと,もっと多くの情報を入れるべき(説明のために単純化している).
Lectureの情報にアクセスするためのルーティングを設定する.
config/routes.rb を編集し,次のようにする(get 'lectures/index' 等は削除してよい).
Rails.application.routes.draw do
namespace :mypage do
root to: 'home#index'
resources :users, only: [ :show, :update, :edit ]
end
root to: 'lectures#index'
resources :lectures, only: [ :index, :show ]
#resources :user_lectures, only: [ :create, :destroy ]
devise_for :users, controllers: {
sessions: 'users/sessions',
passwords: 'users/passwords',
registrations: 'users/registrations'
}
end
http://localhost:3000 で lectures の一覧が表示されるようになる.ただし,まだこの時点 では何も表示されない.
app/controllers/lectures_controller.rb を以下のとおりに修正する.
class LecturesController < ApplicationController
def index
@lectures = Lecture.all
end
def show
@lecture = Lecture.find(params[:id])
end
end
index では全てのエントリを取得し,show では指定するエントリを取得するという基本的なパターンである.
ビューを設定する.app/views/lectures/index.html.erb を以下のとおりに修正する.
<h1>Lectures List</h1>
<ul>
<% @lectures&.each {|lecture| %>
<li><%= link_to lecture.title, lecture_path(lecture) %>
<%= ": #{lecture.teacher}, @ #{lecture.room}" %></li>
<% } %>
</ul>
テスト用に,コンソールからデータを入れてみよう.ダミーデータなので,好きなデータを入れてよい.
$ bin/rails c
Running via Spring preloader in process 91299
Loading development environment (Rails 6.1.4.1)
irb(main):001:0> Lecture.create(title: '国際情報学演習 I', teacher: '飯尾淳', room: '501')
...
irb(main):002:1> Lecture.create(title: '国際情報学演習 III', teacher: '飯尾淳', room: '501')
...
irb(main):003:0> Lecture.create(title: 'プログラミング基礎', teacher: '飯尾淳', room: '501')
...
irb(main):004:0> exit
ブラウザで localhost:3000 にアクセスし,一覧が表示されることを確認せよ.
科目をクリックしてもそっけないテンプレートが表示されるだけなので,なんとかしよう.
app/views/lectures/show.html.erb を以下のとおりに修正する.
<h1>Lecture Info</h1>
<ul>
<li>科目: <%= @lecture.title %></li>
<li>教員: <%= @lecture.teacher %></li>
<li>教室: <%= @lecture.room %></li>
</ul>
一覧に表示された科目のリンクをクリックすると,科目情報の詳細が表示されるようになった.
UserLectureの導入
User と Lecture には多対多の関係がある.そこで,User と Lecture を繋ぐ UserLecture モデルを導入する.
$ bin/rails g model user_lecture user:references lecture:references evaluation:integer
なお,UserLectureの属性として evaluation という項目を一つ用意しているが,ここは,いろいろと追加すること(今回はevaluationだけ使う).
モデル間の関連付けをする.
app/models/user.rb を次のように修正する(赤字部分を追記).
class User < ApplicationRecord
has_many :user_lectures
has_many :lectures, through: :user_lectures
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:rememberable, :validatable
def email_required?
false
end
end
また app/models/lecture.rb を次のように修正する.
class Lecture < ApplicationRecord
has_many :user_lectures
has_many :users, through: :user_lectures
end
app/models/user_lecture.rb は,モデル作成時に references を指定して作ると自動で belongs_to が追記されるので,なにもし なくてよいが,いちおう,こうなっている.
class UserLecture < ApplicationRecord
belongs_to :user
belongs_to :lecture
end
モデルを作ったらデータベースに反映させる.
$ bin/rails db:migrate
UserLectureの操作(生成と削除)
コントローラを作成する.UserLectures はこのサンプルでは作って消すだけなのでとりあえず create と destroy だけだが,評価を記入する画面を作るときには show と update も必要になるかな?まあ,後からメソッドを追加すればよかろう.
$ bin/rails g controller user_lectures create destroy
ルーティングを設定する.config/routes.rb を編集し,次のようにする.
Rails.application.routes.draw do
namespace :mypage do
root to: 'home#index'
resources :users, only: [ :show, :update, :edit ]
end
root to: 'lectures#index'
resources :lectures, only: [ :index, :show ]
resources :user_lectures, only: [ :create, :destroy ]
devise_for :users, controllers: {
sessions: 'users/sessions',
passwords: 'users/passwords',
registrations: 'users/registrations'
}
end
app/views/lectures/show.html.erb を以下のとおりに修正する(赤字部分を追記).
<h1>Lecture Info</h1>
<ul>
<li>科目: <%= @lecture.title %></li>
<li>教員: <%= @lecture.teacher %></li>
<li>教室: <%= @lecture.room %></li>
</ul>
<% if current_user %>
<% if @registered %>
<%= link_to '登録をやめる', user_lecture_path(@registered), method: :delete, class: 'btn btn-danger' %>
<% else %>
<%= link_to '登録する', user_lectures_path(lecture: @lecture),
method: :post, class: 'btn btn-primary' %>
<% end %>
<% end %>
<br /><br />
<%= link_to '科目一覧へ戻る', lectures_path %>
app/controllers/lectures_controller.rb に一行(赤字部分)追記する.画面の都合上,下記では折り返しているが,実際には一行でよい.
class LecturesController < ApplicationController
def index
@lectures = Lecture.all
end
def show
@lecture = Lecture.find(params[:id])
@registered = UserLecture
.find_by(user: current_user, lecture: @lecture)
end
end
app/controllers/user_lectures_controller.rb を次のように作る.
class UserLecturesController < ApplicationController
def create
lecture = Lecture.find(params[:lecture])
UserLecture.create(user: current_user, lecture: lecture)
redirect_to lecture_path lecture
end
def destroy
ul = UserLecture.find(params[:id])
UserLecture.destroy(ul.id)
redirect_to lecture_path ul.lecture
end
end
ここまでの設定で,UserLecture のデータを生成,削除できるようになった.ログインした状態で科目の詳細ページにアクセスすると「登録する」ボタンができているはず.
「登録する」ボタンを押してみよう.UserLecture#create が発動され,UserLecture データが登録される.処理終了後,redirect_to が設定されているので,再度,Lecture#show に戻るが,そのときは既に登録済み(@registered が nil ではない)なので,「登録をやめる」ボタンが表示されるようになる.
「登録をやめる」を押すと UserLecture#destroy の処理を経た結果,同様の動作で元にもどる.[この動作の仕組みを考えて,きちんと理解すること]
登録済み科目のマイページへの表示
登録した Lecture をマイページに一覧表示させる.
app/views/mypage/users/show.html.erb を以下のとおりに修正するだけでよい.
<h1><%= current_user.fullname %>'s MyPage</h1>
<h2>登録済み科目一覧</h2>
<ul>
<% current_user.lectures&.each {|lecture| %>
<li><%= link_to lecture.title, lecture_path(lecture) %>
<%= ": #{lecture.teacher}, @ #{lecture.room}" %></li>
<% } %>
</ul>
マイページに登録済みの科目一覧が表示されるようになった.
科目の評価ボタンの追加
では,科目を評価するインタフェースを作ろう.ログインしていたら科目の詳細ページから科目を評価できるようにする.科目評価のために,UserLectureに show と update を追加する.
ルーティングを設定する.config/routes.rb を編集し,次のようにする(赤字部分が追記した箇所).
Rails.application.routes.draw do
namespace :mypage do
root to: 'home#index'
resources :users, only: [ :show, :update, :edit ]
end
root to: 'lectures#index'
resources :lectures, only: [ :index, :show ]
resources :user_lectures, only: [ :create, :edit, :update, :destroy ]
devise_for :users, controllers: {
sessions: 'users/sessions',
passwords: 'users/passwords',
registrations: 'users/registrations'
}
end
app/views/lectures/show.html.erb に次の行(赤字部分)を追加する.
<% if current_user %>
<% if @registered %>
<%= link_to '登録をやめる', user_lecture_path(@registered), method: :delete, class: 'btn btn-danger' %>
<%= link_to '評価する', edit_user_lecture_path(@registered),
class: 'btn btn-success' %>
<% else %>
<%= link_to '登録する', user_lectures_path(lecture: @lecture),
method: :post, class: 'btn btn-primary' %>
<% end %>
<% end %>
<br /><br />
<%= link_to '科目一覧へ戻る', lectures_path %>
評価ページへのボタンが追記された.ただし,コントローラを書いていないので,押すとエラーになる.
科目の評価(編集画面と更新処理)
ボタンを押すと,UserLecture#edit が呼ばれるようになる.そこで,UserLecture のコントローラを修正する.
app/controllers/user_lectures_controller.rb に次(赤字部分)を追記する.edit, updateメソッドの追記と,ストロングパラメータの処理の追加を行なった.
class UserLecturesController < ApplicationController
def create
lecture = Lecture.find(params[:lecture])
UserLecture.create(user: current_user, lecture: lecture)
redirect_to lecture_path lecture
end
def edit
@ul = UserLecture.find(params[:id])
end
def update
ul = UserLecture.find(params[:id])
p = user_lecture_params
ul.evaluation = p[:evaluation]
ul.save
redirect_to lecture_path ul.lecture
end
def destroy
ul = UserLecture.find(params[:id])
UserLecture.destroy(ul.id)
redirect_to lecture_path ul.lecture
end
private
def user_lecture_params
params.require(:user_lecture).permit(:evaluation)
end
end
評価を編集するビューを書く.
app/views/user_lectures/edit.html.erb を次のように用意する.
<h1>Evaluation of Lecture</h1>
<p>
科目: <%= @ul.lecture.title %><br />
教員: <%= @ul.lecture.teacher %><br />
教室: <%= @ul.lecture.room %>
</p>
あなたの評価:
<%= form_with model: @ul do |f| %>
<%= f.select :evaluation, [['鬼', 1], ['やや鬼', 2], ['普通', 3],
['やや神', 4], ['神', 5]],
include_blank: true %>
<%= f.submit '送信' %>
<% end %>
これでOK.「評価する」ボタンを押すと,次のような画面になる.
プルダウンメニューから選択肢を選んで,送信すれば,登録される.「評価する」を再度押すと,先ほど評価した値が設定されていることを確認せよ.ただし,科目の登録をやめると,UserLecture そのものが削除されてしまうため,評価も再度やり直しになる点には注意のこと.
科目の評価処理の確認
また,上記の評価処理を行なった結果,データベースに評価が登録されていることを,次の手順でも確認できる.
$ bin/rails c
Running via Spring preloader in process 94649
Loading development environment (Rails 6.1.4.1)
irb(main):001:0> UserLecture.all
UserLecture Load (0.6ms) SELECT "user_lectures".* FROM "user_lectures"
=>
[#<UserLecture:0x000000014223bcc8
id: 8,
user_id: 1,
lecture_id: 1,
evaluation: 5,
created_at: Thu, 28 Oct 2021 22:16:47.783474000 UTC +00:00,
updated_at: Thu, 28 Oct 2021 22:19:02.728075000 UTC +00:00>]
irb(main):002:0>
コンソールで確認すると,evaluation に値がセットされていることがわかる.
とりあえずここまで.
0 件のコメント:
コメントを投稿