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
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