概要
Rails開発で最低限気をつけること(=気をつけてほしいこと)をメモ
少し長いですがRailsを覚え始めの人に読んでいただければと。
全般
タイポをしない
当たり前ですが、タイポの原因はタイピングをミスすることです
残念ながらrubyは動的型付け言語であり、タイポによるエラーはプログラム実行時に発生します
タイポを防ぐ方法として、
- Lintを活用する
- 変数はコピペする
- スペルが間違っていないか辞書 or Google で検索するようにする
などが挙げられます
上記を徹底し、 視覚的にタイポを防ぐ 、 タイピングをやめる ことでタイポ0を目指しましょう
インデントを揃える
PullRequestを作成する前には、必ずコードのフォーマットを直しましょう
インデントが揃っていることはソフトウェアエンジニアのマナーの一つだと思います
String vs Symbol
Symbolの方がパフォーマンスが良いため、できるだけStringではなくSymbolを使うようにしてください
理由は下記の記事を参考ください
Rubyの文字列とシンボルの違いをキッチリ説明できる人になりたい - Qiita
if
vs if not
vs unless
rubyでは条件式の判定に、 if
if not
unless
などがあります
条件式が複雑かつ、否定演算子などが組み合わされると一気に可読性が低下し、バグの原因につながるため、
条件式では「常に正常系を」書くようにしています
いくつか例を挙げてみます
例: if ~ else
構文
if @record.save # 条件式は正常系
# 成功時の処理を書く
else
# 失敗時の処理を書く
end
例 unless
でGurad構文(=早期リターン)
def process(record)
return false unless record.valid? # 早期リターン(=条件式は正常系)
# 以下、正常系の処理を実行
end
「常に正常系を」を記述することのを推奨する理由については下記リンクを参考にしてみてください
ifとunlessの使い分け
boolean型のメソッド名には末尾に ?
をつける
一般的に、rubyではbooleanを返すメソッドには末尾に ?
をつける習慣があります
メソッド名の末尾に ?
がついていることで boolean を返すことがわかり可読性が上がります
ぼっち演算子 &.
をつける
rubyでは、2.3から &.
演算子(safe navigation operator = ぼっち演算子)が導入されました
実行時に nil なオブジェクトに対してメソッドチェーンを実行すると undifined method error for nil:NilClass
と
なってしまうため、nil
になる可能性のあるメソッドチェーン呼び出しには全て &.
をつけるようにすべきです
ソースコードの責任の範囲を意識する
OOPの思想に沿って、ソースコードの責任の範囲を考えて設計&実装する
Rails開発はMVCに依存しがちになますが、もっと柔軟にクラスを切った方が良いと思います
また、アプリケーションやビジネスロジックに依存せず汎用的に使えるクラスは lib
配下に記述することもおすすめします
例として、下記のようにディレクトリを切ると良いかなと思います
- app
- controllers
- decorators
- forms # form経由の値を扱う(Controllerをファットにさせない)
- helpers
- jobs
- listeners # wisperなど、Observerパターンでcallbackを処理する
- mailers
- models
- operators # ビジネスロジックを扱う(ControllerやModelをファットにさせない)
- policies # punditなどで権限管理
- validators # 独自定義したバリデーション
- values # Valueオブジェクト
- lib
- xxx
- xxx
- xxx
Controller
before_action
でインスタンス変数への代入を控える
before_action
を複数記述した場合、記述した順番に実行されます
before_action
内で、他の before_action
で代入された変数を呼び出すと、
プログラムが正しく動作するかどうかが before_action
を呼び出す順番に依存してしまい、
スパゲッティコードにつながってしまいます
可能であれば変数を取得できるメソッドを作成することをおすすめします
× before_action
を使う
class UsersController < ActionController::Base
before_action :set_user, only: [:show]
def show
end
def set_user
@user = User.find(params[:id])
end
end
◯ 専用のメソッドを用意する
class UsersController < ActionController::Base
def show
end
def user
@user = User.find(params[:id])
end
helper_method: user
end
helper_method :user
とすることで、viewファイルでも変数を参照できるようになります
インスタンス変数をメモ化する
ActiveRecord
経由で取得するデータは、変数をメモ化することで値のキャッシュができます
展開された変数はリクエスト終了時にクリアされるため、可能な限りキャッシュすることをおすすめします
class UsersController < ActionController::Base
def show
end
def user
# @note @user がnilの場合のみ代入され、nilでなければキャッシュされたデータを返す
@user ||= User.find(params[:id])
end
helper_method: user
end
レコードの保存処理を行う場合は flash
を表示する
レコードの保存処理を行う場合は成功時&失敗時に合わせて適切なflashメッセージを表示するようにしてください
def create
if @record.save
redirect_to records_path
flash[:success] = 'レコードの保存に成功しました'
else
render :new
flash.now[:error] = 'レコードの保存に失敗しました'
end
end
def destroy
if @record.destroy
redirect_to records_path, flash: { success: 'レコードを削除しました' }
else
redirect_to records_path, flash: { error: 'レコードを削除できませんでした' }
end
end
また、レコードの更新に失敗し render
を実行する場合は flash.now
を使うようにしてください
参考: 【Rails】flashとflash.nowの違い - avosalmonのブログ
Model
belongs_to
には required: true
または presence: true
をつける
belongs_to
で必ず親となるレコードが存在する場合は、 required: true
または presence: true
を記述してください
has_one
, has_many
には class_name
をつける
has_one
または has_many
を使う場合は、 class_name
オプションをつけることで、
モデルが取得できずエラーとなってしまうことを防ぐことができる場合があるため、記述するようにするべきです
必要に応じて foreign_key
も指定することをおすすめします
has_one
, has_many
には dependent
オプションをつける
削除時に has_one
または has_many
先の子モデルに対する振る舞いを dependent
オプションで定義できます
不要なレコードはDBのパフォーマンスにも影響が出るので、適切に設定することをおすすめします
dependent
オプションについては、下記リンクで詳しく説明されていたので参照してみてください
ActiveRecord::has_manyのdependentオプション
バリデーションを記述する
DB層でのバリデーションが必要なカラムに対しては、validates
メソッド等を使って
適宜バリデーションを記述する
また、必要に応じて適宜カスタムバリデーションを作成して再利用できるようにすることもおすすめします
カスタムバリデーションを実行する
View
form_with
を使う
Rails5.1からは form_for
と form_tag
が form_with
というインターフェースに統合され、
URLベース、スコープ、モデルを指定してformタグを生成できるようになりました
※ form_for
を使う場合は local: true
を設定してください
https://qiita.com/bluegirl_beer/items/a361171f653edcd888ad
form_for
や form_with
ではモデルの指定でaction先を絞る
railsで自動生成されるpathって読みづらいですよね
form_for
や form_with
では、渡すオブジェクトが保存されているかどうかで
create
のアクションを実行するか、 update
のアクションを実行するかを自動的に判別してくれます
また、必要に応じて method
や action
オプションを渡すことで、アクション先を絞ることができます
DB
migrationファイルでカラムを追加するときは comment
をつける
comment
オプションをつけることで、生成されるスキーマファイルにコメントを追加できます
可能な限りコメントの追加をお願いします
class CreateBlogs < ActiveRecord::Migration[5.1]
def change
create_table :blogs, comment: 'ブログ' do |t|
t.string :title, comment: 'タイトル'
t.text :body, comment: '本文'
t.timestamps
t.datetime :deleted_at
end
end
end