0

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
Dercni
  • 1,216
  • 3
  • 18
  • 38

1 Answers1

1

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
Rokibul Hasan
  • 4,078
  • 2
  • 19
  • 30
  • Amazing, thank you. Can the first solution be defined as a class method in my People model? I get an "undefined method `collect'" error. I'll update my example to show my code. – Dercni May 17 '17 at 08:00
  • I have edited my answer to fix your code, but this is not an good way, you can use scope, will add an example with scope. – Rokibul Hasan May 17 '17 at 08:31
  • Thank you Rokibul however it is not working for me. In my example I used "people" to make the example simpler however the real model name is "group". I have updated your example to "group" without success. I will update my example to show the real model name and this may help. – Dercni May 17 '17 at 09:20
  • You are making mistakes, I have update your question, you can not call collect on class, you can call map/collect on array of objects, so you have to pass that array of objects in your method. – Rokibul Hasan May 17 '17 at 09:28
  • Yes, thank you. I am now working on your scope solution which I see is superior. – Dercni May 17 '17 at 09:32
  • Can you please show me the output of Ancestor.includes(:group) ? – Rokibul Hasan May 17 '17 at 09:35
  • I have added the full results above: "ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "ancestors" does not exist" – Dercni May 17 '17 at 09:38
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/144443/discussion-between-rokibul-hasan-and-dercni). – Rokibul Hasan May 17 '17 at 09:41