今更ですが後編です。

元記事

RUNTEQの講師をやってみてわかった初学者にありがちなパターン20選(後編)

前編

RUNTEQの講師をやってみてわかった初学者にありがちなパターン20選(前編)

11. 『フォームとは』が曖昧

Rails云々の以前の話で、フォームがなんなのかの理解が浅いです。Railsから入った人は特にそうなのかもしれません。

  • nameとvalueがペアになってサーバに送られる
  • nameとvalueはinputやselectやradioなどに付与される
  • action属性に指定されたURLに対して入力値が送られる

これを知っているだけでRailsでの開発が一気にスムーズになるはずです。
逆にこれを知らないとform_withなどのフォームヘルパーが何をやっているかブラックボックスすぎて魔法のようにしか感じられないでしょう。

フォームとは要はクライアントとサーバの窓口です。お互いを繋ぐものです。お互いを繋ぐというからにはインターフェース(接点)があるはずです。
ではインターフェースとはなんでしょう。具体例を書きます。

クライアント(フォーム部分)

<input type="text" name="user[email]" value="dyson@example.com">

サーバ(コントローラ)

params.require(:user).permit(:email)

インターフェースはどこでしょう?
・・・
・・

はい!
name="user[email]"user部分がrequire(:user):user部分に対応します。
name="user[email]"email部分がpermit(:email):email部分に対応します。

これがインターフェースです。
訳も分からずrequire(:user)permit(:email)を使ってませんか?

ぜひインターフェースを意識する癖をつけていただきたいです。

12. フォームヘルパーが魔法に感じる

【11. 『フォームとは』が曖昧】に関連する話です。フォームとはなんぞやがわかってないとform_withなどのフォームヘルパーが魔法に感じます。『何をやってくれてるのかよくわからないけどユーザー新規登録できた!ログインできた!』となりがちです。

フォームについて再掲します。

  • nameとvalueがペアになってサーバに送られる
  • nameとvalueはinputやselectやradioなどに付与される
  • action属性に指定されたURLに対して入力値が送られる

form_withはこれらをよしなに設定した上でフォームを生成してくれてるに過ぎません。

= form_with model: @user do |f|
  = f.label :email 
  = f.email_field :email

このようにいちいちname属性やらaction属性やらを書かなくても「よしなに」設定してくれます。
余談ですがこの「よしなに」力があり過ぎるが故にRailsは初学者向きではないという意見もあって、確かになーという感じです。

13. 実際に出力されているHTMLを見ない

これも【11. 『フォームとは』が曖昧】【12. フォームヘルパーが魔法に感じる】に繋がる話ですが、何かうまくいかないときにビューテンプレート(new.html.erbやedit.html.erbなど)とにらめっこする人が多いです。

結局ブラウザが解釈してるのはそのビューテンプレートを元に生成されたHTMLです。なので『このform_withの書き方どっかおかしいのかな?』とビューテンプレートと対峙していてもらちがあきません。まずはブラウザの開発者ツールからHTMLソースをみましょう。そしてname属性には何が設定されているか、action属性には何が設定されているか、etcを確認しましょう。

14. 何か機能を作るときにER図を書かずに実装を始める

こういう人が案外多いなと感じました。
実際には書きださなくても良いですが、少なくとも頭の中にER図が浮かんでないと実装は不可能です。

ある機能を実現したい場合、それをRDBではどう表現するかを考えるべきです。慣れないうちはER図を書き出すと良いでしょう。

15. テーブル設計

【14. 何か機能を作るときにER図を書かずに実装を始める】の問題について、テーブル設計の引き出しがまだ足りてないのでER図を書こうにも書けないのだと推測します。これは色んなパターンに出会うしかないでしょう。

これ、結構おもしろいです。テーブル設計のプロセスを学べる実践的な内容になってます。
楽々ERDレッスン

16. 何か機能を作るときにエンドポイントを意識せずに実装を始める

エンドポイントを意識せず実装を始める人が一定数いました。

例えばユーザーの新規作成・ログイン・ログアウトの機能を作るとします。
実装前にこんな表を自分で作ってみると良いでしょう。

Image from Gyazo

まず「やりたいこと」を書き出していって、それぞれどういうエンドポイントにすべきかを記入していきます。あとはそれに沿ってルーティングやコントローラを作っていけばOKです。

その際、RESTfulなルーティングを心がけましょう。基本的に「index new create edit update show destroy」の7つのアクションで仕様を満たせないか考えてみましょう。

17. レンダーとリダイレクトを混同しがち

  • レンダーは特定のビューテンプレートを利用してレスポンスをクライアントに返す
  • リダイレクトは再度サーバサイドにリクエストを投げている

英語の意味を考えるとわかりやすいかも。

render・・・描写する
redirect・・・re + direct = 再び、道を教える

このサイトの図がわかりやすいです。
render と redirect の違い

18. マイグレーションの理解が浅い

マイグレーションは、データベーススキーマの継続的な変更 (英語) を、統一的かつ簡単に行なうための便利な手法です。マイグレーションではRubyのDSLを使っているので、生のSQLを作成する必要がなく、スキーマとスキーマへの変更をデータベースの種類に依存せずに済みます。

1つ1つのマイグレーションは、データベースの新しい'version'とみなすことができます。スキーマは最初空の状態から始まり、マイグレーションによる変更が加わるたびにテーブル、カラム、エントリが追加または削除されます。Active Recordは時系列に沿ってスキーマを更新する方法を知っているので、履歴のどの時点からでも最新バージョンのスキーマに更新することができます。Active Recordはdb/schema.rbファイルを更新し、データベースの最新の構造と一致するようにします。

Railsガイド マイグレーションの概要

  • マイグレーションファイルを作ったタイミングでDBに反映される
  • 『やっぱりstring型からtext型に変更しよう!』と考えた時に、マイグレーションファイルを直接変更すればDBに反映される

という勘違いが案外多いです。

マイグレーションファイルはあくまでも「データベーススキーマの継続的な変更を、統一的かつ簡単に行なうための便利な手法」です。データベーススキーマを更新するにはSQLを発行する以外方法はありません。そのためにはrails db:migrateを実行する必要がありますよね。
ただ、一度実行したマイグレーションファイルは再度実行されないので一旦ロールバックするなどして未実行の状態に戻してあげないといけなかったりします。その辺の理解を深められると良いなーと思いました。

19. パラメータを理解してなさげ

コントローラでよく使うparams。こいつがなんなのかのイメージがついてなさげです。すごいざっくり言うとクライアントから送られてきたデータです。

<input type="text" name="email" value="abc@example.com">

という入力項目があってこれをサーバサイドに送ると

def create
  p params[:email] # => abc@example.comが取ってこれる
  # 省略...
end

こんな感じでparams[:email]でユーザーの入力値が取ってこれます。

【11. 『フォームとは』が曖昧】で書いた『インターフェース(接点)』にも密接に関わってくるところですね。

Webサービスは所詮クライアントから何か値を渡してサーバサイドはそれを受け取って何か処理してレスポンスを返すをやっているに過ぎません。送られてきたパラメータを使って何をするかがRuby(Rails)のお仕事です。このparamsの中身を入力値としてUser.create(email: params[:email])のようにcreateやnewメソッドの引数に渡しています。

paramsとはユーザーから送られてきた値が入ってるもの。これを使ってサーバサイドでごにょごにょお仕事をする
これを覚えておいてください。

20. database.ymlを意識しない人が多い。

RailsチュートリアルではSQLiteを使っているためか、database.ymlを意識しない人が多いです。

RUNTEQではMySQLを使ってローカルに環境を作ってもらってます。
こんな構成になってます。

名称未設定ファイル.png

SQLiteを使っているとデータベースサーバへのログインなんて考えませんが、実際はMySQLなりPostgresqlなりのサーバがあってそこにログインする必要があります。また、そのデータベースサーバの中でどのデータベースを使用するかを指定する必要もあります。そういった情報が書かれているのがdatabase.ymlです。

例)

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root # こことか
  password: password # こことか
  socket: /tmp/mysql.sock

development:
  <<: *default
  database: sample_app_development # こことか

こういうところを意識しないと環境構築で詰まる可能性大ですし、詰まった時に解決できないです。

まとめ

以上、ここ数ヶ月初学者に教えてきて思った『初学者ありがちパターン』でした!!
ちょっとでもRails初学者の方の助けになればと思います!