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?

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)

Then all menu on site looks correct

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

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

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