##困った
既に動いているサービスに新しく機能を追加する際に、
1対1のリレーションシップを持たせたテーブルを追加する必要がありました。
例えば、usersテーブルにuser_settingsテーブルを1対1の関係で追加するってイメージです。
※usersにカラム追加すればいいじゃんってのは別の話で。
ここで困ったのが、新しく追加したテーブルへのデータ追加方法です。
考えられる方法として、
1.デプロイする際にバッチで一気にデータ投入する
2.新規追加したmodelを使う際にnullチェックをしてnullならば作成
の2パターンなんですが、
1だとデータ量が多くなっている場合にシビアになってくるので2で考えました。
しかし毎度modelを呼び出すところでnullチェックするのもめんどくさい。。
##こんな実装がしたい
#既存でデータが入っているモデルクラス
class User << ActiveRecord::Base
has_one :user_setting
end
#新しく追加し、リレーションを組むモデルクラス
class UserSetting << ActiveRecord::Base
belongs_to :user
def hoge_user?
return true
end
end
def test
user = User.find(params[:user_id])
if user.user_setting.hoge_user?
p "hogehoge"
end
end
ここで、user_settingsテーブルに指定のuser_idのデータが入ってないと、
user_controller.rbでhoge_user?呼んでるところでぬるぽります。
##そこでこんな実装をしてみた
#既存でデータが入っているモデルクラス
class User << ActiveRecord::Base
has_one :user_setting
# ここを追加
def user_setting
UserSetting.find_or_create_by(user_id: id)
end
end
#新しく追加し、リレーションを組むモデルクラス
class UserSetting << ActiveRecord::Base
belongs_to :user
def hoge_user?
return true
end
end
def test
user = User.find(params[:user_id])
if user.user_setting.hoge_user?
puts "hogehoge"
end
end
user.rbでuser_settingというメソッドを実装(オーバーライド)して、
そこでfind_or_create_byという読み出し時にnullの場合はcreateしてからデータを返してくれるメソッドを使い、nullでもきちんと欲しいデータが作成され取得できるようにしてみました。
ここでこだわったのがコントローラー等からはいつもどおりの読み出しかたでそれを実現したところです。
初期値とか色々いじりたかったら実装したメソッドいじればいいんじゃないですかね。
これでコントローラーやビューでデータ取得時に毎度nullチェックして作成とか意味のわからない実装しなくて済む!!
##とはいえ
Railsさんなのでもうちょっと設定とかでできるんじゃねーのと思って探してて見つけれなかったのでこんな実装してみました。
これ以外にも絶対方法あると思うので誰か教えてください