2

I'm having a really tricky time modeling this data problem.

My application is basically a messaging app between two types of user object—users and admins. The data for each is the same, but their relationship to messages is slightly different.

A regular user has a single group that all messages are received at. An Admin, however, can send messages to multiple regular users in different groups.

So:
- users have one group, and have many messages through that group
- admins have many groups, and have many users through groups

it is necessary that that the two types of user exist in the same table because the api spec requires that groups are pulled by user id regardless of the type of user.

I keep going around in circles between polymorphism, STI, and self joins, and just cannot for the life of me figure out the right approach.

Any advice is greatly appreciated!

EDIT:

So this is a semi functioning solution. With this, I can get admins from regular user and vice versa, groups, as well as all messages, but only from a reg_user.

From a data perspective, this is still wrong. A regular user will have multiple groups, but the relationships allow you to pull all messages that belong to a user regardless of group. So can be controlled/restricted from the ui/controller.

The spec I have also dictates that a regular user can only have one thread, which this does not adhere to.

UserModel

class User < ApplicationRecord
  has_many :groups
  has_many :admins, through: :reg_user, source: :user

  has_many :messages, through: :groups

  has_many :admins, through: :groups
  has_many :reg_user, foreign_key: :admin_id, class_name: 'Group'
end
colintherobot
  • 157
  • 2
  • 11
  • I fell it is more a `self joins` with `has_many :through` – Pavan Jul 19 '17 at 12:50
  • Would it be too problematic to assume all users *could* be in multiple groups, even if non-admins can only currently be in one group? – Tom Lord Jul 19 '17 at 12:51
  • @TomLord Yeah, I mean that is a possibility. Since that really just means a simple has many/belongs to and a restriction by role. However, I would like to somehow validate and actually say a regular user can only have one and an admin can have many. – colintherobot Jul 19 '17 at 12:53
  • @Pavan, my current implementation I'm testing is exactly that. Would the through join be on the group? I currently was building it through a `followings` object (join table) which in hindsight I'm second guessing. – colintherobot Jul 19 '17 at 12:56
  • @cohart *"I would like to somehow validate ... a regular user can only have one"* -- That shouldn't be too hard, although admittedly it's not ideal to be adding such a validation. But at least this provides easier future flexibility if the requirements change. – Tom Lord Jul 19 '17 at 13:06
  • is the only difference between an `Admin` and a `User` the number of groups that they are associated with? – Michael Gorman Jul 19 '17 at 14:27
  • @MichaelGorman Yeah, that's the only difference. – colintherobot Jul 20 '17 at 15:17
  • then you could do a flag that declares a user an admin `is_admin`, then a validation that says `groups.count >1 && !is_admin` is invalid – Michael Gorman Jul 20 '17 at 15:32

0 Answers0