Ruby on Rails 機能の追加
一覧画面のコントローラーを開発しよう
タスク一覧ページがリクエストされた時に呼ばれる
タスクスコントローラーのindexメソッドを実装!!
ファイルエクスプローラーで
app→controllers→task_controller.rb
ファイルを開く
ルーティングでいうと、
1行目のtasks#indexの行を実装していく!
次のように入力する
def index
@tasks = Task.all
end
Task.allでタスクステーブルから全てのレコードを取得!
(開発者がデータベースを操作するためのSQLを書かなくて済む!)
実際にはrailsが裏でSQLを発行している。
SQLはターミナルに表示されるので、
意図しないSQLが発行されていないか確認できる!
Task.allの戻り値を@tasksに代入
@tasksはタスクの一覧を格納するために使うインスタンス変数
(このインスタンス変数はview側でも利用できる)
一覧画面のビューを開発しよう
先ほど作成したTasksControllerの
indexメソッドに対応するビューを開発する
(タスクの一覧表示画面のビューを作成)
app→views→tasksファイル配下に
index.html.erbファイルを作る
次のように入力する
<h1>Tasks</h1
<ul>
<% @tasks.each do |task| %>
<li>
<%= check_box_tag '','' %>
<%= task.title %>
</li>
<% end %>
</ul>
補足
このファイルはerbテンプレートrubyのプログラムが埋め込める
テンプレートを使っている
ファイルのベースはhtmlだが、テンプレートエンジンerbを使うことにより、
<% %>
<%= %>
で囲まれた部分にはrubyのプログラムを書くことができる
コントローラーから渡されたインスタンス変数@tasksには、
複数のタスクのデータが入っているので
それをrubyのeachで一つずつ取り出しながら、
タスクの完了状態を管理するためのcheck_box_tag(ダミー)と
タスクのタイトルを出力している
⚠️よくある間違い!⚠️
<% %>
イコール記号がないものは任意のコードを実行したい時に使う
<%= %>
イコール記号があるものは、何かページに出力したい時に使う
railsサーバーを起動し、動作確認をする!
このようにデータベースに登録した
タスク名とチェックボックスがリスト表示されていればOK
新規タスクの追加機能を開発しよう
ルーティングのtasks#newの行を使って実装していく
TasksControllerのnewメソッドを実装する
(タスクを新規に追加する画面の実装)
def new
@task = Task.new
end
タスクモデルのインスタンスをnewメソッドで作り、
インスタンス変数@taskに入れる
@taskはview側でフォームを作成する時に利用する
views配下のtasksの中にnew.html.erbファイルを作る!
次のように入力!
<h1>New</h1>
<%= form_with model: @task do |form| %>
<% end %>
form_withヘルパーメソッドでformビルダーをインスタンス化する
formビルダーと呼ばれるrailsの機能を使用してフォームを作成!
formビルダーを使用すると、最小限のコードを記述すれば
railsの規則に従ったフォームを簡単に出力できる!
form_withに利用するモデルのインスタンスをセットすると、
ファイルのPWなどを自動的に設定してくれた上で
HTMLのコードが生成される
ここでいうヘルパーメソッドとはviewをよりシンプルに書くために用意された機能
次のように、フォームの各パーツを実装することができる!
<p>
<%= form.label :title %><br>
<%= form.text_field :title %>
</p>
<p>
<%= form.submit %>
</p>
URLに/tasks/new入力して、ページを表示すると、、
このように表示されていればOK!
Googleクロムのデベロッパーツールで
どのようなHTMLが生成されているか見てみる
例えば、Titleラベルを右クリックして検証すると、
formタグが生成されているのがわかる🙆🏻♀️
form_withのモデルにインスタンスを渡すことで
適切なPWであったり、メソッドが指定されている。
labelメソッドはラベルテキストを生成する。
text_fieldメソッドは、テキストボックスを生成する!
HTMLのタグとしては、input type="text"が生成されている。
submitメソッドはsubmitボタンを生成する!
HTMLのinput type="submit"タグを生成
次に、送信ボタンが押された時のコントローラーの処理
tasks#createの行を使う
tasks_controllerを開き
送信ボタンが押された時に呼ばれるcreateメソッドを実装していく!
createメソッドではフォームから送られてきたデータを元に
データベースに値を保存する
フォームから送信されるデータはpalamsというメソッドで所得できる!
palamsメソッドは、フォームなどによって
送られてきた情報(パラメーター)を取得するメソッド!
簡単にできる方法としてはpメソッドを使う!
def create
p params
end
サーバーにデータを送信すると、
createメソッドが呼ばれて
pメソッドでparamsの値がターミナルに出力される
ターミナルにParametersの値が出力された状態であれば、
それを開発に利用することも可能!
ストロングパラメーターを利用しよう
ストロングパラメーター(Strong Parameters)とは、
Ruby on Railsでリクエストパラメータを安全に受け取るための仕組みのこと!
ストロングパラメーターは、Mass Assignment(一括代入)攻撃を防止するために導入された。
Mass Assignment攻撃とは、、
ユーザーが送信したパラメーターを直接モデルに保存することによって、
意図しないデータが保存されたり、不正な操作が行われることを意図した攻撃。
例えば、ユーザーがフォームから送信したパラメーターを直接モデルに保存した場合、
ユーザーが送信したはずのデータとは異なる、不正なデータが保存されることがある。
ストロングパラメーターを使用することで、
不正なデータの保存を防止し、セキュリティを向上させることができる。
private
def task_params
params.require(:task).permit(:title)
end
privateを指定するとそれより配下は
privateメソッドとして扱われる
class内からのみ利用できる!
メソッド名は慣習として
モデル名_paramsとする
requireメソッドでデータのオブジェクト名を指定する
permitメソッドでデータベース保存の処理に使うカラムを指定
(カンマ区切りで複数指定できる!)
指定した以外のデータを送ってくる悪意のあるリクエストを受けた時に
permitメソッドで許可していない項目については
データベースの値の変更には使われなくなり、データの扱いがより安全になる🙆🏻♀️
データベースに値を保存しよう
def create
@task = Task.new(task_params)
@task.save
redirect_to root_path
end
createボタンは新規登録ボタンが押された時に呼ばれる!
フォームに入力されたデータをもとにタスクモデルを作成。
task_params経由で、データをモデルにセットすることで
フォームから送信されたデータのうち、
タイトルカラムのみデータベースに保存するようにしている🙆🏻♀
セーブを行い、ルートパスにリダイレクトする。
データベースに新規タスクが追加されて
一覧画面に遷移、値が追加されていればOK!
新規追加画面へのリンクを設置しよう
一覧画面からタスクの新規追加画面へ遷移できるリンクを設置
index.html.erbファイルに次のように記述!
<%= link_to 'new', new_task_path %>
link_toメソッドとは、、ハイパーリンクを生成するヘルパー
'new'の部分がハイパーリンクを設定したい文字列
new_task_pathがパスになる
(Prefix、new_taskに_pathをつけたものを指定している)
動作検証をして、
newのリンクをクリックして新規追加画面へ遷移すればOK!
バリデーションを追加しよう
バリデーションとは?
- 記述・入力したデータが、あらかじめ規定された条件た仕様、形式などに適合しているかどうかを検証・確認すること
- 例)未入力チェック、文字数チェック
バリデーションの練習
- Title...未入力チェック、5文字以上であること
この条件に引っ掛かる場合は、データをセーブできないようにする
さらに、バリデーションエラーのメッセージを表示して値を修正するように促す
app→models→task.rbファイルに記述
validates :title, presence: true, length: { minimum: 5}
これで、タイトルカラムについてpresence: trueで未入力チェック
length: { minimum: 5}の記述で5文字以上の文字列が入力されているかチェック!
次にtasks_controllerを修正!
createメソッドを編集する
def create
@task = Task.new(task_params)
if @task.save
redirect_to root_path
else
render 'new', status: :unprocessable_entity
end
end
renderメソッドはviewファイルを指定して表示することができるメソッド
status: :unprocessable_entityでステータスコード422でレンダリングする。
422はバリデーションエラーの場合に返すステータスコード
次にnew.html.erbファイルを編集!
エラーメッセージを表示する部分を記述
text_fieldの下に記述
<% if @task.errors.any? %>
<%= @task.errors.messages[:title][0] %>
<% end %>
バリデーションエラーがある場合は、
@task.errors.any?がtrueになるので
下のエラー表示部分を有効にする。
@task.errors.messagesに配列でエラー内容が入っているので
titleの先頭の1つについて画面に表示する。
動作確認
新規タスク登録画面を開き、
タイトルを空のまま送信すると
can't be blankと表示されてデータベースに値は保存されない
5文字以下を入力して送信しても
is too short(minimum is 5 characters)
短すぎて保存ができません。
5文字以上入力して送信すると、
データベースに値が保存されて一覧画面に遷移できた!
一覧画面から編集画面へのリンクを作成しよう
タスクの編集機能を開発していく!
一覧画面の各タスクに編集画面へのリンクをつける
編集ページの表示には、tasks#editの行のルーティングを使う!
index.html.erbを開き編集!
task.titleの下に次のように入力
<%= link_to '[edit]', edit_task_path(task) %>
ファイルを保存し、ページをリロードすると
編集画面へのリンクがついた!🙆🏻♀️
編集画面を開発しよう
編集画面を表示するときに使うルーティングはtasks#editの行
編集画面のフォームから送信されたデータを受け取って処理をすることに使う
ルーティングはtasks#updateの行
編集画面のviewを作成する
app→views→tasks配下にedit.html.erbファイルを作成
tasks_controllerを開き、createメソッドの下に書いていく!
editメソッドを作成
def edit
@task = Task.find(params[:id])
end
編集するタスクの情報をデータベースから取得する必要がある。
編集画面を表示するときのURLに着目すると
/tasks/1/edit
とあるが、1のところはtasksのID!
このIDを使ってデータベースから該当のレコードを取得できる。
ターミナルを見ると、
Parameters: {"id"=>"1"}
と表示されている。つまりIDはparamsメソッドで取得できる!
paramsからidだけを抜き出すには、
p params[:id]
ターミナルを見るとIDが出力されている。
idを指定してタスクステーブルからレコードを取得するには、、
@task = Task.find(params[:id])
タスクモデルのfindメソッドで引数にidを指定することで、
該当のレコードを取得できる
インスタンス変数@taskに代入して、viewに渡す。
次に、edit.html.erbファイルを編集!
new.html.erbと見出しを除いて同じになるのでコピペして
NewをEditに変更!
既存の値もセットされて表示される!
次に送信ボタンを押した時の処理
tasks_controllerを開き、updateメソッドを使い記述する!
def update
@task = Task.find(params[:id])
if @task.update(task_params)
redirect_to root_path
else
render 'edit', status: :unprocessable_entity
end
end
まず、タスクのインスタンスをフォームから送られてきたデータを使って作成する。
該当のレコードをアップデートするには、モデルのupdateメソッドを利用。
ストロングパラメーターを利用し、updateが成功したら
root_pathへリダイレクトする。
もしバリデーションエラーなどでupdateが失敗した場合は、
elseの方でもう一度編集画面を表示する!
動作確認
Titleに5文字以上の文字を入力して、
タイトルが書き変わっていればOK!!
削除機能を開発しよう
タスクを削除する機能を開発
一覧ページの各タスクに削除リンクを設置する!
削除には、tasks#destroyの行のルーティングを利用
tasks_controllerを開き、updateメソッドの下にdestroyメソッドを記述!
def destroy
@task = Task.find(params[:id])
@task.destroy
redirect_to root_path, status: :see_other
end
φ(・・
まずデータベースから該当のidのタスクを取得して@taskに入れる!
destroyメソッドで該当のタスクを削除
削除が終わったら、root_pathへリダイレクト
redirect_toメソッドでstatus: :see_otherを指定すると
HTTPステータスコード303が使われる!
(意味は新規リソースへの移動)
フォームへ投稿後に、何らかのURLに転送したいときに使われるコード
ステータス:see_otherをつけないと、
意図しない不具合を発生させる原因になるので必ず記述する!
次に、index.html.erbファイルを開き
削除を実行するためのリンクを作成する!
編集リンクの下に記述していく!
<%= link_to '[destroy]', task_path(task)
data: { turbo_method: 'delete', turbo_confirm: 'Are you sure?'}%>
point
turboメソッドにdeleteを指定する。
確認ダイヤルを出すためにturbo_confirmの部分に、
ダイヤログに表示させるメッセージを書いている。
rails7では、turboというrailsの記述でJSのような
動作を簡易的に実現できる仕組みが使われているため
turbo_というprefixをつけるルールになっている!
ファイルを保存して、動作確認!
削除したいタスクのdestroyをクリックして、
確認ダイヤルのOKボタンを押すとデータが削除できた!🙆🏻♀️
リファクタリングをしよう
railsの基本理念に同じことを繰り返さない
Don't Repeat Yourselfというものがある。
コードの共通化を行う!
複数の場所に同じコードを繰り返し記述するのは避けましょうということ。
例えば、フォームの入力項目が増えた時に
一箇所変更を加えればよくなるためメンテナンス性が高まる!
機能は変えずにコードを整理してより良くすることを
リファクタリングという
viewsフォルダのtasksフォルダ配下に
_form.html.erbファイルを作成!
共通化して呼び出すビューのファイル名の先頭には_をつけるルール!
そこに共通化するコードを記述する!
_form.html.erbファイルを呼び出す記述
<%= render partial: 'form' %>
renderメソッドを指定して、partialにファイルを指定する!
(先頭の_や拡張子は書かないルール!)
partialとは、一部のや部分的なといった意味!
ファイルを保存して、動作確認!
同じように動作すればOK〜〜〜
明日で今やっている講座終わりそうだから、
アドバイスをもらった通りにまた最初から繰り返しやってみる!!
学校行くまでの予習期間、
今やっていることを自分のものにできるよう頑張る!
Discussion