※勉強メモです。
##Rails(Webアプリケーションフレームワーク )
ユーザがHTTPリクエストの4つのCRUD(POST、GET、PUT、DELETE)を使って、Web上のリソースを操作するアプリケーション
Web上のリソースとは、Webページに表示されるすべて
ただし、ユーザに変更権限があるものとないものがある
#####・MVC役割構造
URLとHTTPメソッドを受取り、Controllerに渡すのが、Router
リソース(データ)として振舞うのが、Model
Modelを表示・整形するひな形が、View
ModelやViewを制御するのが、Controller
#####・Rails開発の流れ
1.Model:リソースであり操作対象であり扱うデータを決める
2.Router:Modelを置くURLを決定
3.ルーティングごとに
(1)Controller
(2)View
#####・Railsプロジェクト作成コマンド
rails new プロジェクト名
#####・Bundler
RubyやRailsのプロジェクトで使用するライブラリの管理ツール
Gemfileというファイルにインストールしたいライブラリ名と必要なバージョンの一覧を全て書き出し、bundle installで一気にそれらのライブラリをインストールできる
『gem 'ライブラリ名', 'バージョン指定'』
# バージョン 5.2.x の内、最新をインストールする
gem 'rails', '~> 5.2.2'
# バージョン 0.4.4 以上で 0.6.0 未満の中で、最新のライブラリをインストールする
gem 'mysql2', '>= 0.4.4', '< 0.6.0'
# 最新のライブラリをインストールする(バージョン指定無し)
gem 'spring'
#####・Gitでバージョン管理
プロジェクト作成後はまずコミットしておく
(リポジトリの初期化)
ターミナル、cdで作成フォルダに移動した時(master)と書かれていれば初期化不要。入っていない場合はgit intでバージョン管理を開始
$ git add . #フォルダ内全て選択
$ git commit -m "init Rails Project" #-mを付けてcommit
$ git branch -M main #ブランチ名をmainに変更
(REPLとは)
Read-eval-printloopの略で「読込み-処理-表示」の繰り返しの意味
ターミナルでirb
を実行することで、RubyのREPLが起動
終了はexit
#####・Rails console
ターミナルで実行すると、irb(main):001:0>というirbによるRubyコマンド待受状態になる
コードを変更したらreload!する。reload!コマンドを実行しないと再変更後のRubyコードは反映されない
#####・サーバの起動rails s
#####・エラーの発生
#####Mysql2::Error::ConnectionError
mysql2 の Gem からエラーは発せられていてり、データベースとの連携でエラーが出ていることを予想する
エラーを解消するために、新規でターミナルのタブを開き、sudo service mysql start
で MySQL サーバを起動
#####Activerecord::NoDatabaseError
エラーメッセージから、'message-board_development' のデータベース名で作成すれば良さそうだと予想
#####・MySQL連携の設定ファイルの確認と変更
Rails のデータベースの接続設定を管理しているファイルは config/database.yml
この設定をRailsがサーバ起動時に読み込むことで、RailsとMySQLの接続が確立(連携)される
#####・MySQL接続時のユーザを変更
初期ではdefaultでrootに設定されているので、MySQLレッスンで作成したdbuserに変更
config/database.yml の16・17行目あたりにある username と password の設定を以下のとおりに変更し、ファイルを保存
username: dbuser
password: dbpass
#####・データベースの作成
rails db:create
👇
Created database 'message-board_development'
Created database 'message-board_test'
上記のデータベースが作成され、エラーが解決
#####・サーバを起動してデータベースの接続を確認
rails s
#####・Model
リソースであり操作対象。永久保存されるデータのためデータベースと密接に関係している。
はじめに作成するアプリケーションは、どんなデータを扱うのかを決める。
#####・Modelwo作成する
rails g model Message content:string
#####「メッセージのテーブル設計」
#####・マイグレーションファイル
Railsではマイグレーションファイルという、テーブル管理ファイルによってデータベースのテーブルを管理・実行する
主に、テーブル作成・削除、カラム追加・削除に関することがファイル内に記述される
Railsでテーブルの設定を変更したいときは、マイグレーションファイル作成、Railsからマイグレーション実行をする
def change ... end
内にテーブル操作が書かれる
#####・マイグレーションの実行
マイグレーションファイルの作成だけでは実行されない
rails db:migrate
で実行
※マイグレーション実行後は、このファイルを修正してもテーブルの変更はできない!
変更を加える時は、rails g migration
によって追加のマイグレーションファイルをさらに生成する
#####・マイグレーションの確認
MySQL ログイン
$ sudo mysql -u root
データベースの選択
mysql> use message-board_development
テーブル一覧確認(messagesテーブルが作成されているか確認)
mysql> show tables;
テーブル設計の確認
mysql> describe messages;
#####・モデルクラスの作成
マイグレーションでmodels/messages.rbも作成される
ActiveRecord::Base → ApplicationRecord という順番でクラスを継承した Message モデルには、それらの機能が全て継承されており、Message クラスにコードが無くてもモデル操作できる
#####ActiveRecord:
Railsという大きく統合されたライブラリ群の中の1つで、Model全般の操作を担うライブラリ
Railsアプリとのデータベース連携を担う
ActiveRecordを介する事で、ほとんどSQLを書かず、Rubyの文法でレコードを操作可能になる
#####・Modelで使用するCRUDメソッド一覧
all:全レコード取得
new:新規レコードの為のモデルインスタンス作成
find:idを指定して検索
find_by:id以外でも指定して検索
where:検索条件を文字列、配列、ハッシュのいずれかの方法で与えられる
first:最初のレコードを1件だけ取得する
save:レコードの作成
update,save:データの更新
destroy:データ削除
モデル名::メソッド名やモデルのインスタンス.メソッド名で使用
これらのRubyメソッドを使うことで、Rubyコードが自動的にSQLに変換されて実行される
ORM(Object-relational mapping):オブジェクト指向プログラミング言語コードでデータベースを操作できる技法
#####・Rails consoleでモデルのCRUD操作
rails console前に必ずSQLサーバ起動確認sudo service mysql status
・モデルの一覧を確認
Messages.all
・モデルのインスタンスを作成
message = Message.new(content: "test")
・モデルのインスタンスに値を代入
message.content = "hello"
・モデルのインスタンスをデータベースへ保存(Create)
message.save
#####・モデルのインスタンスの取得(Read)
all:複数のレコードを取得するメソッドで、レコード全体を取得
First:最初のレコードのインスタンスを返す
find:idから単一のレコードを検索し返す
find_by:id以外でも単純な条件で検索可能
Where:条件指定してレコードを検索
・レコードの更新(Update)
findなどでレコードを取得、インスタンスに対して値を再代入、Saveするのが通常
・レコードの削除(Delete)
destroy:削除
#####・RouterとControllerとViewの開発概要
-
Router:URLのルーティングを一元管理している
config/routes.rbの1ファイルで、ルーティングを全て把握できる -
Controller:ユーザから送信されてきたHTTPリクエストの処理を担当
HTTPリクエストはRouterからControllerの1つのメソッドに割り当てられる
Routerと対応するControllerのメソッドをアクションと呼ぶ -
View:最終的にHTTPレスポンスとして返すWebページ
#####・RouterとControllerとViewの開発の流れ
どんな機能を作るか考え、実装すべき機能が挙がると、
1.ルーティングを決める
2.Controllerのメソッドを決める
3.Viewの名前を決める
#####「Router」
・リソースに対するCRUDの為の4つのルーティング
Rails.application.routes.draw do
get 'messages/:id', to: 'messages#show'
post 'messages', to: 'messages#create'
put 'messages/:id', to: 'messages#update'
delete 'messages/:id', to: 'messages#destroy'
end
:idはURLにidを入れる
POSTの場合だけidは不要。新規作成のためidはまだ用意されていない
・CRUDのための残り3つの補助ページ
詳細ページ(show)にアクセスするには、一覧ページ(index)が必要
get 'messages/:id', to: 'messages#show'
この詳細ページにアクセスするには、まずリソースの一覧ページがないと、個々のリソースページである詳細ページへ辿り着けない
👉一覧ページ(index)を付け加える
get 'messages', to: 'messages#index'
・保存アクション(create)にデータを送るには、新規作成用フォームページ(new)が必要
get 'messages/new', to: 'messages#new'
・更新アクション(update)にデータを送るには、更新用のフォームページ(edit)が必要
get 'messages/:id/edit', to: 'messages#edit'
・削除アクション(delete)はボタンがあればOK
どこかのページに削除ボタンが設置してあれば、削除ページは不要
#####・7つの基本ルーティングの省略形
Rails.application.routes.draw do
# CRUD
get 'messages/:id', to: 'messages#show'
post 'messages', to: 'messages#create'
put 'messages/:id', to: 'messages#update'
delete 'messages/:id', to: 'messages#destroy'
# index: show の補助ページ
get 'messages', to: 'messages#index'
# new: 新規作成用のフォームページ
get 'messages/new', to: 'messages#new'
# edit: 更新用のフォームページ
get 'messages/:id/edit', to: 'messages#edit'
end
👇
Rails.application.routes.draw do
resources :messages
end
これでさっきのルーティングと全く同じ意味になる。
indexやshowという命名をした理由は、resourcesで生成されるルーティングがそのように決まっているから
・Routerの完成
トップページにアクセスした時のルーティングをMessagesControllerのindexアクションに設定する。
indexアクションは、トップページ「/」と「/messages」にアクセスした両方で同じルーティングが設定されたことになる
Rails.application.routes.draw do
root to: 'messages#index'
resources :messages
end
・Routerの確認
routes.rbで少し込み入ったコーティングをした場合、rails routes
で現状のルーティングを確認できる
resources :messagesで生成される7つのルーティングを『RESETfulなルーティングと呼ぶ』
RESETfulと言われたら、7つの基本アクション(index,show,new,create,edit,update,destroy)を思い出すように
#####●ControllerとView
・Controllerの作成
rails g controller コントローラ名(モデルの複数形)
Modelと同様に、継承によってControllerとしての基本機能が提供される
・ControllerをRESETfulなルーティングに対応させる
routes.rbで設定したルーティングに対応したアクションをmessages_controller.rbに追加
Controller内のルーティングと同じ名前のメソッド名として定義
・7つのアクションに対応したViewファイルの作成
GETメソッドで指定されたルーティングのみ
GET以外はリソースの具体的な操作の為
index.html.erb のように .erb だけでなく、.html と入れているのは、 ERB ファイルが HTML ファイルへと変換されることを Rails に対して明示するため
・共通部の書き出し
HTMLを書く時に必ず共通部分が出てくる
やhead内要素
application.html.erbにまとめる!
body要素内の<%= yield %>に埋め込まれるページが切り替わる
👉<%= yield %>にindex.html.erbなどの内容が代入される
・7つのルーティングに対するレスポンスの実装
controllerのindexアクション:Messageモデルのレコード一覧表示
def index
@messages = Message.all
end
viewの作成ほか・・・
link_to 表示文字列, リンク先
<%= link_to message.id,message %>
message のように Model のインスタンス(レコード)を渡すと、自動的にそのインスタンスの show アクションへとリンクされる
省略せずに書くと message_path(message) となり、リンク先 にこう記述しても正常に動作する
message も message_path(message) もどちらも最終的に /messages/1 など/messages/:id の形の URL を生成しているだけ
【リンク生成の為のメソッド】
Prefixとしてmessages,new_messagesなどが載せられている
ルーティングを設定すると、自動的にリンク生成の為のメソッドも定義される
(Prefix + _path)となる
:idが必要なものはインスタンスを特定する必要があるので、引数として@messageなどのインスタンスが必要
<%= link_to message.id, message_path(@message) %>
#####・View
ERBにフォームを設置
form_withを使用して生成
<h1>メッセージ新規作成ページ</h1>
<%= form_with(model: @message, local: true) do |f| %>
<%= f.label :content, 'メッセージ' %>
<%= f.text_field :content %>
<%= f.submit '投稿' %>
<% end %>
<%= link_to '一覧に戻る', messages_path %>
form_withでフォーム開始、endで終了
form_with(model: @message)のように、Controllerのnewアクションで用意した@messageを使用してフォームを作成する事を明示する
(local: true)抜かすと画面推移しない通信が発生
今回はサイト内での遷移であること、ならびに画面遷移を伴う同期通信のみで構わないため local: true をつける
f.label,f.text_fieldでカラムを指定し、@messageの中のどのカラムに対する入力欄なのかを明示
f.submitで送信ボタンを生成
<%= link_to '新規メッセージの投稿', new_message_path %> を追加して、 index から new へのリンクを作成
def create
@message = Message.new(message_params)
if @message.save
flash[:success] = 'Message が正常に投稿されました'
redirect_to @message
else
flash.now[:danger] = 'Message が投稿されませんでした'
render :new
end
end
def edit
end
def update
end
def destroy
end
private
# Strong Parameter
def message_params
params.require(:message).permit(:content)
end
コード下部 privateは、それ以降に定義されたメソッドがアクションではなく、クラス内でのみ使用する事を明示
def message_params が【Strong Parameter】
ちゃんと必要なパラメータを把握し、送信されてきたデータを精査(フィルタリング)しようということ
今回は:content以外のデータはフィルタにかけて捨てるようにしている
params.require(:message)でMessageモデルのフォームから得られるデータに関するものと明示し、.permit(:content)で必要なカラムだけを選択している
コード上部 @message = Message.new(message_params)で、Messageインスタンス生成時に、Strong parameterが使用されている
・redirect_toとrenderの違い
redirect_to:強制的に移動させる。createアクション実行→showアクション実行後、show.html.erbが呼ばれる
render:単にmessage/new.html.erbを表示するだけ(アクションは実行しない)
・flashとflash.nowの違い
redirect_toの前ならflash。HTTPリクエストを発生させるため、flash.nowだと内容を保存できず消えてしまう。
renderの前ならflash.now。HTTPリクエストを発生させないため消えない。
・flash表示ファイルの作成
<% flash.each do |message_type, message| %>
<div><%= message %></div>
<% end %>
全てのviewで表示させたいため、application.html.erbでrenderする
(renderと書かれた場所に_flash_messages.html.erb の記述内容が埋め込まれる)
名前が_から始まるファイルを作成し、Viewの一部を抜き出して記述したものを『パーシャル』と呼ぶ
flashに代入されたメッセージを1つ1つ取り出し、全表示する。flashはハッシュである為、|key, value|のペアで取り出される。
今回は|message_type, message|という変数名を用いている。
<body>
<div class="container">
<%= render 'layouts/flash_messages' %>
<%= yield %>
</div>
</body>
●messages#edit
既存のメッセージレコードを編集するので、idでメッセージレコードを検索する。(params[:id])
destroyアクションのredirect_to messages_url
今までprefix_pathだったが、リダイレクトの場合だけは上記で↑
messages_urlはPrefixがmessagesのためindexへリダイレクトされる
リダイレクトの時だけ_urlを使用する
<%= link_to 'このメッセージを削除する', @message, method: :delete, data: { confirm: '本当に削除してよろしいですか?' } %>
method: :delete =DELETEメソッドを送信するのを明示
data: { confirm: ... } =javaScript
【bootstrapの適用】
・link_toにクラスを指定する
class "..."
・bootstrapのページネーション
コマンドでBootstrap用のkaminariのviewを生成
rails g kaminari:views bootstrap4
ページネーションに手を加える場合、viws/kaminariフォルダ内のファイルを編集
・show
showのp要素をテーブルに
<table>
<thead> table header
<tr> table rou(行)
<td> table data
...
一覧に戻るリンクを削除。navbarがあるため、タイトルクリックでindexに戻る為
・new
フォームにform-groupとform-controlのclass属性を付与
グリッドシステム
横長のテキスト入力欄をグリッドシステムで横半分に
フォームをrowとcol-6のdiv要素で囲む→6/12で半分
new.html一覧に戻るリンク削除
・edit
フォームはパーシャルで更新済
一覧に戻るリンク削除
####まとめ
ModelはControllerによって必要なものが取得され、Viewに流れて表示される。ユーザのHTTPリクエストをRouterが解析し、リクエストに沿って適切なModelをユーザに表示するのがWebアプリケーション。
Modelはデータベースが無いと保存できない。データベースが用意される事で、Modelのインスタンスをレコードとして保存できるようになる。
【エラーのデバック】
エラー画面には以下の情報が含まれる
エラータイトル:例外クラスの名前と、発生場所
エラーが起きたファイル名:ファイルのパスと行番号
エラー詳細:エラーメッセージ
エラーが起きた行:強調表示される
トレース状況:エラーが起きたメソッドの呼び出し状況を出力
リクエスト情報:Railsサーバに送信したリクエスト
パラメータ:必要なパラメータが含まれているか、間違っていないか
レスポンス情報:Railsサーバーがどんなレスポンスを返したか
・エラーの修正手順
1.エラーの概要を理解する
タイトルと詳細を読んで概要を理解する
よくあるエラー👇
「NoMethodError in ...」
undefined method (a)for(b)
bにaというメソッドが存在しない。定義されていない、bに正しいデータが入っていない場合が多い
bがnil:NilClassの場合、エラーが起きた場所より前で正しくデータをセットできているか確認
「ActiveRecord::RecordNotFound in ...」
Coludn't find a with b
bの条件を満たすaが見つからない。ユーザIDを指定したけど、DB上にデータが存在しないなど。
「routingError」
No route matches [a] "b"
bのURLへのaメソッドのリクエストを受け取ったが、対応するルーティング設定がない
rails routesコマンドの結果や、routes.rbの内容を確認する
「Missing Template」
コントローラのアクションに対応するビューが存在しない
erbファイルが存在し、ファイルパスが正しい事を確認
「Syntax Error」
プログラムの文法エラー
・エラー発生部分を特定する
・ソースコードを修正する
Railsのデバックツール
pry-byebug Gemfileの追加
gem 'pry-byebug', group: :deveropment
bundle install
使い方
ソースコードの途中で、Railsアプリケーションの実行を一時的に止められる。実行を止めたい部分に「binding.pry」という1行を追加