Ruby是否可以在没有递归的情况下将act_as_nested_set干净地转换为JSON哈希?

时间:2020-03-05 18:46:53  来源:igfitidea点击:

是否有一种快速干净的方法,可以从Ruby on Rails的act_as_nested_set中的任何节点返回JSON哈希,而无需使用递归?

这是递归解决方案,以供参考:

class Node < ActiveRecord::Base
  has_many :products
  def json_hash
    if children.size > 0
      children.collect { |node| { node.name => node.json_hash }.to_json
    else
      { node.name => node.products.find(:all).collect(&:name) }.to_json
    end
  end
end

解决方案

回答

有一篇关于树遍历的维基百科文章,显示了我们正在使用的递归解决方案的不同替代方案。在特定情况下使用它们可能很棘手,但是应该可以的。

但是,我想问的是,我们是否有使用迭代而不是递归的特定原因?我认为任何迭代解决方案都不会如此干净。树是否太大,以至于堆栈空间不足(它们必须很大)?否则,我不确定迭代解决方案是否真的会更快。

不过,如果我们遇到性能问题,我会看到一种改进的潜力...但是我不知道它是否适用,因此我不确定它是否准确:

find方法是否返回新数组?如果是这样,我们可能要调用.collect!而不是.collect,因为如果find创建了一个数组,那么我们只是在创建一个数组,然后将其扔给进行收集的调用(这也会创建一个数组),这肯定不会非常有效,并且可能会减慢速度如果那里有一棵大树,很多。

所以

{ node.name => node.products.find(:all).collect(&:name) }.to_json

可能成为

{ node.name => node.products.find(:all).collect!(&:name) }.to_json

编辑:而且,创建哈希散列,然后将整个事情转换为json可能更有效,而不是像我们正在做的那样转换piecemail。

所以

class Node < ActiveRecord::Base
  has_many :products
  def json_hash
    if children.size > 0
      children.collect { |node| { node.name => node.json_hash }.to_json
    else
      { node.name => node.products.find(:all).collect!(&:name) }.to_json
    end
  end
end

可能成为

class Node < ActiveRecord::Base
  has_many :products
  def json_hash
    to_hash.to_json
  end

  def to_hash
    if children.size > 0
      children.collect { |node| { node.name => node.to_hash }
    else
      { node.name => node.products.find(:all).collect!(&:name) }
    end
  end
end

这是否有效,是否更有效,我作为练习留给我们;-)

回答

JSONifier!

node.to_json(:include=>{:products=>{:include=>:product_parts}})