簡體   English   中英

使用Rabl渲染哈希數組

[英]Render array of hashes using rabl

我的控制器中包含以下哈希值。

@order = {
  :id => "somestringid",
  :user_id => "someotherstringid",
  :amount => 19.99,
  :metadata => [
    {
      :type => :shipping_data,
      :address => "line 1 of address, line 2 of address, city, state, pincode"
    },
    {
      :type => :payment,
      :stripe_customer_id => "somestringid",
      :stripe_card_id => "someotherstringid"
    },
    {
      :type => :contact,
      :email => "someone@example.com",
      :phone => "1231231231"
    }
  ]
}

筆記:

  1. “元數據”是對象列表。
  2. 可以有0個,1個或多個元數據對象。
  3. 每個元數據對象具有不同的結構。
  4. 所有元數據對象的唯一通用鍵是“類型”鍵。

我想使用rabl生成以下json,但無法弄清楚應放入模板中的內容。

我想要的JSON輸出應如下所示。

{
  "id": "somestringid",
  "user_id": "someotherstringid",
  "amount": 19.99,
  "metadata": [
    {
      "type": "shipping_data",
      "address": "line 1 of address, line 2 of address, city, state, pincode"
    },
    {
      "type": "payment",
      "stripe_customer_id": "somestringid",
      "stripe_card_id": "someotherstringid"
    },
    {
      "type": "contact",
      "email": "someone@example.com",
      "phone": "1231231231"
    }
  ]
}

我應該在模板中放入什么,以便獲得所需的輸出?

注意

我不確定rabl是指使用標准的rabl gem 還是rabl-rails,因為您尚未提供有關應用程序性質的任何詳細信息,而是使用所有庫構建的。

但是我下面的解決方案是在使用rabl-rails gem的Rails應用程序的上下文中。 rabl-rails gem的README內容如下:

與標准的rabl gem相比,rabl-rails更快,並且使用的內存更少,同時使您可以訪問相同的功能。 為了使此gem能夠正常工作,您需要對模板進行一些細微的更改,但此過程不會超過5分鍾。

因此,我認為無論應用程序是基於Rails還是Non-Rails構建的,都可以在標准rabl gem的上下文中適應該解決方案。 我的目的是為可用於實現所需輸出的方法提供指導。

現在介紹解決方法:

使用一些抽象,您可以設計一個靈活且可維護的解決方案。 讓我詳細說明:

假設您具有像下面這樣的簡單的紅寶石類Order或者如果您沒有任何此類,則可以使用virtus gem輕松定義它,該類為該類提供了一些方便的即用型功能:

app / models / order.rb

  class Order
    attr_accessor :id, :user_id, :amount, :order_metadata_obj_arr

    ....
    ..
  end

app / models / order_metadata.rb

  class OrderMetadata
    attr_accessor :metadata_type, :metadata_data_obj

    ...
    ...
  end

app / models / shipping_data.rb

  class ShippingData
    attr_accessor :address
  end

app / models / payment_data.rb

  class PaymentData
    attr_accessor :stripe_customer_id, :stripe_card_id
  end

app / models / contact_data.rb

  class ContactData
    attr_accessor :email, :phone
  end

/app/json_views/orders/metadata/shipping.rabl

attribute :address

/app/json_views/orders/metadata/payment.rabl

attribute :stripe_customer_id, :stripe_card_id

/app/json_views/orders/metadata/contact.rabl

attribute :email, :phone

/app/json_views/orders/order_metadata.rabl

attribute :type

# Anonymous node.
node do |order_metadata_obj|
  template_path = "./orders/metadata/#{order_metadata_obj.type}"
  metadata_data_obj = order_metadata_obj.metadata_data_obj
  partial(template_path, object: metadata_data_obj)
end

/app/json_views/order.rabl

  attributes :id, :user_id, :amount

  node(:metadata) do |order_obj|
    partial('./orders/order_metadata', object: order_obj.order_metadata_obj_arr)
  end

然后在您的控制器中執行此操作

/app/controllers/my_controller.rb

 class MyController < MyBaseController

    def my_action
      order_obj = create_order_obj_from_hash(order_hash)

      order_json = order_json_representation(order_obj)
      status = 200

      render json: order_json, status: status
    end

    private

    def create_order_obj_from_hash(order_hash)
      order_metadata_arr = order_hash[:metadata]

      order_metadata_obj_arr = []

      order_metadata_arr.each do |item_hash|
        md_type = item_hash[:type]

        md_obj = case md_type
                        when :shipping_data
                          ShippingData.new(address: item_hash[:address])
                        when :payment
                          PaymentData.new(stripe_customer_id: item_hash[:stripe_customer_id], stripe_card_id: item_hash[:stripe_card_id])
                        when :contact
                          ContactData.new(email: item_hash[:email], phone: item_hash[:phone])
                        else
                          // unsupported md_type
                      end

        unless md_obj.nil?
          omd_obj = OrderMetadata.new(metadata_type: md_type, metadata_data_obj: md_obj)
          order_metadata_obj_arr << omd_obj
        end
      end

      order_attrs = order_hash.slice(:id, :user_id, :amount)

      order = Order.new(order_attrs)
      order.order_metadata_obj_arr = order_metadata_obj_arr
      order
    end

    def order_json_representation(order_obj)
      template_name = "order.rabl"
      template_path = Rails.root.join("app", "json_views")
      RablRails.render(order_obj, template_name, view_path: template_path, format: :json)
    end
  end

希望這可以幫助。

謝謝。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM