[英]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"
}
]
}
筆記:
我想使用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.