Rails Rails 如何优雅地表达多层子属关系?

Chorder · 2021年03月09日 · 最后由 ampedxx 回复于 2021年03月18日 · 808 次阅读

例如:

某个组织 B,它有隶属组织 A,又有下属组织 C。

也许 A 和 C,又分别有其一对多、多对多的子 - 属对应关系。

再例如:

一条评论的评论,它有它的上一级评论,又 (也许) 有它的下一级评论。

就普通的 parent_id 储存树状关系。

2 楼 已删除
Rei 回复

那在前端如何能优雅地遍历展现呢?

存在多对多的话,可以再建一个“关系表”,比如“多级的用户”可以这样:
(用户表)
| id | name | | ---- | ---- | | 1 | 小明 | | 2 | 小红 | | 3 | 小华 |

加入它们三个互为上级,则可以(关系表): | user_id | super_id | | ---- | ---- | | 1 | 2 | | 1 | 3 | | 2 | 1 | | 2 | 3 | | 3 | 1 | | 3 | 2 |

5 楼 已删除

推荐Ancestry这个 Gem

Ancestry is a gem that allows the records of a Ruby on Rails ActiveRecord model to be organised as a tree structure

地址

https://github.com/stefankroes/ancestry

Chorder 回复
// 把带有pid的数组转化成tree结构数据(只用一次循环)
// 以顶级的pid为-1为例
// 本例假设只有一个跟结点(如果有多个根结点,建议把这些根节点跟在一个虚拟的根结点上)

function treefy(arr){
  var home={};
  var dad;
  arr.forEach(function(item){
    //把自己放家里
    if(home[item.id]){ // 如果发现有人顶替老子
      item.children=home[item.id].children; // 那得把儿子们领回来
    }else{
      item.children=[]; // 没有人顶替老子,也得给儿子们准备个地儿
    }

    home[item.id]=item; // 然后进家
    //把自己放到爸爸那里
    if(!home[item.pid]) //如果爸爸不在家
      home[item.pid]={ // 就造个爸爸
        children: []
      };
    home[item.pid].children.push(item); // 找到爸爸!
  });
  return home[-1];
}

var testData=[
  {
    id: 1,
    name: 'id1',
    pid: -1
  },{
    id: 2,
    name: 'id2',
    pid: 1
  },{
    id: 3,
    name: 'id3',
    pid: 2
  },{
    id: 4,
    name: 'id4',
    pid: 5
  },{
    id: 5,
    name: 'id5',
    pid: 1
  }
];

console.log(treefy(testData))

可以用 ancestry 树形结构这个 gem,后端 api 直接放好数据结构,前端直接取就行了

如果不想提高项目依赖复杂度,感觉 adcode 方式还是不错的(前提:层级是有限的)https://zh.wikipedia.org/wiki/%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD%E8%A1%8C%E6%94%BF%E5%8C%BA%E5%88%92%E4%BB%A3%E7%A0%81

closure_tree

需要 登录 后方可回复, 如果你还没有账号请 注册新账号