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

45 views
Skip to first unread message

Роман Ярыгин

unread,
Mar 20, 2015, 2:17:17 AM3/20/15
to rubyonra...@googlegroups.com, mus-m...@mail.ru

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?

Colin Law

unread,
Mar 20, 2015, 6:19:34 AM3/20/15
to rubyonra...@googlegroups.com
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

Роман Ярыгин

unread,
Mar 21, 2015, 12:58:34 AM3/21/15
to rubyonra...@googlegroups.com
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?


Роман Ярыгин

unread,
Mar 22, 2015, 8:12:19 PM3/22/15
to rubyonra...@googlegroups.com, mus-m...@mail.ru

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

Reply all
Reply to author
Forward
0 new messages