Madogiwa Blog

主に技術系の学習メモに使っていきます。

RubyonRails:has_oneで1:1のAssociationを定義し、モデルを適切に分割するメモ

こんばんは、まどぎわです(・∀・)

RailsアプリケーションでUserモデルにプロパティがモリモリマッチョになっていませんか?? 例えばこんな感じ。

Userモデル

  • id
  • email
  • password
  • name
  • birthday
  • sex
  • job etc...

こうなってくるとプロパティだけでなくて、Userモデルにメソッドもモリモリマッチョにになっちゃう可能性がありますよね・・・!
そういうときは、has_oneを使ってモデルを分割してあげるとスッキリします(・∀・)

has_oneとは?

まずhas_oneとは一体なんなのか?ということですが、Railsリファレンスを見てみると下記と記載されています。

指定のクラスがこのクラスの子であることを宣言

has_one - リファレンス - - Railsドキュメント

これだと正直わからないのですが、Railsガイドに良い感じの説明が記載されていました。

has_one関連付けも、他方のモデルとの間に1対1の関連付けを設定します。しかし、その意味と結果はbelongs_toとは若干異なります。has_one関連付けの場合は、その宣言が行われているモデルのインスタンスが、他方のモデルのインスタンスを「まるごと含んでいる」または「所有している」ことを示します。

railsguides.jp

上記説明の通り、has_oneを使えば1:1のアソシエーションを定義することが出来ます!φ(..)

Userモデルを分割する

has_oneについて、概要が理解出来たところで実際にUserモデルを分割してみます。
今回は一番最初に書いた下記のようなプロパティが定義されているUserモデルを例にして分割方法を考えてみようと思います。

  • id
  • email
  • password
  • name
  • birthday
  • sex
  • job

上記プロパティを分類するとログイン関連の情報を表すアカウント系とユーザーの情報を表すプロフィール系の項目に分けられるんじゃないないかと思いますので、下記のように分けてみようと思います!(・∀・)

プロパティ 分割後モデル
id User
email User
password User
name Profile
birthday Profile
sex Profile
job Profile

Profileモデルを定義する

まずはUserのプロフィール関連の項目を設定するProfileモデルを定義するために下記コマンドを実行します。

rails g model Profile name:string birthday:date sex:interger user:references

準備はこれでOK!(・∀・)

associationを定義する

それでは、実際にhas_oneを使ってassociationを定義していきます。
実装はかなりシンプルでUserProfileに1行追加するだけです!(・∀・)

profile.rb

  belongs_to :user

user.rb

  has_one :profile, dependent: :destroy

belongs_toをUserとProfileどちらに記載するか迷うところですが、これはどちらがメインのモデルかを考えて、メインのモデルにhas_oneを記載します。
例えば、UserはProfileを持つこれが成り立つならUserモデルがメインと言えます。※ProfileはUserを持つとは言えないですよね?

おわりに

いかがだったでしょうか?has_oneを使うとモデルが分割できて、モデルの実装がスッキリしますね!(・∀・)
またモデルを分割出来るとcontrollerも分割出来る可能性も大きいので、fat controllerをより防ぎやすくなると思います。
適切にモデルを分割して、可読性の高いコード、わかりやすいテーブル設計が出来るように気をつけて行きたいですねφ(..)