中間テーブルに権限属性を持たせて、権限をコントロールするということがよくあります。以下のコードはシンプルな構成例です。
class User < ApplicationRecord has_many :memberships, dependent: :destroy has_many :accounts, through: :memberships end class Account < ApplicationRecord has_many :memberships, dependent: :destroy has_many :users, through: :memberships end # user_id :integer # account_id :integer # admin :boolean class Membership < ApplicationRecord belongs_to :user belongs_to :account end
そんな時、今ままでは以下のようにチェックしていました。
class User < ApplicationRecord def admin?(account) memberships.find_by(account_id: account.id).admin end end user = User.first account = user.accounts.first user.admin?(account)
これだとわざわざ権限をチェックするために、毎回中間テーブルを参照する必要があります。これでは権限チェックのたびにクエリが走って効率が悪いことこの上ありません。
そこで関連テーブルの取得と同時に中間テーブルの権限属性を引っ張ってくることはできないかと考えました。
考えた結果、何ということはない、単純にselect文の中に中間テーブルの属性を設定してあげれば関連先のテーブルで当該属性を取得できました。
accounts = current_user.accounts.select("accounts.*, memberships.admin AS admin") accounts.first.admin => 1
注意する点は中間テーブルから引っ張ってきたbooleanの属性はtrueまたはfalseではなく、1または0となることです。単純にaccount.admin?とするだけであれば、問題なくtrue, falseの判定ができますが中身のデータを使って何かをするようなときには気をつけなくてはいけません。