如何正确地将两个as_json方法组合成一个?

时间:2015-10-23 10:10:39

标签: ruby-on-rails ruby json

在我的模型中,我有一个as_json方法,如下所示:

  def as_json(options = {})
    super(options.merge(include: [:user, comments: {include: :user}]))
  end

此方法用于在评论中包含用户。

现在我需要在同一模型中添加几乎相同的东西以获得答案:

  def as_json(options = {})
    super(options.merge(include: [:user, answers: {include: :user}]))
  end

如何组合这两个as_json方法,以便我有一个as_json方法?

不要笑,但是我在为此奋斗了3天。

3 个答案:

答案 0 :(得分:3)

这是您不应使用内置to_json序列化ActiveRecord模型的原因之一。

相反,您应该将任务委托给另一个名为serializer的对象。使用序列化程序可以让您拥有同一对象的 illimitate Representations (序列化)(如果对象可以有不同的变体,例如有/没有注释等,则非常有用)和关注点分离

创建自己的序列化程序很简单,就像拥有

一样简单
class ModelWithCommentsSerializer
  def initialize(object)
    @object = object
  end

  def as_json
    @object.as_json(include: [:user, comments: {include: :user}])) 
  end
end

class ModelWithAnswersSerializer
  def initialize(object)
    @object = object
  end

  def as_json
    @object.as_json(include: [:user, answers: {include: :user}])) 
  end
end

当然,这仅仅是一个例子。您可以提取该功能以避免重复。

还有一些像ActiveModelSerializers这样的宝石提供了这个功能,但是我更愿意避免它们,因为它们往往提供了大部分用户真正需要的东西。

答案 1 :(得分:0)

def as_json(other_arg, options = {})
  as_json(options.merge(include: [:user, other_arg: {include: :user}])) 
end

然后你可以打电话:

MyModel.as_json(:comments)
MyModel.as_json(:answers)

答案 2 :(得分:0)

为什么要尝试覆盖核心Rails功能 - 除非绝对必要,否则不是好的做法。

-

This说以下内容:

  

要包含关联,请使用:include:

user.as_json(include: :posts)
# => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
#      "created_at" => "2006/08/01", "awesome" => true,
#      "posts" => [ { "id" => 1, "author_id" => 1, "title" => "Welcome to the weblog" },
#                   { "id" => 2, "author_id" => 1, "title" => "So I was thinking" } ] }

你可以打电话:

@answers.as_json(include :users)

-

Ohhhhhhhh:

  

二级和更高级别的关联也起作用:

user.as_json(include: { posts: {
                       include: { comments: {
                                      only: :body } },
                       only: :title } })
# => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
#      "created_at" => "2006/08/01", "awesome" => true,
#      "posts" => [ { "comments" => [ { "body" => "1st post!" }, { "body" => "Second!" } ],
#                     "title" => "Welcome to the weblog" },
#                   { "comments" => [ { "body" => "Don't think too hard" } ],
#                     "title" => "So I was thinking" } ] }

所以看起来你可以打电话:

@answers.to_json(include: comments: { include: :users })