I have a Location
model that can have many sublocations, or one parent location.
Let's say location-A is a parent location, has location-B and location-C as sublocations. But location-B also has a sublocation location-D.
How can I get all sublocations of the parent location-A, including location-D?
My model:
has_many :sub_locations, class_name: "Location", foreign_key: "parent_location_id", inverse_of: :parent_location
belongs_to :parent_location, optional: true, class_name: "Location", foreign_key: "parent_location_id", inverse_of: :sub_locations
Currently I fetch them like this:
def all_sub_location_ids
[id] + sub_locations.map(&:all_sub_location_ids).flatten
end
But I need an efficient way. Because it throws stack level too deep
Edit: I ended up using .reload
on sublocations and keep the existing method as is. This way it worked.
You can use gem ancestry
.
Please have a look at the official doc here
Add Gem in your gemfile
gem 'ancestry'
Create migration
rails g migration add_Add_ancestry_to_location ancestry:string:index
In you Location
model add it as below:
class Location < ApplicationRecord
has_ancestry
end
now you can use is as below:
location_a = Location.create(name: 'Location A')
location_b = Location.create(name: 'Location B', parent: location_a)
location_c = Location.create(name: 'Location C', parent: location_a)
location_d = Location.create(name: 'Location D', parent: location_b)
parent_location = Location.find_by(name: 'Location A')
sublocations = parent_location.descendants
here sublocations will be an array with locations as Location B
, Location C
, Location D
.