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

По умолчанию для to_json в Rails с: include

Скажем, у меня есть модель Post, которая принадлежит пользователю. Чтобы преобразовать в json, я делаю что-то вроде этого

@reply.to_json(:include => {:user => {:only => [:email, :id]}, 
               :only => [:title, :id])

Однако, я хочу установить некоторые значения по умолчанию для этого, поэтому мне не нужно указывать: только каждый раз. Я пытаюсь переопределить as_json, чтобы выполнить это. Когда я добавляю as_json в модель User, он вызывается, когда я делаю @user.to_json, но когда пользователь включен в @reply.to_json, мой overriden as_json для пользователя игнорируется.

Как мне сделать эту работу?

Спасибо

4b9b3361

Ответ 1

Вы можете сделать это, переопределив serializable_hash в своей модели, например:

class Reply < ActiveRecord::Base
  def serializable_hash(options={})
    options = { 
      :include => {:user => {:only => [:email, :id]}, 
      :only => [:title, :id]
    }.update(options)
    super(options)
  end
end

Это повлияет на все сериализуемые методы, включая serializable_hash, to_json и to_xml.

Ответ 2

В модели Reply:

def as_json(options = {})
   super options.merge(:methods => [:user], :only => [:id, :title])
end

И в модели пользователя:

def as_json(options = {})
   super options.merge(:only => [:id, :email])
end

Если ассоциация включена как метод, а не include, она будет запускать на ней .to_json.

Ответ 3

Вы можете добавить еще один метод в ActiveRecord:: Base, например self.to_minimal_json (* only_fields) и создать свой вызов .to_json.

неважно, но может работать.

Ответ 4

Итак, я выяснил, что проблема заключается в том, что для включения вместо вызова as_json для генерации json Rails напрямую вызывает serializable_hash. Проблема исправлена. Поместите это в инициализатор

module ActiveRecord #:nodoc:
  module Serialization

    def serializable_hash(options = nil)
      options = options.try(:clone) || {}

      options[:except] = Array.wrap(options[:except]).map { |n| n.to_s }
      options[:except] |= Array.wrap(self.class.inheritance_column)

      hash = super(options)

      #serializable_add_includes(options) do |association, records, opts|
        #hash[association] = records.is_a?(Enumerable) ?
        #records.map { |r| r.serializable_hash(opts) } :
        #records.serializable_hash(opts)
      #end

      serializable_add_includes(options) do |association, records, opts|
        hash[association] = records.is_a?(Enumerable) ?
          records.map { |r| r.as_json(opts.merge(:no_root => true)) } :
          records.as_json(opts.merge(:no_root => true))
      end

      hash
    end
  end
end

module ActiveModel
  # == Active Model JSON Serializer
  module Serializers
    module JSON

      def as_json(options = nil)
        hash = serializable_hash(options)

        if include_root_in_json and !options[:no_root]
          custom_root = options && options[:root]
          hash = { custom_root || self.class.model_name.element => hash }
        end

        hash
      end

    end
  end
end

Обратите внимание на то, что вызов serializable_hash заменяется на as_json (с дополнительным параметром для добавления добавления root в include). Теперь, если у вас есть as_json в вашей модели, он будет вызываться даже в случае включения

Ответ 5

Поскольку параметры могут при обстоятельствах быть нуль, нам лучше знать об этом:

module ActiveModel
  # == Active Model JSON Serializer
  module Serializers
    module JSON

      def as_json(options)
        options ||= {}
        hash = serializable_hash(options)

        if include_root_in_json and !options[:no_root]
          custom_root = options && options[:root]
          hash = { custom_root || self.class.model_name.element => hash }
        end

        hash
      end

    end
  end
end