2022/10/13(木) Railsのルーティング&アソシエーション

Railsにおけるバリデーションの設定方法

バリデーションとは、正しいデータのみがデータベースに保存されるようにモデルクラスにて、そのデータが正しいかどうかをチェックするシステムのことを言います。バリデーションに引っかかり、データが不正だと判断された場合は、データベースに保存されません。

バリデーションは、正しいデータだけをデータベースに保存するために行われます。正しいデータだけをデータベースに保存するのであれば、モデルレベルでバリデーションを実行するのが最適です。モデルレベルでのバリデーションは、データベースに依存せず、エンドユーザーがバイパスすることもできず、テストもメンテナンスもやりやすいためです。Railsではバリデーションを簡単に利用できるよう、一般に利用可能なビルトインヘルパーが用意されており、独自のバリデーションメソッドも作成できるようになっています。

Railsガイド

バリデーションの設定方法

validates :カラム名, presence: true
validates :カラム名, length: { maximum: 30 }
validates :カラム名, numericality: { greater_than: 0 }
  • presence: trueは、カラムのデータは、必ず存在する(空のデータでは、保存できないように制限)ように設定したバリデーションです。
  • length: { maximum: 30 }は、カラムの文字数を最大30文字に制限するバリデーションです。(30文字以上のデータは、DBに保存されない)
  • numericality: { greater_than: 0 }は、0以上の数値のみの入力を許可するバリデーションです。
numericalityのオプション 概要
only_integer integerのみ
equal_to 指定された値と等しいか
greater_than_or_equal_to 指定された値以上
less_than_or_equal_to 指定された値以下
greater_than 指定された値よりも大きいか
less_than 指定された値よりも小さいか
odd trueに設定した場合、奇数か
even trueに設定した場合、偶数か

has_many :through関連付け

has_many :through関連付けは、他方のモデルと「多対多」のつながりを設定する場合によく使われます。 この関連付けでは、2つのモデルの間に「第3のモデル」(joinモデル)が介在し、それによって相手のモデルの「0個以上」のインスタンスとマッチします。

Railsガイド

class Restaurant < ApplicationRecord
  has_many :line_foods, through: :foods
end
  • 1つのRestaurantは中間テーブルFoodsを経由して複数のLine_foodを持っています。
  • has_many :throughを使うと、1つのレストランにつき仮注文は、複数作成できますが、その仮注文は、foodテーブルを参照していますよという意味になります。

belongs_toのoptionalオプション

optional: trueとは、アソシエーションによって紐づけられた外部キーの値が存在しない値やnilの場合でも、データベースに保存することができるオプションです。

【Rails】外部キーのバリデーションチェックを回避するoptional: trueについて簡単にまとめてみた

class LineFood < ApplicationRecord
  belongs_to :order, optional: true
end
  • 上記の例で言うと、仮注文テーブルの外部キーにorder_idがセットされていない場合でもバリデーションチェックが行われることなくDBに保存できるようになります。
  • optional: trueを設定すると、belongs_toの外部キーnil(存在しないこと)を許可します。

インスタンスメソッドとは?

インスタンスメソッドとは、クラスから作成されたオブジェクトに対して、呼び出せるメソッドのことです。 インスタンスメソッドをコントローラーではなく、モデルに記述すると、様々な箇所からオブジェクトに対して呼び出すことができます。

  • 特定のデータ(インスタンス)に対する操作は、インスタンスメソッドが使われます。
  • 対して、クラスメソッドは、クラス全体に対する共通の操作を行いたい時に使われます。
  • クラスメソッドの定義は、self.メソッド名のようにメソッド名の前にselfをつける必要があります。

ルーティングの名前空間について

namespace: 名前空間名名前空間をつけられます。名前空間をつけることのメリットは、コントローラーを名前空間名のディレクトリで、クループ化するとともに、URLにも名前空間の情報をつけることが出来ることです。 つまり、名前空間というディレクトリを作成することにより、分かりやすくグループ化したルーティングを作成できるようになります。

namespace :a do
  namespace :b do
    ...
  end
end
  • コントローラーをapp/controllers/a/b/というディレクトに分類し、それをURLにも適用するためにnamespaceが使われています。namespaceであるabが入ったURLでルーティングを作成できます。

ルーティングを作成するresourcesメソッドとresourceメソッド

どちらもルーティングを簡単に作成するためのメソッドです。基本的なアクション(index、show、new、create、edit、update、destroy)に対応するURLの組み合わせ(ルーティング)を作成します。

resorcesメソッド

「resourcesメソッド」は、7つのアクション(index、show、new、create、edit、update、destroy)のidを付与したルーティングを一括生成してくれるメソッドです。

【Rails】resourcesメソッドとresourceメソッドの違いについて簡単に解説!

resourceメソッド

「resourceメソッド」は6つのアクション(show、new、create、edit、update、destroy)のルーティングがidなしで生成されます。加えて、「resourceメソッド」はindexアクションのルーティングが生成されません。

【Rails】resourcesメソッドとresourceメソッドの違いについて簡単に解説!

resourcesとresourceの使い分け

resources :restaurants do
  resources :foods, only: %i[index]
end
  • resourcesは、リソースが複数ある場合に使用します。ルーティングに付与されるidを使って、複数あるリソースを識別します。
  • 上記の例で、レストランは、あちらこちらにたくさん存在するので、resourcesを使用しています。
resources :users do
  resource :profile
end
  • resourceは、リソースが1つしかない時に使用します。リソースが複数ではないため、リソースの一覧ページを表示する必要性がありません。よって、resourceでは、indexアクションに対するルーティングが作成されないのです。
  • 上記の例では、特定のユーザーに対するプロフィール情報は、1つなのでresourceを使用しています。

saveとsave!メソッド

  • saveメソッドは、生成したモデルオブジェクトをデータベースに保存します。データベースに保存できなかった場合は、falseを返します。
  • 一方save!メソッドは、同じく生成したモデルオブジェクトをデータベースに保存しますが、保存に失敗した場合は、例外を発生させます。
  • 例外を発生すると、例外が起きた場所で処理を停止します。

参考

Railsガイド-バリデーション

Railsガイド-has many throughについて

【Rails】外部キーのバリデーションチェックを回避するoptional: trueについて簡単にまとめてみた

【Rails】resourcesメソッドとresourceメソッドの違いについて簡単に解説!