Rails: Отключить root в JSON только для определенных действий контроллера? - PullRequest
6 голосов
/ 31 августа 2011

Я знаю, как отключить корневой элемент глобально, например, Rails 3.1 include_root_in_json или с помощью ActiveRecord::Base.include_root_in_json = false, но я хочу сделать это только для нескольких запросов JSON (не глобально).

Пока я делал это так:

@donuts = Donut.where(:jelly => true)
@coffees = Coffee.all
@breakfast_sandwiches = Sandwich.where(:breakfast => true)

dunkin_donuts_order = {}
dunkin_donuts_order[:donuts] = @donuts
dunkin_donuts_order[:libations] = @coffees
dunkin_donuts_order[:non_donut_food] = @breakfast_sandwiches

Donut.include_root_in_json = false
Coffee.include_root_in_json = false

render :json => dunkin_donuts_order

Donut.include_root_in_json = true
Coffee.include_root_in_json = true

Есть около 5 случаев, когда мне приходится это делать, иногда с более чем одной моделью, и она совсем не выглядит чистой. Я пытался поместить это в around_filter с, но исключения нарушали поток, и это также становилось волосатым.

Должен быть лучший способ!

Ответы [ 2 ]

2 голосов
/ 01 сентября 2011

Ответ, к сожалению, да и нет.

Да, то, что вы сделали выше, можно сделать лучше.Нет, Rails не позволит вам добавить рут для каждого отдельного действия.Рендеринг JSON просто не был создан с учетом такой гибкости.

При этом, вот что я бы сделал:

  1. Установите include_root_in_json на falseдля тех моделей, у которых есть root в зависимости от действия (например, Donut и Coffee выше).
  2. Переопределить as_json, чтобы обеспечить большую гибкость.Вот пример:

    # in model.rb
    def as_json(options = nil)
        hash = serializable_hash(options)
        if options && options[:root]
            hash = { options[:root] => hash }
        else
            hash = hash
        end
    end
    

    В этом примере будет сделано так, что вы можете по желанию передать корень, но по умолчанию нет корня.В качестве альтернативы вы можете написать это другим способом.

  3. Поскольку вы переопределили as_json, вам придется соответствующим образом изменить вызовы рендеринга.Итак, для Donut вы бы сделали render :json => @donut.to_json.

Надеюсь, это поможет!

1 голос
/ 07 февраля 2013

Вы можете установить include_root_in_json для модели экземпляр , и это не повлияет на класс (см. class_attribute в rails api для описания этого поведения).Таким образом, вы можете установить разумное значение по умолчанию на уровне класса, а затем установить разные значения для каждого экземпляра в соответствующих контроллерах.

Пример:

@donuts = Donut.where(:jelly => true).each {|d| d.include_root_in_json = false }

Для удобства вы можете создатьслужебный метод, который принимает массив экземпляров модели и устанавливает значение для всех из них.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...