2013-07-20 19 views
17

ActiveModel :: Serializersを使用してAPIを構築しています。 paramsを使用して条件付きでデータをサイドロードする最善の方法は何ですか?ActiveModel ::シリアライザで条件付きでサイドローディング

だから私はGET /api/customersのような要求を行うことができますのparamsに応じて、そのような

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

そして

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

GET /api/customers?embed=address,note何かを。 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のような何か他のもののためのスコープを使用する必要がある場合ので、私はこの方法が好きではありません。

しかし、この解決策は場合によっては機能します。

あなたはview_contextを渡す代わりに直接paramsを渡すことができます

UPDATE。

scopeの代わりにparamsの名前を保持するようにシリアライザで委任できます。あなたの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を使うことができます。例えば、コントローラにあなたはCustomerSerializerで、その後

render json: customer, include_addresses: true 

を呼び出す場合:

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

が、その後のアドレスがシリアライズされます。 include_addressesfalseに設定してレンダリングすると、レンダリングされません。 新しいバージョンのactive_model_serializersでは、 @optionsではなく serialization_optionsを使用してください。