Наследование ассоциации через другую модель в Rails 5 - PullRequest
0 голосов
/ 03 февраля 2019

У меня довольно стандартная настройка User / Role (роли пользователя HABTM, пользователи роли HABTM).Я использую CanCanCan для авторизации, и ваша роль определяет, что вы можете делать с приложением.Эта часть работает нормально, но теперь я хочу, чтобы пользователи могли наследовать роли как часть подписки на разные членства.

Вот соответствующие модели:

class User < ApplicationRecord
  has_and_belongs_to_many :roles
  has_one :membership_subscription
  has_one :membership, through: :membership_subscription
end

class Role < ApplicationRecord
  has_and_belongs_to_many :users
end

class MembershipSubscription < ApplicationRecord
  belongs_to :user
  belongs_to :membership
end

class Membership < ApplicationRecord
  has_many :membership_subscriptions
  has_many :users, through: :membership_subscriptions
end

Я думал, что смогу просто добавить ассоциацию has_many: roles в членство, а затем сказать, что пользователь has_manyролей посредством их подписки на членство, а также текущей ассоциации HABTM, которая позволяет назначать роли напрямую.

Таким образом, вы можете напрямую назначать роли пользователям, как вы можете сейчас (так как некоторые роли являются аддитивными, ивообще не относится к подписке / типу членства), но также пользователи автоматически наследуют роли (и теряют их снова), когда их подписчики приходят и уходят.

Имеет ли это смысл?Я полагаю, что другим вариантом было бы использовать обратные вызовы в модели, чтобы иметь дело с созданием / удалением ассоциаций ролей, но это не выглядит так элегантно.

Любой совет, высоко ценится!

1 Ответ

0 голосов
/ 03 февраля 2019

Хорошо, я думаю, что это правильный ответ:

Сначала обновите модели, чтобы между членами и ролями были ассоциации:

class Role < ApplicationRecord
  has_and_belongs_to_many :users
  has_and_belongs_to_many :memberships
end

class Membership < ApplicationRecord
  has_many :membership_subscriptions
  has_many :users, through: :membership_subscriptions
  has_and_belongs_to_many :roles
end

Затем создайтеметод в пользовательской модели, который можно использовать для извлечения как непосредственно назначенных ролей, так и унаследованных ролей:

def combined_roles
  if self.membership == nil
    self.roles
  else
    self.roles + self.membership.roles
  end
end

Затем, когда вам нужно проверить роль, вызывайте этот метод вместо обычного user.roles

Не уверен, что это наивный способ делать вещи, но, похоже, работает хорошо.Комментарии по-прежнему приветствуются, если есть лучший способ

РЕДАКТИРОВАТЬ:

Это позволяет пользователю иметь одну и ту же роль несколько раз - ее можно назначать напрямую или наследовать.Измените метод комбинированный_руль так, чтобы он удалял дубликаты:

def combined_roles
  if self.membership == nil
    self.roles
  else
    (self.roles + self.membership.roles).uniq
  end
end
...