1

I'm trying to group users in families. A family can have one parent and multiple members so a parent is considered a member as well.

I have tried answers provided here association and migration between users and teams (rails) and here rails many to many self join to try to make it work but no luck

Here is what I have

class User < ActiveRecord::Base
# this defines the parent to members fine and you can get them
# only if you have the parent
  has_many :memberships, :class_name => 'Family', :foreign_key => 'user_id'
  has_many :family_members, :through => :memberships, :source => :registrar
# trying to define that user is also a member of family 
 belongs_to :registrar_family, :foreign_key => 'member_user_id'
end

class Family < ActiveRecord::Base
  belongs_to :user, :class_name => 'User', :foreign_key => "user_id"
  has_many :users, :class_name => 'User', :foreign_key => "id"
end

So if I have user 1 who is a parent and has four members I can use

user.family_members # to get family members for this parent 

but how do I make so that I can also get the full family from a members

examples of DB

Users:
  id, name
 1, King
 2, Queen
 3, Prince
 4, Duaghter 
Users Family: 
 id,user_id, member_user_id
 1, 1, 2
 1, 1, 3 
 1, 1, 4

How do I say something like

user = User.find(4)
user.family.parent.members # which would return a family association 

The complete solution for this is (if anyone is interested):

class User < ActiveRecord::Base
  def family
    members = Family.where("user_id = ? OR member_user_id = ?", self.id, self.id)
    # if members is only 1 person then this person is a member only
    # then get all members from parent
    if members.count == 1
      members = members.first.parent.family
    end
    members
  end

  def family_count
    # if there is family then count is family + parent else 0
    family.count > 0 ? family.count + 1 : 0
  end

end

class Family < ActiveRecord::Base
  belongs_to :parent, :class_name => 'User', :foreign_key => "user_id"
end
Gamal Tawaf
  • 125
  • 1
  • 13

1 Answers1

2

Perhaps you have reasons you haven't mentioned why you need a Family class. But for a simple implementation you can do it all within the User model:

class User < ApplicationRecord
  def is_parent?
    parent_id.nil?
  end

  def family
    User.where(id: id_of_parent).or(User.where(parent_id: id_of_parent))
  end

  private
  def id_of_parent
    is_parent? ? id : parent_id
  end
end

if the users table contains

| id | first_name | parent_id |
| 1  | Fred       |  nil      |
| 2  | Wilma      |  1        |
| 3  | Pebbles    |  1        |
| 4  | Barney     |  1        |

Then:

> User.find(1).family.map(&:first_name) # -> [Fred,Wilma,Pebbles,Barney]
> User.find(2).family.map(&:first_name) # -> [Fred,Wilma,Pebbles,Barney]

You can add a self-join in the User model, if you like, but it doesn't add much:

Class User < ActiveRecord::Base
  belongs_to :parent, class_name: 'User', foreign_key: :parent_id

  etc...

I realize it's not exactly what you asked, but does it meet your needs?

Les Nightingill
  • 5,662
  • 1
  • 29
  • 32
  • The reason I need the family class is that user should be able to confirm and reject that they are part of that family and we need to store that state. I ended up using your approach but a little bit modified :) – Gamal Tawaf Oct 22 '19 at 12:56