2013-10-26 5 views
0

У меня есть класс Item, который также содержит много элементов (с использованием has_many). Я хочу прочитать все элементы, у которых нет родительского (верхнего уровня) и всех их подэлементов. Поэтому в основном мне нужна вся таблица элементов, вложенная правильно, в json.Rails to_json со всеми отношениями

Это код, который я использую прямо сейчас, но это возвращает только элементы верхнего уровня и их элементы, это не идет ни на что ниже. (Так что я оставил только два уровня)

@items = Item.where("item_id IS ?" , nil).order("position") 
respond_to do |format| 
    format.json { render :json => @items.to_json(:include => :items)} 
end 
+0

вы знаете о RABL камень? Я думаю, вы можете использовать его. https://github.com/nesquena/rabl –

+0

Класс предмета, который также содержит много элементов? – shiva

+0

@shiva да. Итак, в основном для каждого элемента, который я могу сделать Item.first.items – networkprofile

ответ

2

Я не предлагаю переопределить as_json или to_json.

Причина в том, что вам нужны необработанные данные в другом месте, и вам могут потребоваться данные в другом формате. Манипуляция as_json, наконец, изменит данные, и вы не сможете расширить их.

Использование декоратора - путь. Хороший выбор драгоценный камень ActiveModel Serializers. В основном это работает, как этот

class ItemSerializer < ActiveModel::Serializer 
    attributes :id, :title, :body 
    has_many :comments # The JSON output will have comments inside. 
end 

, а затем в контроллере:

@items = Item.where("item_id IS ?" , nil).order("position") 
respond_to do |format| 
    format.json { render :json => @items } 
end 

Ваш @items будет сериализуются ItemSerializer автоматически.

Или вы можете выбрать пользовательский сериалайзер

render json: @items, each_serializer: ItemWithAssociatedSerializer 
+1

переопределение 'as_json', как я это делал, просто меняет по умолчанию, поэтому вы всегда можете вернуться к предыдущему поведению, передав аргументы 'to to_json'. Во всяком случае, лучше использовать сериализатор (я использовал as_json, потому что это официально рекомендованный метод), поэтому вы правы :) –

1

Во-первых, я бы рекомендовал использовать драгоценный камень, как ancestry или awesome nested set. Это поможет вам эффективно управлять структурой элементов данных (получение всей иерархии в одном запросе SQL и т. Д.).

, то вы можете сделать что-то вроде этого:

class Item 
    def as_json(options={}) 
    super({include: items}.merge options) 
    end 
end 

это означает, что вызов to_json по пункту по умолчанию включают детский JSON; поэтому рекурсивно мы идем по всей иерархии.

Если вам нужен способ, чтобы ограничить количество вложенных уровней, вы можете сделать:

class Item 
    def as_json(options={}) 
    return super({include: items}.merge options) unless options[:depth].present? 
    if options[:depth] > 0 
     super({include: items, depth: options[:depth] - 1}.merge options) 
    else 
     super 
    end 
    end 
end 
+0

Это, похоже, не работает (или мне нужно сначала установить драгоценные камни?) Это на самом деле единственный такой случай в моем приложении, и мне не нужно много вариантов, но я посмотрю на эти драгоценные камни, если они облегчат жизнь. Благодаря! – networkprofile

+0

извините, не испытал это. Что не работает? первое или второе решение? –

+0

ouch, опечатка. 'includes' =>' 'nclude' –

Смежные вопросы