【Rails】Rails開発者が知っておくべきスタイルガイドまとめ
はじめに
Railsのスタイルガイドを参考に、振り返り用に、まとめ記事を記載していこうと思います。
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!など)を使用するか、メソッドの戻り値をチェックして適切に処理するべきです。create
、save
、update
、destroy
、first_or_create
、find_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