Dercni
Dercni

Reputation: 1224

Awesome nestset set ancestor class method

Awesome nested set includes an ancestors instance method: https://github.com/collectiveidea/awesome_nested_set/wiki/Awesome-nested-set-cheat-sheet

@john = Group.where(name: "John").first
@tree = @john.ancestors

I am looking for a class method that would return an array or AR relation of ancestors for every group called "John"

@johns = Group.where(name: "John")
@tree  = @johns.ancestors

Presently I am doing this by looping through an AR relation and running the instance method for each row.

Update1

class Group < ApplicationRecord
  acts_as_nested_set    :counter_cache => :children_count

  def self.build_tree(groups)
    groups.collect(&:ancestors).flatten!
  end
end

class GroupsController < ApplicationController
    def index
        @johns = Group.where(name: "John")
        @tree  = Group.build_tree(@johns)
    end
end

Error:

undefined method `collect' for #<Class:0x00000002a28378>

Update2

There appears to be a problem with the Ancestor => Group relationship.

class Group < ApplicationRecord
  acts_as_nested_set    :counter_cache => :children_count
  has_many :ancestors

  def self.build_tree(objects)
     objects.collect(&:ancestors).flatten!
  end
End

class Ancestor < ActiveRecord::Base
  belongs_to :group
  scope :with_group, -> (name) { joins(:group).where("groups.name = ?", name) }
end


2.4.0 :008 > Ancestor.joins(:group)
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  relation "ancestors" does not exist
LINE 1: SELECT  "ancestors".* FROM "ancestors" INNER JOIN "groups" O...
                                   ^
: SELECT  "ancestors".* FROM "ancestors" INNER JOIN "groups" ON "groups"."id" = "ancestors"."group_id" LIMIT $1


2.4.0 :009 > Ancestor.includes(:group)
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  relation "ancestors" does not exist
LINE 1: SELECT  "ancestors".* FROM "ancestors" LIMIT $1
                                   ^
: SELECT  "ancestors".* FROM "ancestors" LIMIT $1

Upvotes: 0

Views: 408

Answers (1)

Rokibul Hasan
Rokibul Hasan

Reputation: 4156

You are almost there, try following

@johns = People.where(name: "John")
@tree  = @johns.collect(&:ancestors).flatten!

or you can use join query

Ancestor.joins(:people).where("peoples.name = ?", 'John')

According your code base you can just pass the records, but this is not a good way.

class People < ActiveRecord::Base
   acts_as_nested_set    :counter_cache => :children_count

   def self.build_tree(peoples)
     peoples.collect(&:ancestors).flatten!
   end
end


class PeopleController < ApplicationController
   def index
      @johns = People.where(name: "John")
      @tree  = People.build_tree(@johns)
  end
end

Example with scope, good one

 class People < ActiveRecord::Base
    has_many :ancestors
    #your codes goes here  
 end


 class Ancestor < ActiveRecord::Base
     belongs_to :people
     scope :with_people, -> (name) { joins(:people).where("peoples.name = ?", name) }
 end


class PeopleController < ApplicationController
   def index
      @tree = Ancestor.with_people("John")
   end
 end

Upvotes: 1

Related Questions