Ruby on Railsの「Scaffolding(スキャフォールディング)」という機能を利用すれば、アプリの雛形を自動生成できるとご紹介させて頂きました。
【Ruby on Rails】の「O/Rマッパー」である「ActiveRecord(アクティブレコード)」、Scaffoldingで雛形アプリ作成まで
一覧画面のソースコードを見てみる。
app/controllers/users_controller.rb
一覧画面に対応するアクションとしては、下記のindexアクションになります。
1 2 3 4 5 6 7 8 9 10 |
class UsersController < ApplicationController before_action :set_user, only: [:show, :edit, :update, :destroy] # GET /users # GET /users.json def index @users = User.all end … end |
Usersモデルクラスのallメソッドを使って、インスタンス変数「@users」に格納しています。
app/views/users/index.html.erb
一覧に対応するビューとしては、こちらのビューになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<p id="notice"><%= notice %></p> <h1>Users</h1> <table> <thead> <tr> <th>Name</th> <th colspan="3"></th> </tr> </thead> <tbody> <% @users.each do |user| %> <tr> <td><%= user.name %></td> <td><%= link_to 'Show', user %></td> <td><%= link_to 'Edit', edit_user_path(user) %></td> <td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </tbody> </table> <br> <%= link_to 'New User', new_user_path %> |
<p id="notice"><%= notice %></p>
コントローラの処理結果を、ユーザーに通知したい場合に使われる変数です。
「<% @users.each do |user| %> … <% end %>」のブロック
コントローラでモデルクラスから取り出した値をループで取り出しています。
「<%= link_to」から始まる内容
「link_to」はヘルパーメソッド(ビュー、コントローラで共通で呼び出せるメソッド)で、リンクであるaタグをHTMLに出力します。
1 |
link_to リンク名,リンク先 |
link_toメソッドで使える引数
引数 | 説明 |
---|---|
リンク名 | aタグで囲むテキスト名 |
リンク先 | リンク先のURL |
link_toメソッドで指定できるリンク先について
ルーティングに出力されていたPrefixに「_path」をつけた形式を指定すると、メソッドで指定できるリンク先のURLに変換されます。
ルーティング情報及び、Prefixは下記のコマンドで確認できます。
1 |
rails routes |
表示画面
URLとしては、「http://IPアドレス:ポート番号/アクション名/ID」にアクセスした際に表示される画面になります。
まずは、コントローラの処理から見ていきましょう。
コントローラ(app/controllers/users_controller.rb)
まず、着目するのは、「before_action」から始まる下記の記述です。
1 2 3 4 |
class UsersController < ApplicationController before_action :set_user, only: [:show, :edit, :update, :destroy] … end |
結論から言えば、上記構文は、「show(表示画面)、edit(編集画面)、update(更新画面)、destroy(削除画面)」が呼び出された際に、事前処理として「set_userメソッド」を実行するという意味になります。
今回は、表示画面の解説になるので、「set_userメソッド」が呼び出されることになります。
詳しい構文の意味は、下記で解説しています。
before_actionメソッド
このメソッドは、「アクションを呼ぶ前に特定の処理をさせたい場合に定義するメソッド」になります。
構文
1 |
before_action メソッド名,条件ハッシュ |
メソッドの引数の説明
メソッドの引数 | 説明 |
---|---|
メソッド名 | コントローラ内のメソッドをシンボルとして記述します。 |
条件ハッシュ | 適用するアクションの条件をハッシュで記述します。 |
条件ハッシュの構文
1 |
(only/except):[アクションのシンボル1,アクションのシンボル2,…] |
only
指定したアクションのみに適用されます。
except
指定したアクション以外の全てのアクションに適用されます。
showアクション
表示画面は、下記の「showアクション」が対応しています。
1 2 3 4 |
# GET /users/1 # GET /users/1.json def show end |
ただし、見て分かるとおりデフォルトでは何も中身が記述されていません。
では、画面に表示させる内容は、「set_userメソッド」で設定しているのです。
set_user(アクション名)メソッド
showアクションが呼ばれる前の事前処理になります。
1 2 3 4 5 6 7 |
private # Use callbacks to share common setup or constraints between actions. def set_user @user = User.find(params[:id]) end … end |
ここでは、画面の表示させているURLのIDの値のデータを取得して、「@user変数」に代入しています。
1 |
User.find(params[:id]) |
「params[:id]」というのは、「http://192.168.10.5:3000/users/298486374」というURLで言えば、「298486374」の部分を取り出す構文(HTTPパラメータを取り出す構文)になります。
URLのどの部分を、取り出すかはルーティング情報に記載されています。
ビュー(app/views/users/show.html.erb)
1 2 3 4 5 6 7 8 9 |
<p id="notice"><%= notice %></p> <p> <strong>Name:</strong> <%= @user.name %> </p> <%= link_to 'Edit', edit_user_path(@user) %> | <%= link_to 'Back', users_path %> |
ビューの出力内容は、ほぼ一覧画面で出力している内容と同じです。
しいて言えば、画面表示に事前処理の「set_user(アクション名)メソッド」で代入した「@user」を使っていることでしょう。
登録画面
「Scaffolding」で自動生成された下記の「登録画面」のソースコードを見ていきます。
コントローラ(app/controllers/users_controller.rb)
登録画面のアクションとなるのは、「newアクション」になります。
1 2 3 4 5 6 7 8 9 |
class UsersController < ApplicationController before_action :set_user, only: [:show, :edit, :update, :destroy] … # GET /users/new def new @user = User.new end … end |
@user = User.new
Userモデルクラスのnewメソッドを使うことで、インスタンスを生成して、「@userインスタンス変数」に格納しています。
ビュー(app/views/users/new.html.erb)
1 2 3 4 5 |
<h1>New User</h1> <%= render 'form', user: @user %> <%= link_to 'Back', users_path %> |
<%= render 'form', user: @user %>
下記の構文を使っています。
1 |
<%= render 部分テンプレート名, キー1: 値1,キー2:値2 %> |
部分テンプレート
ビューから切り出されたビューファイルのことです。
登録画面の入力フォームの部品内容を、各画面の共通処理として使いまわすことができるというメリットがあります。
登録画面で呼びされる部分テンプレートとしては、下記のパスにあるビューファイルになります。
また、第二引数で指定している「キー:値」のセットについては、「部分テンプレート(_form.html.erb)」の中に、アクションメソッドで用意された@user(Userモデルクラスのインスタンス)にuser変数でアクセスするということを意味しています。
<%= link_to 'Back', users_path %>
一覧画面へのリンクの作成をしています。
部分テンプレート(app/views/users/_form.html.erb)
部分テンプレートは、他の画面から共通処理として呼び出されるテンプレートになります。
new.html.erbから共通の部分テンプレートとして呼び出されているファイルになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<%= form_with(model: user, local: true) do |form| %> <% if user.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2> <ul> <% user.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= form.label :name %> <%= form.text_area :name %> </div> <div class="actions"> <%= form.submit %> </div> <% end %> |
form_withビューヘルパー(<%= form_with(model: user, local: true) do |form| %> ~ <% end %>)
引数の形式によって様々なformタグを出力するヘルパーメソッドです。
ヘルパーメソッドとは、ビューやコントローラで共通して呼び出されるメソッドのことです。
構文
1 2 3 |
<%= form_with(model: モデルクラスのインスタンス, local: 真偽値) do |form| %> 表示するフォームの内容 <% end %> |
今回の場合はモデルクラスのインスタンスにuserが指定されているので、userモデルクラスの値をフォームの内容に使用することができます。
local:真偽値
Ajaxによるデータ更新を許可するかどうかの設定になります。
真偽値 | 説明 |
---|---|
true | Ajaxによるデータ更新を許可する必要がない場合に指定する。 |
false | Ajaxによるデータ更新を許可する必要がある場合に指定する。 |
Ajaxについては、下記の記事で解説していますので、合わせてご覧下さい。
画面に出力されるHTML
下記のHTMLが出力されます。
1 2 3 4 5 |
<form action="/users" accept-charset="UTF-8" method="post"> <input name="utf8" type="hidden" value="✓" /> <input type="hidden" name="authenticity_token" value="Q7XS5s0p+B5fz9JkDZvOxWwzRtu5J5q3jBQXYaaQHOMLczS56uCvn1a97mU8gOv2l9PdP3jaK58ATFc+mvVVzg==" /> … </form> |
「<input type="hidden" name="authenticity_token"…」から始まるinputタグは、CSRF(クロスサイトリクエストフォージェリ)という不正アクセス対策に使用されるタグのことです。
labelビューヘルパー(<%= form.label :name %>)
構文
1 |
<%= form.label フィールド名 %> |
フィールド名
モデルクラスのインスタンスのフィールド名のことです。
出力されるHTML
1 |
<label for="user_name">Name</label> |
for属性で指定されている値は、その後に生成されるテキストエリア等の値と同じになります。
text_areaビューヘルパー(<%= form.text_area :name %>)
構文
1 |
<%= form.text_area 引数,属性名1:値1 %> |
登録画面に、「textareaタグ」を出力します。任意ですが、出力されるtextareaタグに属性を増やしたい場合は、カンマ区切りで指定します。
出力されるHTML
1 2 |
<textarea name="user[name]" id="user_name"> </textarea> |
name属性には、「オブジェクト名[カラム名]」のような配列が出力されています。
submitビューヘルパー(<%= form.submit %>)
構文
1 |
<%= form.submit %> |
登録画面にサブミットボタンを出力します。
出力されるHTML
1 |
<input type="submit" name="commit" value="Create User" data-disable-with="Create User" /> |
data-disable-with属性は、二重クリック防止対策のための属性です。
データ登録
Scaffoldingで生成されたソースコードの登録画面のフォーム部分を見るとURLが「families(リソース名)」に対してPOSTしていることがわかります。
1 2 3 4 5 6 7 |
<form action="/families" accept-charset="UTF-8" method="post"> <input type="hidden" name="authenticity_token" value="rI2sNF03GVrmh1i+zm3ZQNrJ7uIRAGVKEZNDgepKM0djHXNCNhV2aZbKzDxhxo/1H6zQXRD0oKLkqz3fPnvhaQ==" /> ‥ <div class="actions"> <input type="submit" name="commit" value="Create Family" data-disable-with="Create Family" /> </div> </form> |
コマンドでルーティングの情報をみてみるとfamiliesのPOSTはcreateメソッドを呼ぶようになっています。
コントローラのcreateメソッドは下記のようになっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def create @family = Family.new(family_params) respond_to do |format| if @family.save format.html { redirect_to @family, notice: 'Family was successfully created.' } format.json { render :show, status: :created, location: @family } else format.html { render :new } format.json { render json: @family.errors, status: :unprocessable_entity } end end end |
@family = Family.new(family_params)
famiily_paramsメソッドの戻り値を引数としてfamiliyモデルのインスタンスをnewメソッドで作成しています。
famiily_paramsメソッド
プライベートメソッドとして同じコントローラに下記のように定義されています。
1 2 3 |
def family_params params.require(:family).permit(:name) end |
Strong Parameters(ストロングパラメータ)
Strong Parameters(ストロングパラメータ)という構文で下記のように指定します。Strong Parametersは意図しないキーからパラメータは弾きエラーとするのでセキュリティ対策にもなります。Rails4から追加された仕組みです。(Rails3までは同じような仕組みとしてMassAssignmentが利用されていましたが脆弱性が見つかり、現在のところStrong Parameterが一般的に利用されています。)画面からサーバに送られてくるパラメータに制限をかけることができ不用意なデータがDBに登録できないようにするというセキュリティを向上させることができます。
1 |
params.require(モデル名).permit(キー1,キー2‥) |
params
フォームから送信された値のことです。
require(:family)
引数には取得したいモデル名を指定します。そうすると入力フォームの値のハッシュ(キーと値の組み合わせ)になります。
permit
ハッシュから取得したい入力フォームの値のキーを指定します。
respond_toメソッド
ファイルのURLの末尾の拡張子によって処理を分ける場合に使用します。
RailsではURLに拡張子が何も指定されていない場合はHTMLと判断し、末尾に「.json」がついている場合はフォーマットがJSONと判断します。
1 2 3 4 |
respond_to do |format| format.html{URLの拡張子がHTMLの場合に実施する処理} format.json{URLの拡張子がJSONの場合に実施する処理} end |
@family.save
familyテーブルにデータを保存するメソッドです。保存に成功したらtrueを返し失敗したらfalseを返します。
redirect_toメソッド
リダイレクトを行います。後述するrenderと違ってURLを直接実行するので再度リクエストが発生することになります。
1 |
redirect_to リダイレクト先,出力メッセージ(flashメッセージ) |
redirect_to @family
@familyというのは現在のオブジェクトのIDを示すので「families/新規登録ID」というURLにリダイレクトされることになります。ルーティング情報をみるとshowメソッドが呼ばれるので「show.html.erb」というビューに飛ぶことになります。
flashメッセージ
リダイレクトの際に、次のリクエストに対してデータを伝えるためにRailsが用意している仕組みで内部的にはセッションを利用して実現がされています。
上記コードのように「notice:」で指定した場合はnotice変数に格納されるので、ビュー側のHTMLでは「<%= notice %>」で参照できます。
render :show, status: :created, location: @family
テーブルにデータ登録が成功してかつURLの拡張子がJSONだった場合の処理です。redirect_toメソッドと違って2度リクエストが発生はしません。
render :show
views/falimlies/show.json.jbuilderをビューとして呼ぶ。
status: :created
Webサーバからの応答を示し、createdの場合はHTTPステータスコード201を返します。
location: @family
新しく登録されたデータのURLを示します。
views/falimlies/show.json.jbuilder
登録が成功して、URLの拡張子がJSONだった場合に呼ばれるソースになります。ソースの中には下記のような処理が記述されています。
1 |
json.partial! "families/family", family: @family |
json.partial!ビューヘルパー
構文は下記のように記述して「JBuilder形式」の部分テンプレートを呼び出します。
1 |
json.partial! 部分テンプレート名,キー1:値1,キー2:値2‥ |
実際に呼び出すのは「views/families/_family.json.jbuilder」というファイルになります。
views/families/_family.json.jbuilder
下記のようなソースコードが記述されています。
1 2 |
json.extract! family, :id, :name, :created_at, :updated_at json.url family_url(family, format: :json) |
json.extract!ビューヘルパー
1 |
json.extract! モデルオブジェクト,カラム要素1,カラム要素2‥ |
モデルオブジェクトのキーと値のペアを出力します。上記例で言えば、familyテーブルのID、名前、登録日、更新日をJSON形式で出力することになります。
json.url family_url(family, format: :json)
URLを生成します。「families/ID.json」というURLを生成することになります。
render json: @family.errors, status: :unprocessable_entity
json: @family.errors
全てのエラーメッセージをJSON形式で返します。
status: :unprocessable_entity
HTTPステータスコード422を返し処理できなかったことを表します。
jbuilderとは?
Railsが標準で採用しているgemの一つでJSON形式のデータを出力するための簡単な記述方法を提供してくれるものです。
jbuilderの拡張子
拡張子を「.json.jbuilder」とするとそのビューファイル内でjbuilderが提供する記述を使うことができます。
jbuilderが提供する記述
json.partial!ビューヘルパー
jBuilder形式の部分テンプレートを呼び出すことができます。
json.extract!ビューヘルパー
モデルオブジェクトのカラム要素の値をJSON形式で出力します。
この記事へのコメントはありません。