【问题标题】:Rails Tree Structure API [closed]Rails 树结构 API [关闭]
【发布时间】:2019-03-21 05:49:27
【问题描述】:

我有 JSON: JSON Link

现在我需要创建父子关系。 这样我就可以消费数据了:

HTTP GET /:tree_id
=> Return the saved structure
HTTP GET /:tree_id/parent/:id
=> Return the list of parents
HTTP GET /:tree_id/child/:id
=> Return the list of childs

我有情侣宝石,例如。 acts_as_tree & ancestry 但是以上所有的 gem 都让我可以使用 parent.children 来获取数据。

但是我需要使用上面的 API。您能否帮助我应该如何使用关联和模型结构来保存和获取基于上述 REST 请求的数据。

【问题讨论】:

  • “我需要创建父子关系”到底是什么意思?您要创建的输出是什么?
  • HTTP GET /:tree_id/parent/:id,如果有人点击了这个 url,它会返回父 ID 列表或 HTTP GET /:tree_id/child/:id => 返回列表孩子
  • 可以是查找子/父节点的搜索功能
  • 请不要链接到托管您的代码的外部网站。如果您有与您的问题相关的代码,那么您必须将其直接包含在您的问题中。
  • 我不能从这里访问 pastebin 所以我看不到你的例子。如果您认为省略唯一有意义且相关的代码以使我或其他任何人能够回答您的问题是“完全可以的”,那么我不确定您为什么要花时间问一个问题。 SO 为您提供了将其包含在帖子中所需的工具;为什么你会不遗余力地让人们更难帮助你?使用外部网站克服了人们无法看到您的代码并且无法回答您的问题的缺点,您可以获得什么好处?

标签: ruby-on-rails ruby ruby-on-rails-4 ruby-on-rails-5.1


【解决方案1】:

你创建一个模块怎么样:

module Ancestry

  def self.extended(receiver)
    receiver.class_eval do 

      define_method(:children_ids) do |children_ary=[]|
        receiver[:child].each_with_object(children_ary) do |child, children_ary|
          children_ary << child[:id]
          child.extend(Ancestry).children_ids(children_ary)
        end if receiver[:child].any?
      end

      define_method(:parent_ids) do |parents_ary=[]|
        if receiver[:child].any?
          parents_ary << receiver[:id]
          receiver[:child].each_with_object(parents_ary) do |child, parents_ary|
            child.extend(Ancestry).parent_ids(parents_ary)
          end
        end
      end

      define_method(:node) do |node_id|
        return receiver if receiver[:id] == node_id
        receiver[:child].each do |child|
          child.extend(Ancestry).node(node_id).tap do |x| 
            return x unless x.blank?
          end
        end if receiver[:child]
        {}.extend(Ancestry)
      end

      define_method(:child) do 
        receiver[:child] || []
      end

    end
  end

end

然后像这样扩展您的hash

data = {
  "id": 1,
  "child": [
    {
      "id": 1847,
      "child": [
        {
          "id": 8078,
          "child": []
        },
        {
          "id": 3380,
          "child": [
            {
              "id": 561,
              "child": []
            },
            {
              "id": 706,
              "child": []
            }
          ]
        }
      ]
    }
  ]
}.with_indifferent_access.extend(Ancestry)

现在你可以这样做了:

data.children_ids
 => [1847, 8078, 3380, 561, 706]
data.parent_ids
 => [1, 1847, 3380]
data.node(1847).node(3380).child
 => [{"id"=>561, "child"=>[]}, {"id"=>706, "child"=>[]}]
data.node(9999).node(3380).child
 => []
data.node(1847).node(9999).child
 => []
data.node(1847).node(3380).node(561).child
 => []

【讨论】:

  • 谢谢。但是你能告诉我是否有人点击 /:tree_id/child/:id,它是如何工作的
  • 我不知道/:tree_id/child/:id 中的:tree_id:id 是干什么用的。如果有人访问/4/child/3,他们会收到什么?
  • /1847/child/3380 => "child": [ { "id": 561, "child": [] }, { "id": 706, "child": [] } ]
  • 感谢您到现在为止的帮助,来自侧面的支持。
  • 噢噢噢噢。那是完全(或至少有些)不同的东西。这就是为什么我最初问你你在寻找什么输出。你真的应该更新你的问题,这样它就更清楚了。无论如何,我更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多