ruby-on-railsrubyancestry

How best to propogate an `admin` status to children using Rails and Ancestry


I have User and Collection models, and am using the Ancestry gem to support nested sub-Collections.

Each collection has many admin_users and each user is the admin of many collections:

# user.rb
class User < ApplicationRecord
  has_many :admins
  has_many :collections, through: :admins
end

# collection.rb
class Collection < ApplicationRecord
  has_ancestry
  has_many :admins
  has_many :admin_users, through: :admins, source: :user
end

# admin.rb
class Admin < ApplicationRecord
  belongs_to :collection
  belongs_to :user
end

Each user that is an admin of a collection should automatically be an admin of all its descendants, without having to explicitly create an Admin record in the database for each. What's the "Rails way" to determine if a User is an admin of a collection or one of its ancestors?


Solution

  • I haven't used the ancestry gem before. But as far as I understand our requirements, you need to query the path_ids (see tree navigation) for the given collection. And then find all users that are an admin for at least one of those path items (collections from the current collection to the root collection).

    I would add an instance method path_admins to the Collection class like this:

    # in app/models/collection.rb
    def path_admins
      User
        .distinct
        .joins(:admins)
        .where(admins: { collection: path_ids })
    end