ruby-on-railsruby-on-rails-4model-view-controllerawesome-nested-set

Rails: Enumerate data in the view with different context


I use awesome_nested_set gem for the binary tree in my app.

I need to display the binary tree on the page. Each node in the tree have a button, which shows two next childs.

Mockup with tree

My current code is not DRY, large and difficult to maintain. I get all descendants for the current user:

- users = current_user.descendants.unscope(:order).order(:depth, :lft)

Each level and "collaspsing zones" must have own classes.

#lvl-0
  .person-container
    .person-avatar
      = image_tag current_user.avatar_file_name, class: "img-circle avatar"
    .person-name
      %b
        = current_user.name
        = current_user.surname
  #lvl-1-left.lvl-child
    .person-container
      %span.badge(data-toggle="collapse" data-target="#lvl-2-left-from-left, #lvl-2-right-from-left")
        %span.caret
      .personal-avatar
        = image_tag users[0].avatar_file_name, class: "img-circle avatar"
      .personal-name
        %b
          = users[0].name  -# first child
          = users[0].surname
    #lvl-2-left-from-left.collapse.lvl-child
      .person-container
        %span.badge(data-toggle="collapse" data-target="THIS USER'S NEXT TWO CHILDREN")
          %span.caret
        .personal-avatar
          = image_tag users[2].avatar_file_name, class: "img-circle avatar"
        .personal-name
          %b
            = users[2].name
            = users[2].surname

    #lvl-2-right-from-left.collapse.lvl-child
      .person-container
        %span.badge(data-toggle="collapse" data-target="THIS USER'S NEXT TWO CHILDREN")
          %span.caret
        .personal-avatar
          = image_tag users[3].avatar_file_name, class: "img-circle avatar"
        .personal-name
          %b
            = users[3].name
            = users[3].surname

And so on...

I want something like this

- current_user.self_and_descendants.unscope(:order).order(:depth, :lft).each do |user|
  - case user.depth
  - when 0
    -# inject id and data-target, render _person.html.haml
  - when 1
    -# inject id and data-target, render _person.html.haml
  -# etc

Solution

  • what you need is a recursive partial

    create a partial _nested_fields.html.haml and add

    - users.each do |user|
      .person-container
        - if this user is not root
          %span.badge(data-toggle="collapse")
          %span.caret
        .personal-avatar
          = image_tag user.avatar_file_name, class: "img-circle avatar"
        .personal-name
          %b
            = user.name
            = user.surname
    
        - if this user has children
          = render "path_to_this/nested_fields", users: user.children
    

    in your view

    = render "nested_fields", users: [current_user]
    

    to add the indentation you can add some css

    .person-container {
      margin-left: 20px;
    }