Включение атрибута "тип" в json response_with Rails 3.1
Кажется, что при возврате объекта, содержащего атрибут "тип" в виде JSON из приложения Rails 3.1, атрибут "тип" не включается. Предположим, у меня есть следующее:
Модель с соответствующей таблицей STI Animal. Модели кошек, собак и рыб, которые наследуют животных.
Возвращая Animal через JSON, я хочу включить столбец "type", но этого не происходит:
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 ответа
Переопределите метод as_json. Используется to_json
для того, чтобы произвести вывод. Вы можете сделать что-то вроде:
def as_json options={}
{
id: id,
can_swim: can_swim,
type: type
}
end
Это то, что я сделал. Это просто добавляет недостающее type
к набору результатов
def as_json(options={})
super(options.merge({:methods => :type}))
end
Для меня в 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
Итак, в моем приложении я поместил это в миксин:
module RailsStiModel
# The following two methods add the "type" parameter to the to_json output.
# see also:
# http://stackru.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
Вот мое решение, которое может сохранить оригинальную особенность 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