10

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

不工作的方式

警报类

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

消息类

 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

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

alert.as_json()

我从 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

消息类

  # 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

在第二个设置中,我得到了我想要的所有消息的嵌套属性。

我的问题是,我是否缺少一些 Rails 约定来正确执行此操作?似乎会有/应该有更简单的方法。

4

3 回答 3

7

对我来说最好的答案是使用serializable_hash. @kikito 在他的评论中谈到了这一点,但有一个错字导致它无法正常工作。不是serialized_hash,是serializable_hash

从字面上看,只需 find + replace as_jsonwith serializable_hash,这个错误就消失了。(它在今天的 Rails 4.0.2 中仍未修复)。您还可以在以后更轻松地实现 XML API 中获益(有些人仍在使用这些!)。

于 2014-03-25T02:22:58.137 回答
3

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

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

于 2012-04-26T20:11:46.550 回答
1

我建议您看一下 RABL(代表 Ruby API Builder 语言)gem(railscastgithub)。它为您提供了一个 DSL,用于在模板中定义 JSON(以及 XML)响应的结构(就像 Haml 或 CoffeeScript 一样)。它还支持部分。

于 2012-04-26T19:54:38.187 回答