📖

【Rails】Rails開発者が知っておくべきスタイルガイドまとめ

2024/07/28に公開

はじめに

Railsのスタイルガイドを参考に、振り返り用に、まとめ記事を記載していこうと思います。
https://github.com/rubocop/rails-style-guide

1. ルーティング

menber,collectionルーティング

RESTful リソースにさらにアクションを追加する必要がある場合、memberおよびcollectionルートを使用します。(本当に必要か検討する)

# bad
get 'orders/:id/confirm'
resources :orders

# good
resources :orders do
  get 'confirm', on: :member
end

# bad
get 'users/active'
resources :users

# good
resources :users do
  get 'active', on: :collection
end

複数のルートを定義する必要がある場合は、member/collection代替ブロック構文を使用します。

resources :orders do
  member do
    get 'confirm'
    # more routes
  end
end

resources :users do
  collection do
    get 'active'
    # more routes
  end
end

名前空間ルート

関連するアクションをグループ化するには、名前空間ルートを使用します。

namespace :admin do
  # Directs /admin/customers/* to Admin::CustomersController
  resources :customers
end

2. コントローラー

ステータスコード

数値の HTTP ステータス コードよりも、対応するシンボルを優先します。

# bad
render status: 200
# good
render status: :ok

# bad
render status: 404
# good
render status: :not_found

# bad
render status: 500
# good
render status: :internal_server_error

# bad
render status: 422
# good
render status: :unprocessable_entity

DBに変更を加える時

ActiveRecordオブジェクトを永続化する際は、例外を投げるbang!メソッド(例:create!、save!など)を使用するか、メソッドの戻り値をチェックして適切に処理するべきです。createsaveupdatedestroyfirst_or_createfind_or_create_byなどでの使用時に推奨されます。例外メソッドは失敗時に例外を発生させ、通常のメソッドでは戻り値を使用して成功か失敗を判断します。

# bad
user.create(name: '山田')

# bad
user.save

# good
user.save!
# or
if user.save
  ...
else
  ...
end

3. モデル

多対多のassociation

has_and_belongs_to_manyよりもhas_many :throughを優先してください。 has_many :throughを使用することで、結合モデルに属性と検証を追加することができます。

# not so good - using has_and_belongs_to_many
class Product < ApplicationRecord
  has_and_belongs_to_many :categories
end

class Category < ApplicationRecord
  has_and_belongs_to_many :products
end

# preferred way - using has_many :through
class Product < ApplicationRecord
  has_many :categorizations
  has_many :categories, through: :categorizations
end

class Categorization < ApplicationRecord
  belongs_to :product
  belongs_to :category
end

class Category < ApplicationRecord
  has_many :categorizations
  has_many :products, through: :categorizations
end

バリデーションの記載

検証を読みやすくするために、検証ごとに複数の属性をリストしないように記載します。

# bad
validates :email, :password, presence: true
validates :email, length: { maximum: 50 }

# good
validates :email, presence: true, length: { maximum: 50 }
validates :password, presence: true

コールバックの順序

コールバック宣言は、実行される順序で並べます。

# bad
class User
  after_commit :after_commit_callback
  before_validation :before_validation_callback
end

# good
class User
  before_validation :before_validation_callback
  after_commit :after_commit_callback
end

SQLインジェクション対策

クエリ内での文字列の補間は避けた方がいいです。コードが SQL インジェクション攻撃に対して脆弱になります。

# bad - param will be interpolated unescaped
User.where("username = '#{params[:username]}'")

# good - param will be properly escaped
User.where('username = ?', params[:username])

名前付きプレースホルダー

クエリに複数のプレースホルダーがある場合は、位置プレースホルダーではなく名前付きプレースホルダーの使用を検討します。

# okish
Product.where(
  'price >= ? AND category_id = ?',
  params[:min_price], params[:category_id]
)

# good
Product.where(
  'price >= :min_price AND category_id = :category_id',
  min_price: params[:min_price], category_id: params[:category_id]
)

数の取得方法

Active Record コレクションを問い合わせる際には、countよりもsizeやlengthを使用することが推奨されます。countは常にデータベースにクエリを送って数を数えますが、sizeはコレクションが既にメモリ上にロードされているかどうかに基づいてcountとlengthの振る舞いを選択します。lengthは常に全コレクションをメモリにロードし、配列要素を数えます。

# bad
User.count

# good
User.all.size

# good - if you really need to load all users into memory
User.all.length

まとめ

一部分のみになりますが振り返り用でまとめました。

Discussion