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

Добавить виртуальный атрибут для вывода json

Скажем, у меня есть приложение, которое обрабатывает список TODO. В списке завершены и незавершенные предметы. Теперь я хочу добавить два виртуальных атрибута в объект списка; количество готовых и незавершенных предметов в списке. Мне также нужны, чтобы они отображались на выходе json.

У меня есть два метода в моей модели, которые извлекают незавершенные/готовые элементы:

def unfinished_items 
  self.items.where("status = ?", false) 
end 

def finished_items 
  self.items.where("status = ?", true) 
end

Итак, как я могу получить количество этих двух методов в моем json файле?

Я использую Rails 3.1

4b9b3361

Ответ 1

Сериализация объектов в Rails состоит из двух шагов:

  • Во-первых, as_json вызывается для преобразования объекта в упрощенный хэш.
  • Затем to_json вызывается в возвращаемом значении as_json для получения окончательной строки JSON.

Обычно вы хотите оставить to_json самостоятельно, поэтому все, что вам нужно сделать, это добавить свою собственную реализацию as_json вроде следующего:

def as_json(options = { })
    # just in case someone says as_json(nil) and bypasses
    # our default...
    super((options || { }).merge({
        :methods => [:finished_items, :unfinished_items]
    }))
end

Вы также можете сделать это следующим образом:

def as_json(options = { })
    h = super(options)
    h[:finished]   = finished_items
    h[:unfinished] = unfinished_items
    h
end

если вы хотите использовать разные имена для поддерживаемых методом значений.

Если вам интересны XML и JSON, посмотрите serializable_hash.

Ответ 2

С Rails 4 вы можете сделать следующее -

render json: @my_object.to_json(:methods => [:finished_items, :unfinished_items])

Надеюсь, что это поможет кому-то, кто находится на последней/последней версии

Ответ 3

Другой способ сделать это - добавить это в свою модель:

def attributes
  super.merge({'unfinished' => unfinished_items, 'finished' => finished_items})
end

Это также автоматически будет работать для сериализации xml. http://api.rubyonrails.org/classes/ActiveModel/Serialization.html Однако имейте в виду, что вам могут понадобиться строки для ключей, поскольку метод не может обрабатывать символы при сортировке ключей в рельсах 3. Но он не сортируется в рельсах 4, поэтому больше не должно быть проблем.

Ответ 4

просто закройте все ваши данные в один хэш, например

render json: {items: items, finished: finished, unfinished: unfinished}

Ответ 5

Я просто подумал, что дам этот ответ всем, как я, который пытался интегрировать это в существующий блок as_json:

  def as_json(options={})
    super(:only => [:id, :longitude, :latitude],
          :include => {
            :users => {:only => [:id]}
          }
    ).merge({:premium => premium?})

Просто нажмите .merge({}) в конце вашего super()

Ответ 6

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

  render json: list.attributes.merge({
                                       finished_items: list.finished_items,
                                       unfinished_items: list.unfinished_items
                                     })

Ответ 7

В качестве Aswin, приведенного выше, :methods позволит вам вернуть конкретный метод/функцию модели в качестве атрибута json, если у вас сложная ассоциация будет делать трюк, поскольку он добавит функции к существующей модели/ассоциациям: D будет работать как прелесть, если вы не хотите переопределять as_json

Проверьте этот код и обратите внимание, как я использую :methods, а также :include [N + Query даже не вариант;)]

render json: @YOUR_MODEL.to_json(:methods => [:method_1, :method_2], :include => [:company, :surveys, :customer => {:include => [:user]}])

Функция Overwritting as_json будет сложнее в этом сценарии (особенно потому, что вы должны добавить собеседники :include вручную:/ def as_json(options = { }) end