Rails as_json问题 - 如何有效地包含嵌套对象?

blu*_*l2k 10 ruby ruby-on-rails ruby-on-rails-3

我遇到了一个问题,我正在使用as_json方法,以及如何在JSON中有效地返回对象,并且它也是作为JSON的belongs_to对象,其中belongs_to对象具有自己的belongs_to对象.代码可能会更好地解释它.

不工作的方式

警报课

class Alert < ActiveRecord::Base
    belongs_to :message
    # for json rendering
    def as_json(options={})
        super(:include => :message)
    end
end
Run Code Online (Sandbox Code Playgroud)

消息类

 def as_json(options={})
    super( methods: [:timestamp, :num_photos, :first_photo_url, :tag_names],
           include: { camera: { only: [:id, :name] },
                      position: { only: [:id, :name, :address, :default_threat_level ]},
                      images: { only: [:id, :photo_url, :is_hidden]} })
  end
Run Code Online (Sandbox Code Playgroud)

第一次设置的问题是当我有一个Alert对象和调用时

alert.as_json()
Run Code Online (Sandbox Code Playgroud)

我从Alert中获取了所有属性,并从Message中获取了所有属性,但没有来自Message的其他属性,如Camera,Position等.

这是"它的工作,但可能不是正确的设计方式"

警报类

class Alert < ActiveRecord::Base

    belongs_to :message

    # for json rendering
    def as_json(options={})
        super().merge(:message => message.as_json)
    end
end
Run Code Online (Sandbox Code Playgroud)

消息类

  # for json rendering
  def as_json(options={})
    super( methods: [:timestamp, :num_photos, :first_photo_url, :tag_names])
          .merge(:camera => camera.as_json)
          .merge(:position => position.as_json)
          .merge(:images => images.as_json)
  end
Run Code Online (Sandbox Code Playgroud)

在第二个设置中,我得到了所有Message的嵌套属性,就像我想要的那样.

我的问题是,我是否错过了一些适当的Rails公约?似乎应该/应该是一种更简单的方法.

Mav*_*vie 7

对我来说最好的答案是使用serializable_hash.@kikito在他的评论中提到了这一点,但有一个错字阻止它工作.它不是serialized_hash,它是serializable_hash.

字面上只是找到+替换as_json,serializable_hash这个bug就消失了.(它仍未在今天的Rails 4.0.2中修复).您还可以获得以后更轻松地实现XML API的好处(有些人仍然使用它们!).


Cad*_*ade 3

您使用的是哪个版本的 Rails?这是旧版本 Rails 中的一个已知错误,据说已通过此拉取请求修复。你的语法对我来说看起来很正确,所以也许这就是你的问题?

顺便说一句,您可能还想查看 Jose Valim(Rails 核心成员)的新active_model_serializers。它至少可以让您以更优雅的方式解决您的问题。