##背景
仕訳記録用の会計ソフトを開発しています。ユーザのサインアップ、検証、ログイン、ログアウト機能は既にできています。
ただし、例えばユーザAが登録した仕訳が、新しくサインアップしてログインしたユーザBに漏れなく見られてしまいます。つまり、全てのデータは全員共有という状態です。
望ましいのは、ユーザAが登録した仕訳がユーザAのみに見られ、ユーザBがサインアップしてログインすると、またきれいな環境になり、ユーザBがユーザBのみ見られる仕訳を登録できるようになるということです。
ただし、一部の汎用勘定科目はAもBも見れます。
また、アプリのURLは変わらないです。AもBも同じURLで同じシステムをログインします。
##いろいろ調べた結果
希望な機能は「マルチテナンシー」(Multitenancy)と呼ばれます。
幸いなのは、Railsの中に既にいくつかのGemがありました。苦労せず実現できそうな感じです。
一番流行っているらしいのが「Apartment」というGemです。違うテナントは違うsubdomainを通じてデータの隔離することを実現します。
Apartment+PostgreSQLの場合、微妙な問題がありそうです。未だに完璧に解決できていないようです。
二番目有名なGemは「acts_as_tenant」というGemです。今回使ってみたのはこれです。
##いよいよ始めよう
インストールはとっても簡単
-
gem 'acts_as_tenant'
をGemfileに入れます -
Bundle Install
を実行します。 -
完了です。
データを隔離したいテーブルにテナントを代表するIDの列を追加
rails g migration addAccountToTables
でMigration Fileを生成させ、下記のように書きます。
説明:
① dealsは仕訳を保存するテーブル、bank_accounts は銀行口座を保存するテーブルです。そしてユーザごとにデータを隔離したいテーブルです。両方とも既にあったテーブルです。
② usersは既にあったユーザを保存するテーブルです。今回はuserごとにデータを隔離したいので、ここでは:user_idを入れてOKです。もし一つのAccount(Tenant)に複数のuserが含まれ、同じTenantのuserたちはデータを共有するという形がほしかったら、別途Accountテーブルを作る必要があります。
③ 勘定科目を共有したいため、勘定科目テーブルgl_accountsはそのまま変わらないです。
p.s.Migration Fileの名前は「AddAccountToTables」じゃなくても何でもいいです。
Modelにacts_as_tenant(:user)
を追加
隔離したいModelだけが必要です。勘定科目のmodel-GlAccountはそのまま何も変わらないです。
テナントを判別するコードをcontrollerに入れる
説明:
① ここのset_current_tanant_through_filter
はgemが提供してくれる関数です。名前は変えられないです。
② find_current_tenant
は自分で作ったprivate関数です。好きな名前にしてもOKです。
③ set_current_tenant
はgemが提供してくれる関数です。名前は変えられないです。
④ パラメータのcurrent_user
は自分がその前に書いた関数です。目的はログインしているユーザをゲットすることです。
以上だけ設定すると、ユーザAもBも自分しか見れない/作れないデータをできるようになりました。
非常にシンプルで分かりやすいGemだと思います。