before_action
毎回行う処理はまとめて記述できる
例えば、show,edit,update,destoryアクションで毎回同じ処理を書いていたとする。
このような場合はrailsのDRYの精神に基づいて無駄を省いていく。
before_action
これはアクションを実行する前に必ず実行してくれる関数。今回は以下のような処理が複数あったのでまとめてみた。
@project = Project.find(params[:id])
この処理をbefore_actionにかく。
before_action :set_project,only:[:show,:edit,:update,:destroy]
set_projectという関数を毎回実行する。onlyオプションをつけることで、指定したアクションの前に実行される。
set_projectはprivate関数として定義し、その関数内にまとめたい処理を書いておけばOK
Destroyアクション(削除)
モデルを削除する
とりあえず、indexにリンクをつくる。
<%=rink_to "[Delete]", project_path(project.id), method: :delete, data:{confirm:"are you sure?"} %>
いつもと違うのは、methodと確認用のアラートが追加されている。
methodにdeleteを設定することで、destroyアクションを行えるようになる。data:{confirm:""}は確認用アラートのおまじない。
Destroyアクション
def destory @project = Project.find(params[:id]) @project.destroy redirect_to projects_path
削除対象のモデルを取得して、destoryすることで削除することができる。削除したらindexにリダイレクト。
以上でCRUDの全てのアクションを実装できた。
EditとUpdateアクション
編集(editアクション)
newで作ったモデルを編集するためには、editアクションを実行する。
edit用ページへのリンク(index.html.erb)
<%= link_to "[Edit]", edit_project_path(project.id) %>
編集対象のモデルのidを一緒に渡す必要がある。
editアクション
def edit @project = Project.find(params[:id]); end
editのViewを作る
editのviewはnewと同様にフォームとボタンがある。railsのDRYに沿って、共通部分は共通化していく。
パーシャル
新たに_form.html.erbというファイルを作る。これがパーシャルというもので、ここにformのコードを書いておく。そうするとeditとnewのコードはこんな感じに。パーシャルとして使う場合のファイルの命名規則は_アンダーバーから始まること。
<%= render 'form' %>
更新(Update)
editの画面でsubmitを押した時の処理を書いていく。
updateアクション
def update @project = Project.find(params[:id]) if @project.update(project_params) redirect_to projects_path else render 'edit' end end
編集したモデルを取得して、updateでモデルを更新する。その際に、newの時と同様にフィルタリングをやっておく。project_paramsでvalitation。saveの時と同様に、update時にvalitationされるっぽい。
これで、Create Read Updateまで完成。あとは削除
Newアクション(新規作成)
新規作成の流れ
newアクションとそれに対応するviewにフォームを設置。フォームからの入力をPOSTでprojectsが受け取り、createアクションを実行するという流れ。
コントローラー(newアクション)
def new @project = Project.new end
フォームView(new.html.erb)
<h1>Add New</h1> <%= form_for @project do |f| %> <p> <%= f.label :title %><br> <%= f.text_field :title %> </p> <p> <%= f.submit %> </p> <% end %>
フォームの作成
form_forでフォームの開始と終了タグを生成できる。
ラベル作成
f.label
テキストフィールド作成
f.text_field
サブミットボタン
f.submit
データの保存
projectsにpostしてcreateアクションを起こす流れ。submitボタンを押した段階でpostされる...?
保存する仕組みとvalidation
createアクション
def create @project = Project.new(project_params) if @project.save redirect_to projects_path else render 'new' end end private def project_params params[:project].permit(:title) end end
フィルタリング
project_paramsというプライベートメソッドでフィルタリングをする。newアクションで渡ってきたprojectのtitleだけを許可するみたいな感じ。昔はこんなことしなかったみたいだけど、最近はセキュリティーを高めるために必要とのこと。お決まりの書き方。
Validation
フォームからなにも入力しなくても新しいモデルが作れてしまう。なので、適切な形でデータを保存できるようにvalidateというものをする。
project.rb(モデル)を編集
class Project < ActiveRecord::Base validates :title, presence: true end
対象はtitle、ルールはそれがあるかどうかを判定するpresenceを指定する。
@~.saveを実行した段階でvalidationが実行されるので、if文をsave部分に追加する。
そして、エラー入力があった場合は画面遷移させたくないので、falseだった場合にrenderでnewを指定することで、画面遷移せず同じ画面にとどまる。
エラーメッセージの表示(newのviewをいじる)
<% if @project.errors.any? %> <%= @project.errors.inspect %>
@project.errorsにエラーが格納されているので、if文でerrorがあるかどうか判定する。あった場合に、errosに格納されている内容をメッセージとして表示する。inspectはエラーメッセージをそのまま表示する。一旦、inspectでどんな内容か確かめ、必要な部分だけを抽出してあげるという流れ。
内容を見ると、titleがキーで、メッセージ配列の0番目にデフォルトメッセージが入っているので、これを表示してあげる。
<%= @project.errors.messages[:title][0] %>
メッセージを変える
model.rbでpresenceを設定したが、いくつでもルールを追加できるし、メッセージも自由に作ることができる。
validates :title, presence: {message: "入力してください"}, length: {minimum:3,message:"3文字以上!"}
新たにlengthという文字数指定を追加した。
因にmessage:""はシンボルをキーとして使う表記法みたい。ハッシュの書き方なのかなーrubyやってないからよく分からん。
とまあ、このな感じでフォーム作成→検証→保存の流れを作成した。
Showアクション(詳細表示)
Modelの詳細を表示する
Modelにはtitle属性をつけ、index_viewで一覧表示させた。そのmodelの各要素の詳細を表示するアクションShowを作っていく。
indexからのリンクをはる(index.html.erb)
<%= link_to @projects.title , project_path(project.id) %>
rake routesで全体像を見てみると、projectはパラメータを必要とし、showアクションを実行することが分かる。idはmigrateした段階で勝手に作られるものの一つ(あとはタイムスタンプとか)。テーブルでいうどこの列かを示すものだと思う。
showアクション
def show @project = Project.find(params[:id])
find関数を使って、指定したid(列)の要素をとってくる。
URLで渡ってきた数字はparamsに格納される。:idはシンボルでURIで指定されているもの。
show のためのviewを作る
<h1><%= @project.title %></h1>
idで指定した要素のtitleを表示する。
共通テンプレート
共通のテンプレートを編集する
場所:view/layout
<!DOCTYPE html> <html> <head> <title>Mebuy</title> <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %> <%= javascript_include_tag "application", "data-turbolinks-track" => true %> <%= csrf_meta_tags %> </head> <body> <%= image_tag "logo.png" %> <%= yield %> <%= link_to "HOME",projects_path %> </body> </html>
yieldの部分に各view独自の構造が挿入される形。
画像を表示
- イメージタグヘルパーと使うと楽(rails)
<%= image_tag "logo.png" %>
このタグはassets/imagesフォルダにある画像を参照してくれるので、必要な画像はこのフォルダに突っ込んどく。イメージタグ書くより遥かに楽ちん♩
リンク
これもヘルパーが用意されている。
<%= link_to "HOME", projects_path %>
カンマより右側はファイルのパスを表している。rake routesで表示されるあれ!
左側に書いてある名前_pathで真ん中に表示されているURIに変換してくれる!便利!