2016-07-01 10 views
3

私のサーバサイドデータテーブルの機能を拡張しようとしています。私はいくつかの余分なフィルターを私のコントローラー/データテーブルに渡します。これを結果のフィルターに使用します。現在のところ、私のモデルでは、スコープを適用する前にパラメータが存在するかどうかをテストしていますが、フィルタのリストが大きくなるif/elseシナリオが多いので、これが最良の方法であるとは確信していません。これを「レールの道」としてどうすればいいですか?条件付きチェーンスコープを設定する最良の方法

if params[:store_id].present? && params[:status].present? 
    Order.store(params[:store_id]).status(params[:status]) 
elsif params[:store_id].present? && !params[:status].present? 
    Order.store(params[:store_id]) 
elsif !params[:store_id].present? && params[:status].present? 
    Order.status(params[:status]) 
else 
    Order.joins(:store).all 
end 

ANSWER:この作業コードに 組み合わせの答え:

query = Order.all 
query = query.store(params[:store_id]) if params[:store_id].present? 
query = query.status(params[:status]) if params[:status].present? 
query.includes(:store) 
+0

なぜ3 difを処理するには1つのAPIエンドポイントを使用する必要がありますかなぜ3エンドポイントを代わりに使用しないのですか? – songyy

+0

それはどういう意味ですか?私はストア/ステータスで注文をフィルタリングしています。 – stoerebink

+0

Ahh OK私の悪い..私はいくつかの操作をしていたと思った – songyy

答えて

3

関係が連鎖可能なので、それはあなたの検索クエリを「構築」することはしばしば便利です。これを行うための正確なパターンは大きく異なり、オーバーエンジニアリングには注意が必要ですが、私が取り組んだ大規模なRailsコードベースでは、普通のRubyオブジェクト(PORO)を使用してクエリを構築しています。あなたのケースでは、あなたはおそらくちょうどそうのようなあなたのロジックを簡素化して逃げることができます:

relation = Order.join(:store) 

if params[:store_id] 
    relation = relation.store(params[:store_id]) 
end 

if params[:status] 
    relation = relation.status(params[:status]) 
end 

@orders = relation.all 

Railsのも、あなたのニーズが特に複雑になる場合には、ways to "undo" logic that has been chained previously提供します。

+0

両方のパラメータが存在しない限り、店に加わる必要はないと思いますよね? –

+0

@HoMan:ユースケースに依存しますが、私の推測では両方のスコープがすでに店舗に加わっています。そうでなければ、2つのブランチは '.unscope(:join)'を指定するか、答えがそうであるような条件を使うことができます。 –

+0

また、あなたのコメントは、なぜ私が結合を使用しているのか考えてしまった。結局必要なかった。乾杯! – stoerebink

5

あなたはこのようにそれを行うことができます。また

query = Order 
query = query.store(params[:store_id]) if params[:store_id].present? 
query = query.status(params[:status]) if params[:status].present? 
query = Order.joins(:store) if query == Order 

、あなたもすぐ内側の条件を含めることstatusstoreスコープを再構築できます。

scope :by_status, -> status { where(status: status) if status.present? } 

その後、あなたの代わりにこれを行うことができます:

query = Order.store(params[:store_id]).by_status(params[:status]) 
query = Order.joins(:store) unless (params.keys & [:status, :store_id]).present? 
関連する問題