Rails中to_json的默认值是:include

时间:2022-12-31 23:21:01

Let us say I have a model Post which belongs to a User. To convert to json, I do something like this

假设我有一个属于用户的模型贴子。要转换成json,我要这样做

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

However, I want to set some defaults for this so I don't have to specify :only everytime. I am trying to override as_json to accomplish this. When I add as_json in User model, it is called when I do @user.to_json but when user is included in @reply.to_json, my overriden as_json for User is ignored.

但是,我想为它设置一些默认值,这样我就不必每次都指定:only everytime。我正在尝试覆盖as_json来实现这一点。当我在用户模型中添加as_json时,当我使用@user时就会调用它。但当用户包含在@reply中时。to_json,我的overriden as_json用户被忽略。

How do I make this work?

我要怎么做呢?

Thanks

谢谢

5 个解决方案

#1


31  

You can do this by overriding serializable_hash in your model, like so:

可以通过在模型中重写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

This will affect all serializable methods, including serializable_hash, to_json, and to_xml.

这将影响所有可序列化的方法,包括serizable_hash、to_json和to_xml。

#2


3  

In the Reply model:

在应答模式:

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

And in the User model:

在用户模型中:

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

When the association is included as a method and not an include, it will run the .to_json on it.

当关联作为一个方法而不是include被包含时,它将在其上运行.to_json。

#3


0  

You could add another method to ActiveRecord::Base, like self.to_minimal_json(*only_fields) and build your .to_json call there.

您可以向ActiveRecord: Base添加另一个方法,比如self.to_minimal_json(*only_fields),并在那里构建.to_json调用。

unspectacular, but may work.

不引人注目的,但是可能的工作。

#4


0  

So I found out that the problem is that for includes, instead of calling as_json to generate the json, Rails directly calls serializable_hash. Monkey patching fixes the problem. Put this in an initializer

所以我发现问题是for include直接调用serializable_hash而不是调用as_json来生成json。猴子补丁解决了问题。把这个放到初始化器中

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

Notice how the serializable_hash call is replaced with as_json (with an extra parameter to supress addition of root in includes). Now if you has as_json in your model, it will be called even in case of includes

注意,如何用as_json替换serializable_hash调用(在include中添加根的附加参数)。现在,如果您的模型中有as_json,那么即使包含也会调用它

#5


0  

As options might under circumstances be nil, we'd better be aware of it:

由于在这种情况下选择可能是零,我们最好知道:

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

#1


31  

You can do this by overriding serializable_hash in your model, like so:

可以通过在模型中重写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

This will affect all serializable methods, including serializable_hash, to_json, and to_xml.

这将影响所有可序列化的方法,包括serizable_hash、to_json和to_xml。

#2


3  

In the Reply model:

在应答模式:

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

And in the User model:

在用户模型中:

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

When the association is included as a method and not an include, it will run the .to_json on it.

当关联作为一个方法而不是include被包含时,它将在其上运行.to_json。

#3


0  

You could add another method to ActiveRecord::Base, like self.to_minimal_json(*only_fields) and build your .to_json call there.

您可以向ActiveRecord: Base添加另一个方法,比如self.to_minimal_json(*only_fields),并在那里构建.to_json调用。

unspectacular, but may work.

不引人注目的,但是可能的工作。

#4


0  

So I found out that the problem is that for includes, instead of calling as_json to generate the json, Rails directly calls serializable_hash. Monkey patching fixes the problem. Put this in an initializer

所以我发现问题是for include直接调用serializable_hash而不是调用as_json来生成json。猴子补丁解决了问题。把这个放到初始化器中

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

Notice how the serializable_hash call is replaced with as_json (with an extra parameter to supress addition of root in includes). Now if you has as_json in your model, it will be called even in case of includes

注意,如何用as_json替换serializable_hash调用(在include中添加根的附加参数)。现在,如果您的模型中有as_json,那么即使包含也会调用它

#5


0  

As options might under circumstances be nil, we'd better be aware of it:

由于在这种情况下选择可能是零,我们最好知道:

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