【问题标题】:Rails - Building custom JSON using JBuilderRails - 使用 JBuilder 构建自定义 JSON
【发布时间】:2014-08-09 21:11:29
【问题描述】:

我目前正在开发一个个人 Rails 4 项目,在其中一个控制器中,我有一个包含三个不同对象的数组,我正试图将其转换为 JSON。我正在使用find_by_sql 方法通过自定义MySQL 查询来查询数据库。代码如下:

控制器:

class ActivitiesController < ApplicationController
  def index
    user = current_user.id # using devise
    limit = 100

    likes = Like.find_by_sql(...)
    shares = Share.find_by_sql(...)
    comments = Comment.find_by_sql(...)

    @activities = [likes, shares, comments]
  end
end

这三个对象中的每一个都包含不同的字段。例如,likes 对象包含 post_idfirst_namelast_name 等字段。shares 对象包含 post_idfirst_namelast_name 等字段。 strong>post_id、share_countshared_time

这是我要输出的 JSON:

{
    "likes": [
      { "post_id": "7", "first_name": "Yss", "last_name": "Salas", "profile_pic": "345943754_o.png" },
      { "post_id": "34", "first_name": "Jessica", "last_name": "Nigri", "profile_pic": "pikachu.png" }
    ],
    "shares": [
      { "post_id": "43", "share_count": 54, "shared_time": "2014-05-04 15:14:45" },
      { "post_id": "54", "share_count": 17, "shared_time": "2014-05-24 03:43:45" }
    ],
    "comments": [
      { "post_id": "34", "first_name": "Yss", "last_name": "Salas", "comment": "¡Me gustas mucho!" },
      { "post_id": "12", "first_name": "Jenna", "last_name": "Marbles", "comment": "Blah blah blah look at my ugly dog awwwww!" }
    ]
}

index.json.jbuilder:

json.array! @activities do |subactivities|
  json.array! subactivities do |activity|
    if activity.class == Like
      json.likes.post_id activity.post_id #exception raised in this line
      json.likes.title activity.title
      json.likes.first_name activity.first_name
      json.likes.last_name activity.last_name
      json.likes.profile_pic activity.profile_pic
    elsif activity.class == Share
      json.shares.post_id activity.post_id
      json.shares.share_count activity.share_count
      json.shares.shared_time activity.shared_time
    else
      json.comments.post_id activity.post_id
      json.comments.first_name activity.first_name
      json.comments.last_name activity.last_name
      json.comments.comment activity.comment
    end
  end
end

以上引发了异常NoMethodError in Activities#index, undefined method 'post_id' for #&lt;Object:0x00000003064250&gt;。我对 Rails 很陌生,我猜这是因为没有 json.likes 属性可以分配值。如何使用 JBuilder 构建上述 JSON 结构?

【问题讨论】:

    标签: ruby-on-rails json jbuilder


    【解决方案1】:

    来自 Jbuilder 的GitHub page,解决方案相当简单。所需要做的就是将实例变量传递到一个块中,然后手动分配自定义键/值对。

    以下示例将为 @likes 实例变量生成一个键/值对数组:

    # activities/index.json.jbuilder
    
    json.likes @likes do |like|
      json.post_id like.post_id
      json.first_name like.user.first_name
      json.last_name like.user.last_name
      json.profile_pic like.user.profile_pic
    end
    

    上面会输出:

    {
      "likes": [
        { "post_id": 7, "first_name": "Yss", "last_name": "Salas", "profile_pic": "345943754_o.png" },
        { "post_id": 34, "first_name": "Jessica", "last_name": "Nigri", "profile_pic": "pikachu.png" }
      ],
    }
    

    【讨论】:

      【解决方案2】:

      您可以在没有 JBuilder 的情况下做到这一点,更轻松、更快捷。

      def index
        user = current_user.id # using devise
        limit = 100
      
        likes = Like.find_by_sql(...).map(&:attributes) # this will return an array of JSON objects
        shares = Share.find_by_sql(...).map(&:attributes)
        comments = Comment.find_by_sql(...).map(&:attributes)
      
        @activities = {"likes" => likes, "shares" => shares, "comments" => comments}
      end
      

      像这样,你有一个包含所有你需要的信息的哈希。 最好将查找喜欢、分享和 cmets 的逻辑提取到一个单独的类中,这样您就可以调用InformationCollector.collect,它会给您所需的响应。

      【讨论】:

      • 虽然你的例子很方便,但不幸的是,我需要在这个项目中使用 Jbuilder。我已经从项目 GitHub 页面上的 Jbuilder wiki 中弄清楚了(我将回答我自己的问题)。看来是我想多了,解决方案比我想象的要简单得多。
      猜你喜欢
      • 2016-01-10
      • 2020-05-15
      • 1970-01-01
      • 2012-10-03
      • 1970-01-01
      • 2013-05-13
      • 2016-03-01
      • 1970-01-01
      • 2014-01-09
      相关资源
      最近更新 更多