Ответ 1
Это известная ошибка в Rails. (Проблема отмечена закрытой из-за миграции на проблемы Github из предыдущего трекера ошибок, но это все еще проблема с Rails 3.1.)
У меня есть модель с данными, которые никогда не должны включаться, когда она отображается как json. Поэтому я применил метод класса as_json для надлежащего поведения. Проблема в том, что другие модели с ассоциациями с этой моделью отображают json, мой пользовательский as_json не вызывается.
class Owner < ActiveRecord::Base
has_one :dog
def as_json(options={})
puts "Owner::as_json"
super(options)
end
end
class Dog < ActiveRecord::Base
belongs_to :owner
def as_json(options={})
puts "Dog::as_json"
options[:except] = :secret
super(options)
end
end
Загрузка среды разработки (Rails 3.0.3)
ruby-1.9.2-p136: 001 > d = Dog.first
= >#<Dog id: 1, owner_id: 1, name: "Scooby", secret: "I enjoy crapping everwhere"
>
ruby-1.9.2-p136: 002 > d.as_json
Собака:: as_json
= > { "dog" = > { "id" = > 1, "name" = > "Scooby", "owner_id" = > 1}}
ruby-1.9.2-p136: 004 > d.owner.as_json (: include = > : dog)
Владелец:: as_json
= > { "owner" = > { "id" = > 1, "name" = > "Shaggy",: dog = > { "id" = > 1, "name" = > "Scooby", "owner_id" = > 1, "secret" = > "Мне нравится обниматься везде" }}}
Спасибо за помощь
Это известная ошибка в Rails. (Проблема отмечена закрытой из-за миграции на проблемы Github из предыдущего трекера ошибок, но это все еще проблема с Rails 3.1.)
Как было отмечено выше, это проблема с базой Rails. Патч rails здесь еще не применяется и кажется хотя бы слегка противоречивым, поэтому я не решаюсь применять его локально. Даже если он применяется как патч обезьяны, это может потенциально осложнить будущие обновления рельсов.
Я по-прежнему рассматриваю RABL, как показано выше, это выглядит полезно. На данный момент я бы предпочел не добавлять в мое приложение другой язык шаблонов. Мои текущие потребности очень малы.
Итак, вот обходной путь, который не требует патча и работает для самых простых случаев. Это работает, когда метод ассоциации as_json
, который вы хотите вызвать, выглядит как
def as_json(options={})
super( <... custom options ...> )
end
В моем случае у меня есть модель Schedule
, у которой много Events
class Event < ActiveRecord::Base
# define json options as constant, or you could return them from a method
EVENT_JSON_OPTS = { :include => { :locations => { :only => [:id], :methods => [:name] } } }
def as_json(options={})
super(EVENT_JSON_OPTS)
end
end
class Schedule < ActiveRecord::Base
has_many :events
def as_json(options={})
super(:include => { :events => { Event::EVENT_JSON_OPTS } })
end
end
Если вы следовали указаниям, что в любое время вы :include
связываете в своих методах as_json()
, вы определяете любые параметры, которые вам нужны в качестве константы в модели, на которую нужно ссылаться, это будет работать для произвольных уровней ассоциаций. ПРИМЕЧАНИЕ Мне нужен только первый уровень ассоциации, настроенный в приведенном выше примере.
Я столкнулся с той же проблемой. Я хотел, чтобы это работало:
render :json => @favorites.as_json(:include => :location)
Но это не так, я закончил тем, что добавил index.json.erb со следующим:
<% favs = @favorites.as_json.each do |fav| %>
<% fav["location"] = Location.find(fav["location_id"]).as_json %>
<% end %>
<%= favs.to_json.html_safe %>
Не исправление - просто работа. Я полагаю, вы сделали то же самое.
Обновление @Джон сказал, что это известная ошибка в Rails. Патч для исправления выглядит следующим образом: at https://github.com/rails/rails/pull/2200. Тем не менее, вы можете попробовать RABL, потому что его сладкий.
Я всегда был разочарован передачей сложного набора опций для создания представлений JSON, которые я хочу. Ваша проблема, с которой я столкнулась с Mongoid в Rails 3.0.9, побудила меня написать шаблоны JSON. Но на самом деле, если вы имеете дело с отношениями или пользовательскими свойствами api, получается, что шаблоны лучше.
Кроме того, работа с разными выходами кажется мне видимым для слоя, поэтому я решил использовать RABL, API templating language.. Это упрощает создание достоверных JSON и включает любые ассоциации или поля.
Не решение проблемы, но лучшее решение для использования.
Я обнаружил, что serializable_hash работает так же, как вы ожидали, что as_json будет работать, и всегда называется:
def serializable_hash(options = {})
result = super(options)
result[:url] = "http://.."
result
end
Об этом сообщается как об ошибке: http://ternarylabs.com/2010/09/07/migrating-to-rails-3-0-gotchas-as_json-bug/