将2个哈希数组合成一个JSON响应

时间:2017-07-10 21:31:17

标签: ruby-on-rails ruby

我正在开发一个具有某种新闻源功能的网站。我想从表中提取包含项目和数据的表中的数据,然后将这些数据的一部分组合成JSON响应。两者都是哈希数组。我不想采取所有这些领域,只有部分。

我以为我会拉两个完整记录然后在一个方法中进行组合,以便只打两次DB。我可以轻松地将最后5个项目拉出来:

class NewsfeedsController < ApplicationController
  before_action :authenticate_user!

  def index
    @newsfeed_data = json_response(return_items(params[:limit]))
  end

  private

  def return_items(limit)
    output = Item.last(limit=limit).reverse
  end
end

现在我被卡住了。我不知道如何从输出中删除不需要的项目或如何将其与用户数据相结合。项目属于模型中的User,因此有一个user_id字段链接它们。

以下是项目和用户的模式

create_table "items", force: :cascade do |t|
  t.string   "name"
  t.text     "description"
  t.string   "type"
  t.json     "properties"
  t.integer  "user_id"
  t.datetime "created_at",                   null: false
  t.datetime "updated_at",                   null: false
  t.index ["user_id"], name: "index_items_on_user_id", using: :btree
end

create_table "users", force: :cascade do |t|
  [lots of Devise settings...]
  t.string   "first_name"
  t.string   "last_name"
  t.string   "company"
  t.string   "position"
  t.string   "email"
  t.json     "tokens"
  t.datetime "created_at",                               null: false
  t.datetime "updated_at",                               null: false
  t.string   "avatar"
  [indexes...]
end

这是我想要的输出:

{
  "name": "Item name",
  "type": "Item type",
  "first_name": "User owner's first name",
  "company": "User's company",
  "avatar": "URL string to saved image"
}

2 个答案:

答案 0 :(得分:2)

最干净,最易维护的方法是使用ActiveRecordSerializers宝石。

  1. Install the gem
  2. app/serializers/newsfeeds_serializer.rb
  3. 创建文件
  4. 在该文件中,定义一个如下所示的序列化程序:

    class NewsfeedsSerializer < ActiveModel::Serializer
      attributes :name, :type, :first_name, :company, :avatar
    
      def first_name
        object.user.first_name
      end
    
      def company
        object.user.company
      end
    
      def avatar
        object.user.avatar
      end
    end
    
  5. 在您的控制器中,按如下方式编写索引路径:

    class NewsfeedsController < ApplicationController
      before_action :authenticate_user!
    
      def index
        @items = Item
          .order(created_at: :desc)
          .limit(params[:limit])
          .includes(:user)
        render json: @items, each_serializer: NewsfeedsSerializer
      end
    end
    
  6. 这将使用我们在序列化程序中定义的方法序列化每个Item对象。使用:includes会预加载每个User所属的Item项,因此我们将使用的所有内容都会在一次数据库调用中被抓取。

    如果您想要编辑您要发送的JSON,可以轻松更改序列化程序。如果您遇到任何设置问题或想要更多自定义配置(camelCased密钥或类似内容),我建议您阅读ActiveModelSerializer guides they provide

答案 1 :(得分:1)

你可以做这样的事情,但是rails可能已经构建了一些用于提取JSON响应的东西。

def return_items(limit=10)
    items = Item.includes(:user).select('user_id, name, type, etc_you_want_to_pick').first(limit)
    response = []
    items.each do |item|
      response << {
        "name": item.name,
        "type": item.type,
        "first_name": item.user.first_name,
        "company": item.user.company,
        "avatar": item.user.avatar
      }
    end
    return response
  end

如果您可以将整个用户放在哈希中,那么可以使用相同的AR查询,然后在集合上调用.as_json。