Подтвердить что ты не робот

RoR вложен: включить, чтобы включить под-ресурсы в to_xml/to_json

У меня возникла странная ситуация с моделью данных, поэтому, возможно, весь мой подход ошибочен. Вот что я делаю:

У меня есть класс под названием Bird и простой класс Color. Понятно, что у каждой птицы есть две ассоциации to_many для Color, одна для мужских цветов и одна для женских цветов. То, как я справлялся с этим, - использовать модель объединения BirdColoration, которая принадлежит птице и цвету, и имеет дополнительное логическое поле, чтобы определить, является ли окраска для мужчин или женщин. Таким образом, каждая птица на самом деле имеет отношение to_many к BirdColoration, а также to_many to Color: через BirdColoration. Если это звучит разумно, продолжайте чтение. В противном случае остановитесь и скажите мне, почему это неправильно!

Мне нужно, чтобы вываливать стол для птиц как json. Раньше, когда у каждой птицы была только одна ассоциация to_many с цветами, я мог просто использовать: include включить цвета каждой птицы в дампе json. Теперь я включаю BirdColorations в дампе, но мне все равно нужно попасть на цветные модели. Я мог бы отдельно включать цвета и цвета каждой птицы, а затем сопоставлять их во время разбора, но я бы скорее просто включил каждый цвет окраски напрямую. Что-то вроде

      format.json  { render :json => @birds.to_json(:include => [{:bird_colorations => :color}, :seasons, :habitats, :image_holders]) }

Вышеприведенное не работает. Я думаю, что это должно быть возможно. Может ли кто-нибудь указать мне в правильном направлении, как справиться с этим?

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

Спасибо!

4b9b3361

Ответ 1

Я нашел ответ здесь. Синтаксис опции include: to_xml и to_json отличается от синтаксиса для метода find ActiveRecord. Чтобы включить вложенные ресурсы таким образом, вы передаете хэш вместо массива. Правильный вызов метода для меня выглядит следующим образом:

      format.json  { render :json => @birds.to_json(:include => {:bird_colorations => {:include => :color}, :seasons => {}, :habitats => {}, :image_holders => {}}) }

Сравните с тем, что было в моем вопросе, чтобы увидеть разницу. Для ресурсов, для которых вы не хотите включать под-ресурсы, просто передайте пустой хеш в качестве значения для его символьного имени.

Жить и учиться!

Ответ 2

Если у вас сложная структура JSON, лучше переопределить serializable_hash или as_json в вашей модели, чем пытаться сделать все это через render :json.

Так что-то вроде

def serializable_hash(options = nil)
  options ||= {}
  bird = {:name => name, ...}
  bird[:seasons] = seasons.serilizable_hash
  bird[:colors] = ... # whatever complex logic you want to get to the colors
  bird
end

Обе функции просто должны возвращать хэш.