按父ID分组记录

时间:2016-11-10 15:05:28

标签: ruby-on-rails ruby

我的Rails应用程序中有以下记录:

id: 1
name: 'About'
slug: 'about'
permalink: '/about'
parent_id: null

id: 2
name: 'Team'
slug: 'team'
permalink: '/about/team'
parent_id: 1

id: 3
name: 'Cameron'
slug: 'cameron'
permalink: '/about/team/cameron'
parent_id: 2

我将它们显示在这样的列表中:

<ul>
<% @pages.each do |page| %>
  <li>
    <%= page.parent.title rescue '' %><br>
    <%= page.permalink %>
  </li>
<% end %>
</ul>

这会创建一个列表:

<ul>
    <li>About<br>/about</li>
    <li>Team<br>/about/team</li>
    <li>Cameron<br>/about/team/cameron</li>
</ul>

但是我想创建一个如下所示的嵌套列表,它使用parent_id对它们进行分组。

<ul>
    <li>About<br>/about</li>
    <li>-- Team<br>/about/team</li>
    <li>---- Cameron<br>/about/team/cameron</li>
</ul>

是否有一种快速简便的方法可以将它们分组到控制器中?

我想出的最好的想法是在控制器中执行此操作:

@pages = Page.where(parent_id: nil)

然后在视图中:

<% @pages.each do |page| %>
    <%= render 'page_row', :page => page, :sub => 0 %>
    <% page.pages.each do |page| %>
        <%= render 'page_row', :page => page, :sub => 1 %>
        <% page.pages.each do |page| %>
            <%= render 'page_row', :page => page, :sub => 2 %>
            <% page.pages.each do |page| %>
                <%= render 'page_row', :page => page, :sub => 3 %>
            <% end %>
        <% end %>
    <% end %>
<% end %>

使用partial来创建嵌套:

<%
  $i = 0
  $num = sub
  prefix = ''
  while $i < $num do
    prefix += '---'
    $i +=1
  end
%>
<li>
<%= prefix %> <%= page.parent.title rescue '' %><br>
        <%= page.permalink %>
</li>

但是通过像我一直在做的那样手动循环,它将嵌套限制为只有4级深度并且代码不是很好。

如何才能实现相同的结果,但没有手动循环来创建页面的嵌套视图?

3 个答案:

答案 0 :(得分:3)

我要做的是在模型中为同一个模型创建一个引用,也就是说:

has_many :pages, foreign_key: 'parent_id'

然后得到所有顶级父母:

@parents = Page.where(parent_id: nil)

然后在视图中加载每个父项的所有子项:

@parents.each { |p| p.pages.each { |c| ... } }

这种结构也在this SO thread中解释。

答案 1 :(得分:2)

我认为你是在正确的轨道上,但不是循环固定的次数,整个视图应该是递归的。

在控制器中:@top_level_pages = Page.where(parent_id: nil)

在视图中

<%= render 'pages', pages: @top_level_pages, level: 0 %>

在页面部分

<% pages.each do |page| %>
  <li>
    <%= '-' * level %><%= page.name %><br>
    <%= page.permalink %>
  </li>
  <%= render 'pages', pages: pages.pages, level: level + 1 %>
<% end %>

答案 2 :(得分:0)

在我看来,您应该创建一个新类,负责构建一个树结构(JSON或哈希),以减少视图层所需逻辑的方式封装数据。

new Thread(new Runnable() {

        @Override
        public void run() {

            boolean downloading = true;

            while (downloading) {

                DownloadManager.Query q = new DownloadManager.Query();
                q.setFilterById(downloadId);

                Cursor cursor = downloadManager.query(q);
                cursor.moveToFirst();
                int bytes_downloaded = cursor.getInt(cursor
                        .getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));

                if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
                    downloading = false;
                }

                final int dl_progress = (int) ((bytes_downloaded * 100l) / bytes_total);

                ((Activity) mContext).runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        holder.mTextView.setText(String.valueOf(dl_progress) + "%");
                    }
                });
                cursor.close();
            }
        }
    }).start();

在视图中,我将使用partial来定义每个级别的表示 - 生成下一个较低级别,再次调用partial并传入:children。让部分处理迭代遍历该级别的元素,以及其中:children存在,再次将它们传递给partial。