Rails, Mongoid-Ancestry: Exclude child nodes if parent node is not selected

Hello! Please help with trouble (I think it must be obvious solution)

I have code for displaying main menu:

@main_menu = Page.where(active: true).arrange(order: :position)

It grabs all nodes with active parameter is set to true. But if the
parent
node for some children is set to active:false, they connects to
grandparent
node, and so on. How to avoid this behavior, so if parent node is
excluded
then all children nodes become excluded too?

On 20 March 2015 at 06:17, Роман Ярыгин [email protected] wrote:

Hello! Please help with trouble (I think it must be obvious solution)

I have code for displaying main menu:

@main_menu = Page.where(active: true).arrange(order: :position)

It grabs all nodes with active parameter is set to true. But if the parent
node for some children is set to active:false, they connects to grandparent
node, and so on. How to avoid this behavior, so if parent node is excluded
then all children nodes become excluded too?

I think you will need to explain the associations between the models
for us to understand the question. Then explain exactly what is not
happening as you want.

Colin

This is the model:

class Page
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::Ancestry
include Mongoid::Orderable
has_ancestry orphan_strategy: :destroy
orderable column: :position, base: 0

has_many :page_attachment_files

field :name, type: String
field :content, type: String
field :elements_order, type: String, default:
“nav,anounces,news,page_content,albums,paf”
field :show_in_main_menu, type: Boolean, default: true
field :active, type: Boolean, default: true
field :redirect, type: String

validates :name, presence: true
end

When all nodes has attribute active set to :true (like on picture)

https://lh4.googleusercontent.com/-KGGpqXlXqLM/VQz5HaW6bFI/AAAAAAAAAIw/Ccrj1zkcllw/s1600/Снимок%2Bэкрана%2Bот%2B2015-03-21%2B14%3A50%3A20.png

Then all menu on site looks correct

https://lh6.googleusercontent.com/-1d4MyO9yN_c/VQz5Y2j-ZYI/AAAAAAAAAI4/5ns5nqTAJzU/s1600/Снимок%2Bэкрана%2Bот%2B2015-03-21%2B14%3A53%3A41.png

But if set one of parent nodes “active” to false (like that)

https://lh5.googleusercontent.com/-lazObznq07E/VQz5vJL4PnI/AAAAAAAAAJA/FFZItcNlVmo/s1600/Снимок%2Bэкрана%2Bот%2B2015-03-21%2B14%3A55%3A11.png

Then menu breaks: all child nodes are attached to grandparent node (Like
this):

https://lh3.googleusercontent.com/-TOR7XUGCdes/VQz6NcdJYII/AAAAAAAAAJI/I96bq7QF2Po/s1600/Снимок%2Bэкрана%2Bот%2B2015-03-21%2B14%3A57%3A14.png

And I need to exclude all this child nodes if parent node is disabled.
How
to do that?

Okay. Here is the solution

In ApplicationController:

before_filter do
@main_menu = Page.where(active: true, show_in_main_menu:
true).arrange(order: :position)

def menu_ids(attributes, mids = [])
  attributes.map do |attribute, sub_attributes|
    if sub_attributes.empty?
      mids << attribute.id.to_s
    else
      mids << attribute.id.to_s
      menu_ids(sub_attributes, mids)
    end
  end
  mids
end
@menu_ids = menu_ids(@main_menu)

end

In ApplicationHelper:

def main_menu(attributes)
attributes.map do |attribute, sub_attributes|
if sub_attributes.empty?
if @menu_ids.include?(attribute.parent_id.to_s)
content_tag(:li) do
link_to attribute.name.html_safe, page_path(attribute._id)
end
end
else
if attribute.parent_id == nil
content_tag(:li, nil, class: “dropdown”) do
begin
link_to( attribute.name.html_safe,
page_path(attribute._id))+
(icon(‘angle-double-right’) if !attribute.is_root?)+
content_tag(:ul, nil) do
main_menu(sub_attributes)
end
end.html_safe
end
else
if @menu_ids.include?(attribute.parent_id.to_s)
content_tag(:li, nil, class: “dropdown”) do
begin
link_to( attribute.name.html_safe,
page_path(attribute._id))+
(icon(‘angle-double-right’) if !attribute.is_root?)+
content_tag(:ul, nil) do
main_menu(sub_attributes)
end
end.html_safe
end
end
end
end
end.join.html_safe
end

And it finally works like I wanted