<p>Is there a fast and clean way of returning a JSON hash back from any node in a Ruby on Rails' acts_as_nested_set without using recursion?</p>

<p>Here's the recursive solution for reference:</p>

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

[{'answer_id': 41275, 'author': 'Mike Stone', 'author_id': 122, 'author_profile': 'https://Stackoverflow.com/users/122', 'pm_score': 2, 'selected': False, 'text': '<p>There is a <a href="http://en.wikipedia.org/wiki/Tree_traversal" rel="nofollow noreferrer">wikipedia article</a> on tree traversal which shows different alternatives to the recursive solution you are using.  It may be tricky to use them in your specific case, but it should be possible.</p>\n\n<p>However, my question to you is, is there a specific reason you want to use iteration instead of recursion?  I don\'t think any of the iterative solutions will be nearly as clean.  Are your trees so big that you are running out of stack space (they would have to be pretty big)?  Otherwise, I\'m not so sure an iterative solution will really be faster.</p>\n\n<p>I see one potential for improvement though, if you are seeing performance issues... but I don\'t know rails, so I\'m not sure if it is accurate:</p>\n\n<p>Does the find method return a new array?  If so, you probably want to invoke .collect! instead of .collect, because if find creates an array, you are just creating an array and then throwing it away to the call to collect (which also creates an array), which surely is not going to be very efficient and may slow you down a lot if you have a big tree there.</p>\n\n<p>So </p>\n\n<pre><code>{ node.name =&gt; node.products.find(:all).collect(&amp;:name) }.to_json\n</code></pre>\n\n<p>might become</p>\n\n<pre><code>{ node.name =&gt; node.products.find(:all).collect!(&amp;:name) }.to_json\n</code></pre>\n\n<p>EDIT: Also, it may be more efficient to create your hash of hashes, and then convert the whole thing to json in 1 fell swoop, rather than converting it piecemail like you are doing.</p>\n\n<p>So</p>\n\n<pre><code>class Node &lt; ActiveRecord::Base\n  has_many :products\n  def json_hash\n    if children.size &gt; 0\n      children.collect { |node| { node.name =&gt; node.json_hash }.to_json\n    else\n      { node.name =&gt; node.products.find(:all).collect!(&amp;:name) }.to_json\n    end\n  end\nend\n</code></pre>\n\n<p>might become</p>\n\n<pre><code>class Node &lt; ActiveRecord::Base\n  has_many :products\n  def json_hash\n    to_hash.to_json\n  end\n\n  def to_hash\n    if children.size &gt; 0\n      children.collect { |node| { node.name =&gt; node.to_hash }\n    else\n      { node.name =&gt; node.products.find(:all).collect!(&amp;:name) }\n    end\n  end\nend\n</code></pre>\n\n<p>Whether this works and is more efficient I leave as an exercise for you ;-)</p>\n'}, {'answer_id': 3587874, 'author': 'standup75', 'author_id': 433333, 'author_profile': 'https://Stackoverflow.com/users/433333', 'pm_score': 1, 'selected': False, 'text': '<p>JSONifier!</p>\n\n<pre><code>node.to_json(:include=&gt;{:products=&gt;{:include=&gt;:product_parts}})\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/41204', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/3499/']