2013-07-20 27 views
17

我使用ActiveModel :: Serializers來構建API。使用params有條件地加載數據的最佳方法是什麼?有條件地使用ActiveModel :: Serializer進行側載

所以我可以請求像GET /api/customers

"customers": { 
    "first_name": "Bill", 
    "last_name": "Gates" 
} 

而且GET /api/customers?embed=address,note

"customers": { 
    "first_name": "Bill", 
    "last_name": "Gates" 
}, 
"address: { 
    "street": "abc" 
}, 
"note": { 
    "body": "Banned" 
} 

類似的東西取決於PARAMS。我知道ActiveModel :: Serializers的語法是include_[ASSOCIATION]?,但是如何從控制器中有效地使用它?


這是我目前的解決方案,但它不是整齊:

customer_serializer.rb:

def include_address? 
    !options[:embed].nil? && options[:embed].include?(:address) 
end 

application_controller.rb:

def embed_resources(resources = []) 
    params[:embed].split(',').map { |x| resources << x.to_sym } if params[:embed] 
    resources 
end 

customers_controller.rb:

def show 
    respond_with @customer, embed: embed_resources 
end 

必須是一個更簡單的方法?

回答

8

我也在尋找一種有效且乾淨的方法來做到這一點。

我找到了一個解決方案,但它不漂亮。

在我BaseController/ApplicationController中添加此方法:

serialization_scope :params 

所以範圍是現在params哈希表,我可以在我的序列化的include_[ASSOCIATION]?方法使用它。

def include_associations? 
    if scope[:embed] 
     embed = scope[:embed].split(',') 
     return true if embed.include?('associations') 
    end 
end 

,因爲如果我需要使用範圍別的東西,如current_user有條件地返回數據,如果它是例如管理員,我不喜歡這種方法。

但是這種解決方案可以在某些情況下工作。

UPDATE

您可以通過view_context而不是直接通過params

而且您可以在您的序列化程序中委託params名稱而不是scope

在你的ApplicationController

serialization_scope :view_context 

在串行:

delegate :params, to: :scope 

瞧,你可以使用PARAMS:在您的序列化的include_[ASSOCIATION]?方法[嵌入]。

+0

我喜歡你的建議,使用view_context。是否有可能使用rspec進行單元測試? – Richard

+0

我已更新我的問題,向您展示我是如何一直這樣做的。 – Richard

+0

明智的答案,謝謝@lou。十分優雅。 – tristanm

2

我還有一個解決方案基於你的答案,因爲我想要類似的功能。根據文檔,如果您想要關聯序列化的較低級別控制,則可以覆蓋include_associations!

例如:

def include_associations! 
    if scope[:embed] 
     include! :addresses, {embed: :ids, include: true} 
    else 
     include! :addresses, {embed: :ids} 
    end 
end 
1

非常有用瞭解include_associations!謝謝!注意到使用active_model_serializers gem(版本0.8.3),您可以使用@options在控制器中設置上下文。例如,如果在控制器調用

render json: customer, include_addresses: true 

然後在CustomerSerializer:

has_many :addresses 
def include_associations! 
    if @options[:include_addresses] 
    include! :addresses 
    end 
end 

那麼地址將被序列化。如果您使用include_addresses設置爲false進行渲染,則它們不會。 使用更新版本的active_model_serializers,請使用serialization_options而不是@options

相關問題