Rails中to_json的默认值为:include

时间:2011-02-15 07:23:38

标签: ruby-on-rails json

让我们说我有一个属于用户的模型帖子。要转换为json,我会做这样的事情

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

但是,我想为此设置一些默认值,所以我不必每次都指定:我试图覆盖as_json来实现这一目标。当我在User模型中添加as_json时,在我执行@ user.to_json时会调用它,但是当用户包含在@ reply.to_json中时,我的覆盖用户as_json将被忽略。

如何使这项工作?

由于

5 个答案:

答案 0 :(得分:33)

您可以通过覆盖模型中的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_hashto_jsonto_xml

答案 1 :(得分:3)

在回复模型中:

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。

答案 2 :(得分:0)

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

不引人注目,但可能会奏效。

答案 3 :(得分:0)

所以我发现问题是对于includes,而不是调用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替换的(带有一个额外的参数来抑制在include中添加root)。现在,如果您的模型中有as_json,即使包含

,也会调用它

答案 4 :(得分:0)

由于选项在某些情况下可能为零,我们最好注意一下:

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