2017-12-13 12 views
4

私はwhere句複数の同一でかなり複雑なクエリに対処するために持っている同じ複数のリファクタリング:あなたは、レール&ActiveRecordの - 私はRailsの5</p> <p>によwhere句

::AllocatedBudget.joins(:account_code, :budget, account_code: [:place], 
          budget: [:fiscal_year, :budget_state]) 
        .where(immeuble:   { id: place.id }) 
        .where(situation_budget: { codesituation: ['A', 'V']}) 
        .where(plan_comptable:  { supprime: 'false' }) 
        .where(budget:    { supprime: 'false'}) 
        .where(situation_budget: { supprime: 'false' }) 
        .where(budget_previsionnel: { supprime: 'false' }) 
        .where(exercice_comptable: { supprime: 'false' }) 

ファースト私のモデルが醜い名前の古いデータベースに接続されていることを知っている必要があります。私はActiveRecordがクエリを実行するためにモデルの名前の代わりにカスタム名を必要としていることに気付きました。理由は分かりませんが、それだけで動作します...もし誰かがそれがいいと説明できたら)

私の実際の質問は、より良い方法で書くことができますか?同じ時間句 "supprime = 'false'"が非常に多くあります。

ありがとうございます! :)

+0

さて、あなたのすべての 'where'メソッド条件を1つにマージすることができます。また、 '{supprime: 'false'}'を呼び出し前に定義された同じ値の変数に置き換えることもできます。 – potashin

+0

@potashin節はどこですか?読むのが難しいですが、何か利点はありますか? – Matt

+0

モデルでスコープを定義して、代わりにここで使用できます。 –

答えて

0

だろうステップ等しくなりますAndrewSwerlick

module QueryObject 
    class AllocatedBudgetQuery 

    def self.call(filters = {}, relation = ::AllocatedBudget.all) 
     new(filters, relation).tap(&:call) 
    end 

    # filter can have the key/value as follow (key are symbols) : 
    # place_id/string 
    # current_fiscal_year/boolean 
    # budget_state/['A', 'V', '*'] 
    def initialize(filters = {}, relation = ::AllocatedBudget.all) 
     @relation  = relation 
     @filters  = filters 
    end 

    def call 
     conditions = { 
     budget_previsionnel: { supprime: 'false' }, 
     budget: { supprime: 'false' } 
     } 

     # place filter 
     conditions = conditions.merge(immeuble: { id: @filters[:place_id] }) if @filters.key?(:place_id) 

     # situation budget filter 
     conditions = conditions.merge(situation_budget: { codesituation: @filters[:budget_state] }) if @filters.key?(:budget_state) 

     # main extract 
     @relation = @relation.joins(:account_code, 
            account_code: [:place], 
            budget: %i[fiscal_year budget_state]) 
          .where(conditions) 

     # current fiscal year filter 
     @relation = @relation.where("#{Date.today.to_s} between exercice_comptable.datedebutexercice and exercice_comptable.datefinexercice") if @filters.key?(:current_fiscal_year) 
    end 
    end 
end 
1

私はwhereに全体のハッシュを渡して、純粋なRubyコード

  • を使用して、すべての条件のハッシュを作成して2つの段階

    1. に問題を破ります。

    したがって、ステップ1は次のようなものです。

    same_conditions_list = [ 
        :plan_comptable, 
        :budget, 
        :situation_budget, 
        :budget_previsionnel, 
        :exercice_comptable 
    ] 
    
    same_conditions_key_values = same_conditions_list.inject({}) do |conditions, condition| 
        conditions[condition] = { supprime: 'false' } 
        conditions 
    end 
    
    same_conditions = Hash[same_conditions_key_values]  
    
    all_conditions = same_conditions.merge({ 
        immeuble: { id: "place.id" } 
    })  
    

    そのall_conditions後Finaly私はの溶液をミックスしたデザインパターン「クエリオブジェクト」を試してみました。この

    { 
        :plan_comptable=>{:supprime=>"false"}, 
        :budget=>{:supprime=>"false"}, 
        :situation_budget=>{:supprime=>"false"}, 
        :budget_previsionnel=>{:supprime=>"false"}, 
        :exercice_comptable=>{:supprime=>"false"}, 
        :immeuble=>{:id=>"place.id"} 
    } 
    

    は次に、2つだけの

    ::AllocatedBudget.joins(:account_code, :budget, account_code: [:place], 
             budget: [:fiscal_year, :budget_state]) 
            .where(all_conditions) 
    
  • +0

    うわーは素晴らしいね!私はそれと一緒に遊ぶつもりだし、私は戻って私のフィードバックを与えるために戻ってくる! Thx Andrew! –