Mam trzy modele:
Category:
attr_accesible :name, :active ...
has_many :product_categories
has_many :products, :through => :product_categories
has_ancestry
Product:
attr_accesible :name, :description, :active ...
has_many :product_categories
has_many :categories, :through => :product_categories
Product_category:
attr_accesible :product_id, :category_id
belongs_to :product
belongs_to :category
Model Category ma strukturę drzewka, do tego celu użyłem gemu ancestry.
W Products#index pobieram produkty z danej kategorii oraz wszystkich podkategorii do niej należących.
[code]@category = Category.find(params[:id])
category_ids =
if @category.has_children?
@category.subtree_ids
else
@category.id
end
@products = Product
.joins(:product_categories)
.where(
:product_categories => {:category_id => category_ids},
:active => true
)
.page(params[:page]).per(6)[/code]
Problem pojawia się jeżeli chcę pobrać produkty jedynie z aktywnych kategorii/podkategorii. Przykładowe drzewo:
[code]id | name | active
1 | Category X | 1
2 | Foo | 0
3 | Foobar | 1
4 | Bar | 1[/code]
Użytkownik przegląda Category X. Powinny wyświetlić się produkty z bieżącej kategorii oraz wszystkich podkategorii z pominięciem gałęzi Foo. Czyli category_ids powinien zawierać: [1, 4]. Jak to najlepiej zrealizować? Pobrać całe subtree i w ruby wyeliminować nieaktywne gałęzi?
EDIT:
Wykombinowałem coś takiego:
def active_subtree_ids
category_ids = []
inactive_ids = []
self.subtree.select('id, active, ancestry').order(:ancestry).each do |c|
if inactive_ids.include? c.id
next
end
unless c.active
inactive_ids += c.subtree_ids
next
end
category_ids << c.id
end
category_ids
end
EDIT2:
Wypadałoby jeszcze sprawdzać czy dana ścieżka jest aktywna…
def is_active_path?
self.path.select('active').each do |c|
unless c.active
return false
end
end
true
end
Wygląda, że działa tak jak tego chciałem. Nie wiem czy jest to optymalne rozwiązanie. Będę wdzięczny za wszelkie sugestie
EDIT3:
hmm… wygodniej będzie chyba po prostu dezaktywować wszystkie podkategorie…