どんもー、@snskOgataです。
今回はみんな大好き、エラーとの付き合い方を書いていこうかなと思います。
まあ、ちょっとした読み物として楽しんでもらえたらと思います。
対象読者は以下の2つに当てはまる人です。
・エラーという存在が憎くて憎くてしょうがない
・Railsアプリを読み物を見ながら1, 2度作ってみたけど、実際に自分で何も見ずに作るとなったらどうやっていけばいいかわからない
エラーが出るとどうしても怒られているような感覚になってしまいますが、
そうじゃなくて本当は、エラーは正解への道筋を示してくれる相棒のようなものだということを感じてくれると嬉しいです。
実際やっていくこととしては、
エラーを吐かせながら、それに従ってアプリケーションを作っていくということをしていきます。
これによりひとつずつ着実に作業を進めることができます。
アプリの内容は、つぶやきを作成しその一覧を表示する簡単なアプリケーションです。
途中で大体もう流れがわかったら最後まで飛ばしてくれても大丈夫です(笑)
1. Setup
まずはアプリケーションをビルドします。
Railsバージョンは5.2.3を使用します
$ rails _5.2.3_ new dev-with-error
$ cd dev-with-error
$ bundle
$ rails db:migrate
やってることはRailsアプリケーションを立ち上げ、フォルダを移動して、gemファイルのインストール、DBの作成です。
ここまでやるとローカルサーバを立ち上げることができます。
$ rails s
Webブラウザで「localhost:3000」にアクセスすればお馴染みの画面が出てきます。
2.Tweet作成画面を作る
次にTweetの新規作成画面を作っていきたいと思います。
ここで通常であれば、ルーティングをして、コントローラとモデルを作って、適切なビューを作って...とやっていくと思いますが、
今回は冒頭でも書いたようにまずはエラーを吐かせてそれに従って作っていくというふうに作って行きます。
実際にやることとしては、Tweetの新規作成画面ということで「localhost:3000/tweets/new」というアドレスにアクセスをします
まだアプリケーション本体に何も書き込んでいないわけなので当然エラーを吐かれます。
エラーの内容を見てみると、ルーティングがされていないよ!とのエラーが出ているので、実際にルーティング部分を書き加えます。
Rails.application.routes.draw do
resources :tweets, only: :new
end
もう一度先ほどのURLにアクセスすると次はこのようなエラーが出ます。
今度はTweetsControllerがないのでそれを教えてくれます。
エラーに従ってコントローラを作成しましょう。
$ rails g controller tweets
newアクションが見つからないということでTweetsControllerに追記します。
class TweetsController < ApplicationController
def new
end
end
保存をし再びページをリロードすると、
随分長いエラー文となっていますが、冒頭の「TweetsController#new is missing a template」から、newアクションに対応するビューのテンプレートがないというのがエラーの原因というのがわかります。
なので、Tweets#newに対応するように、「views/tweets/new.html.erb」を作成します。
Hello
「localhost:3000/tweets/new」にアクセスすると、
おめでとう!これで新規作成画面の表示に成功しました!
さて、新規投稿するためにインスタンス変数@tweetを用意しましょう。
class TweetsController < ApplicationController
def new
@tweet = Tweet.new
end
end
ここで再びページリロードをすると
Tweetというものがわからない!と言われるので、Tweetモデルを作成してあげます
$ rails g model tweet content:string
...
モデルが生成されましたが
問題を解決するには「rails db:migrate」して、と書かれています。
どうやらマイグレーションファイルをDBに適用していないのが問題みたいです。
$ rails db:migrate
これで再びエラー無しの状態になりました!
次に、実際にビューに今回用意したインスタンス変数を使って、フォームを作成してみます。
<%= form_with model: @tweet do |form| %>
<%= form.text_field :content %>
<%= form.submit %>
<% end %>
ここでのエラーはわかりづらいですが、form_withによってtweets_pathにポストがなされるのですが、そのメソッド(:create)が宣言されていないためにのエラーとなります。
ルーティングで「:create」を追加してあげましょう。
Rails.application.routes.draw do
resources :tweets, only: [:new, :create]
end
再びエラー無しに!
ただしcreateアクションを実際に実装していないため、フォームを入力しても何も変わりません。
なのでコントローラにcreateを追記してあげましょう。
ついでに新規投稿画面に、投稿された一覧を表示できるようにしましょう。
class TweetsController < ApplicationController
def new
@tweet = Tweet.new
@tweets = Tweet.all #追記:全投稿取得→表示に使用
end
def create
Tweet.create(tweet_params) # DBに保存
redirect_to new_tweet_path # 新規投稿画面に再び戻る
end
private
# ストロングパラメータ
def tweet_params
params.require(:tweet).permit(:content)
end
end
<% # local: trueにすることで、送信後ページが更新される %>
<%= form_with model: @tweet, local: true do |form| #local %>
<%= form.text_field :content %>
<%= form.submit %>
<% end %>
<p>Tweets</p>
<% # Tweetの一覧表示 %>
<%- @tweets.each do |tweet| %>
<%= "#{tweet.content} <#{tweet.created_at}>" %>
<br/>
<% end %>
同様にして編集ページや一覧表示ページ、あるいは新しいコントローラやモデルを作成していけば、ある程度のものであればエラーに従っていくだけで作れてしまうと思います!
3. 一気にRMVCを作ってしまう弊害
この手法だとエラーに従ってひとつずつパーツを揃えていくため、今コーディングしている部分が正しくなければ先に進むことができません。
すなわち、エラー部分が限定されて間違っている可能性がある部分というのがすごく限定的になります。
Railsを始めたての人は、MVCを一度に実装してしまったために、エラーが発生したときに何処で起きているのかがわからなくなってしまう、という問題に遭遇してる人が多い様な気がします。
なので、こういうように着実に進められる方法もあるよ、エラーは怒ってるんじゃなくて導いてくれてるんだよ、ってのを少しでも実感してくれたら幸いです。
4.テスト駆動開発
こういう開発手法を思いついたきっかけがテスト駆動開発(TDD)です。
この手法は、今回エラーを起こして進めて行ったような感じで、まずは通らないテストを書いて、それに通るように実装をしていくという手法です。
実際の現場でも使われている手法で1、一度は経験しておいて損はないかなと思います。
読みながらならある程度簡単なアプリなら作り方が理解できる方なら、Rails Tutorialという本が無料で公開されているので挑戦してみると良いかもしれません。(※Rails Tutorialはminitestというデフォルトのテストを用いているのでRSpecを使ってる方は違いには注意!)
Rails Tutorial:https://railstutorial.jp/chapters/beginning?version=5.1#cha-beginning
加えてここではgem(deviseなど)を使わずにユーザ管理を実装するのですが、Deviseの作者も一度は自分の手でUserモデルを作成することを推奨しているので、その点でもオススメです。
追記:ついでにHerokuで簡単にデプロイする方法とか、自作ヘルパーメソッドの実装とかもすごくタメになります!
-
実際はコストの面との相談で使われなかったりする? テスト自体は非常に重要なことには変わりないですが! ↩