В статье википедии о обходе дерева показаны различные альтернативы рекурсивному решению, которое вы используете. Может быть сложно использовать их в вашем конкретном случае, но это должно быть возможно.
Однако мой вопрос к вам: есть ли конкретная причина, по которой вы хотите использовать итерацию вместо рекурсии? Я не думаю, что любое из итеративных решений будет почти таким же чистым. Ваши деревья настолько велики, что вам не хватает места в стеке (они должны быть довольно большими)? В противном случае, я не уверен, что итеративное решение действительно будет быстрее.
Я вижу один потенциал для улучшения, хотя, если вы видите проблемы с производительностью ... но я не знаю рельсы, поэтому я не уверен, что это точно:
Возвращает ли метод find новый массив? Если это так, вы, вероятно, хотите вызвать .collect! вместо .collect, потому что, если find создает массив, вы просто создаете массив, а затем выбрасываете его в вызов метода collect (который также создает массив), что, безусловно, не будет очень эффективным и может замедлить работу много, если у вас там большое дерево.
Итак
{ node.name => node.products.find(:all).collect(&:name) }.to_json
может стать
{ node.name => node.products.find(:all).collect!(&:name) }.to_json
РЕДАКТИРОВАТЬ: Кроме того, может быть более эффективно создать ваш хэш хэшей, а затем конвертировать все это в json одним махом, а не конвертировать его по частям, как вы делаете.
So
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
Работает ли это и является ли это более эффективным, я оставляю вам упражнение; -)