#ruby-on-rails #ruby #json #ruby-on-rails-3
#ruby-on-rails #ruby #json #ruby-on-rails-3
Вопрос:
у меня есть таблица данных, которые могут иметь друг друга в качестве родителей или дочерних элементов, она обрабатывается с помощью поля parent_id (я использую драгоценный камень act_as_tree)
элементы первого уровня имеют 0 в качестве parent_id
дочерних элементов может быть бесконечное количество. Я хочу выводить в формате JSON. конечный результат должен быть примерно таким
{
"feild1": "dd",
"filed2": "ee",
"child" : {
"feild1": "dd",
"filed2": "ee",
}
"child" : {
"feild1": "dd",
"filed2": "ee",
"child" : {
"feild1": "dd",
"filed2": "ee",
}
}
}
пока у меня есть только это
def coa_tree
@roots = Coa.find(:all, :conditions => ['parent_id = ?', 0])
@response = @roots
@roots.each do |root|
logger.debug "roots each"
output = root
root.children.each do |child|
output = {:child => output, :child => child}
end
end
respond_with(@response)
end
очевидно, что я даже близко не подошел к решению проблемы. Если бы кто-нибудь мог указать мне правильное направление, я был бы очень признателен. возможно, есть плагин, о котором я не знаю, который помог бы мне решить эту проблему.
Спасибо.
Ответ №1:
Ваш пример JSON недопустим, потому что в одном объекте есть несколько ключей с одинаковым именем, но вывод древовидной структуры в виде JSON из объекта ActiveRecord определенно возможен.
Попробуйте добавить подобный метод в свой класс модели:
class Coa < ActiveRecord::Base
def to_node
{ "attributes" => self.attributes,
"children" => self.children.map { |c| c.to_node }
}
end
end
Теперь вы можете получить все дерево в формате JSON, используя:
root = Coa.find(:first, :conditions => ["parent_id = ?", 0])
root.to_node.to_json
Комментарии:
1. спасибо, это помогло. и я предполагаю, что более чистым является наличие рекурсивной функции в модели.
Ответ №2:
Единственное, что я хотел бы добавить к ответу Тодда Янделла, это то, что может быть полезно не иметь отдельных ключей для «атрибутов» и «дочерних элементов». Другими словами, в то время как метод Янделла возвращал бы данные, подобные этому:
{
"attributes" : {
"field1": "dd",
"field2": "ee",
"children" : [{
"field1": "dd",
"field2": "ee",
}, {
"field1": "dd",
"field2": "ee",
}, {
"field1": "dd",
"field2": "ee",
}]
}
Возможно, вы пожелаете, чтобы данные в приведенном выше вопросе были отформатированы следующим образом:
{
"field1": "dd",
"field2": "ee",
"children" : [{
"field1": "dd",
"field2": "ee",
}, {
"field1": "dd",
"field2": "ee",
}, {
"field1": "dd",
"field2": "ee",
}]
}
Этот формат особенно полезен в ситуациях, когда клиентский код ожидает данные в формате JSON в формате дерева и не позволяет гибко определять разные ключи для родительских атрибутов и дочерних элементов (например, компонент NestedList в Sencha Touch и т.д.).
Для достижения этой цели, основываясь на концепции Янделла, я придумал следующее:
def to_node
self.attributes.merge({:children => self.children.map { |c| c.to_node }})
end