11

似乎当从 Rails 3.1 应用程序返回包含“类型”属性作为 JSON 的对象时,“类型”属性不包括在内。假设我有以下内容:

具有相应 STI 表 Animal 的模型。继承 Animal 的 Cat、Dog 和 Fish 模型。

通过 JSON 返回动物时,我希望包含“类型”列,但这没有发生:

jQuery.ajax("http://localhost:3001/animals/1", {dataType: "json"});

产量:

responseText: "{"can_swim":false,"created_at":"2012-01-20T17:55:16Z","id":1,"name":"Fluffy","updated_at":"2012-01-20T17:55:16Z","weight":9.0}"

这似乎是 to_json 的问题:

bash-3.2$ rails runner 'p Animal.first.to_yaml'
"--- !ruby/object:Cat\nattributes:\n  id: 1\n  type: Cat\n  weight: 9.0\n  name: Fluffy\n  can_swim: false\n  created_at: 2012-01-20 17:55:16.090646000 Z\n  updated_at: 2012-01-20 17:55:16.090646000 Z\n"

bash-3.2$ rails runner 'p Animal.first.to_json'
"{\"can_swim\":false,\"created_at\":\"2012-01-20T17:55:16Z\",\"id\":1,\"name\":\"Fluffy\",\"updated_at\":\"2012-01-20T17:55:16Z\",\"weight\":9.0}"

有谁知道这种行为背后的原因,以及如何覆盖它?

4

4 回答 4

19

这就是我所做的。它只是将缺失的内容添加type到结果集中

  def as_json(options={})
    super(options.merge({:methods => :type}))
  end
于 2013-09-26T15:56:25.747 回答
6

覆盖as_json方法。它被用于to_json产生输出。您可以执行以下操作:

def as_json options={}
 {
   id: id,
   can_swim: can_swim,
   type: type
 }
end
于 2012-01-20T18:07:00.790 回答
1

对我来说,在 Rails 2.3.12 中,上述方法不起作用。

我可以(当然在我的模型中)做这样的事情:

class Registration < ActiveRecord::Base

  def as_json(options={})
    super(options.merge(:include => [:type]))
  end

end

但这会导致 to_json 抛出如下错误:

NoMethodError: undefined method `serializable_hash' for "Registration":String

我已经解决了这个问题,将这个方法打到我要导出的对象上

class Registration < ActiveRecord::Base

  def as_json(options={})
    super(options.merge(:include => [:type]))
  end

  def type
    r  = self.attributes["type"]
    def r.serializable_hash(arg)
      self
    end
    r
  end
end

所以在我的应用程序上,我把它放到了一个 mixin 中:

module RailsStiModel
  # The following two methods add the "type" parameter to the to_json output.
  # see also:
  # http://stackoverflow.com/questions/8945846/including-type-attribute-in-json-respond-with-rails-3-1/15293715#15293715
  def as_json(options={})
    super(options.merge(:include => [:type]))
  end

  def type
    r  = self.attributes["type"]
    def r.serializable_hash(arg)
      self
    end
    r
  end
end

现在在我的模型类中,我添加:

include RailsStiModel
于 2013-03-08T12:10:20.877 回答
0

这是我的解决方案,它可以保留 as_json 的原始功能。

def as_json(options={})
  options = options.try(:clone) || {}
  options[:methods] = Array(options[:methods]).map { |n| n.to_sym }
  options[:methods] |= [:type]

  super(options)
end
于 2013-07-08T03:00:37.657 回答