2017-09-04 4 views
0

私はレールのスコープに関する問題に遭遇しています。現在のところ、私は、いずれかのカテゴリまたは別のカテゴリにフィルタリングするアプリケーションを引き起こしているインデックスコントローラのケースステートメントがあります。 しかし、私は一度に複数のものをフィルタリングできる必要があります。基本的にスコープをチェーンするため、ユーザーがリンクAをクリックするとスコープAが適用され、リンクBをクリックするとスコープBがスコープAの上に追加され、さらにフィルタリングされます。最終的には、ビューにチェックボックスを追加して、スコープが適用されていることがチェックされ、スコープが選択解除されている場合はスコープが削除されます。スコープを使用して結果をフィルタリングする5

私は、経験を4つの異なるオプション(0-2歳)でフィルタリングする必要があるという理由で、フィルタリングする必要がないため、私が今使用している一連の条件付きロジック(if \ else) 、2〜5年、5〜10年など)。これはすべてのスコープで同じです。

要約すると、フィルタが適用され続ける(フィルタA +フィルタB +フィルタC ...など)ようにスコープを連鎖させる方法を見つける必要があります。フィルタAまたはフィルタBを使用することはできませんが、両者を連携させて結果を絞り込むことはできません。ここ

は、ここに私のスコープ

scope :by_experience, -> (ex) { where(experience: ex) } 

scope :by_num_days_past, -> (days_past) { where('created_at >= ?', days_past.days.ago) } 

ある私の見解

            <!-- toggle for experience -->   
            <a class="" role="" data-toggle="collapse" 
href="#experience-collapse" aria-expanded="false" aria- 
controls="experience-collapse"> 
                Experience<br /> 
            </a> 
            <div class="collapse" id="experience-collapse"> 
              <div class="well"> 
                <%= link_to "0-2 years", filtered_jobs_path(:experience, '0-2 years') %><br /> 
                <%= link_to "2-5 years", filtered_jobs_path(:experience, '2-5 years') %><br /> 
                <%= link_to "5-10 years", filtered_jobs_path(:experience, '5-10 years') %><br /> 
                <%= link_to "10+ years", filtered_jobs_path(:experience, '10+ years') %>         
              </div> 
            </div>   
            <br />             

            <!-- toggle for num_days_past -->   
            <a class="" role="" data-toggle="collapse" href="#num-days- 
past-collapse" aria-expanded="false" aria-controls="num-days-past- 
collapse"> 
                Days Listed<br /> 
            </a> 
            <div class="collapse" id="num-days-past-collapse"> 
              <div class="well"> 
                <%= link_to "7 days", filtered_jobs_path(:num_days_past, '7') %><br /> 
                <%= link_to "30 days", filtered_jobs_path(:num_days_past, '30') %><br /> 
                <%= link_to "60 days", filtered_jobs_path(:num_days_past, '60') %><br /> 
              </div> 
            </div>   
            <br />   

は、ここで私は変更がために場所を取るために必要だと思い、私のコントローラのindexアクションですさ一度に複数のスコープが適用されます。

def index 

      case params[:scope]   
      when "num_days_past" 
        if (params[:format] == "7") 
          @jobs = Job.by_num_days_past("7").paginate(page: params[:page], per_page: 5)      
        elsif (params[:format] == "30") 
          @jobs = Job.by_num_days_past("30").paginate(page: params[:page], per_page: 5)      
        elsif (params[:format] == "60") 
          @jobs = Job.by_num_days_past("60").paginate(page: params[:page], per_page: 5)   
      else 
              @jobs = Job.order('created_at DESC').paginate(page: params[:page], per_page: 5)         
         end       
end 

答えて

0

は、だから私は答えのいくつかの組み合わせを使用して終了しました。最後までページ分割を保留することについてOscarに説明してくれたAhmandは、連鎖に関する情報をくれてありがとう、Johanはjobs_pathパラメータについて説明してくれてありがとう。私は投票をするだろうが、私は十分な報酬ポイントをまだ持っていないと言います。将来誰かがこの問題に遭遇した場合に備えて、私の答えを投稿してください。

コントローラーでは、まずJob.allでスコープを作成し、最後にページネーションを適用します。私はこのすべてをモデルのメソッドに移動し、コントローラから呼び出す必要があるように感じます。しかし、それはそのままの形で動作しているので、後でモデルに移動してテストします。私の見解では

def index 
    @jobs = Job.all 

    # scopes 
    if params[:experience].present? 
    @jobs = @jobs.by_experience(params[:experience]) 
    end 


    if params[:num_days_past].present? 
    @jobs = @jobs.by_num_days_past(params[:num_days_past].to_i) 
    end  


    @jobs = @jobs.paginate(page: params[:page], per_page: 5) 
end 

パラメータが存在する場合、URLは日によって経験とフィルタの両方を表示するように私はリンクに経験のparamsを追加しました。私が以前持っていたスコープ:

 <div class="well"> 
      <%= link_to "7 days", filtered_jobs_path(num_days_past: '7', experience: params[:experience]) %><br /> 
      <%= link_to "30 days", filtered_jobs_path(num_days_past: '30', experience: params[:experience]) %><br /> 
      <%= link_to "60 days", filtered_jobs_path(num_days_past: '60', experience: params[:experience]) %><br /> 
     </div> 

はここでここ

# scopes to filter results from database. 
scope :by_created_at, -> { order(created_at: :desc) } 
scope :by_experience, -> (ex) { where(experience: ex) if ex.present? } 
scope :by_num_days_past, -> (days_past) { where('created_at >= ?', days_past.days.ago) if days_past.present? } 
scope :by_location, -> (location) { where('city LIKE ? OR state LIKE ?', "%#{location}%", "%#{location}%") } 

は私のルートですスコープと私のモデルだ、私は/ファイラ/を削除しました。

#get 'jobs/filter/:scope' => 'jobs#index', as: :filtered_jobs 
    get 'jobs' => 'jobs#index', as: :filtered_jobs 
0

インスタンス変数で複数のスコープを呼び出すと、それらが連結されます。以下を試してください:

def index 

    @jobs = Job.by_num_days_past("7") if (params[:format] == "7")  
    @jobs = @jobs&.by_num_days_past("30") || Job.by_num_days_past("30") if (params[:format] == "30")   
    @jobs = @jobs&.by_num_days_past("60") || Job.by_num_days_past("60") if (params[:format] == "60")   
    @jobs = Job.order('created_at DESC') if @jobs.blank? 
    @jobs.paginate(page: params[:page], per_page: 5) 

end 
0

スコープの適用が完了するまで、ページングを遅らせることができます。これと同じように:

def index 
    case params[:scope] 
    when "num_days_past" 
    if (params[:format] == "7") 
     @jobs = Job.by_num_days_past("7") 
    elsif (params[:format] == "30") 
     @jobs = Job.by_num_days_past("30") 
    elsif (params[:format] == "60") 
     @jobs = Job.by_num_days_past("60") 
    else 
     @jobs = Job.all 
    end 

    # Now you can apply scope 2 
    # For example 
    @jobs = @jobs.by_experience(params[:exp]) if params[:scope_by_experience] 

    @jobs = @jobs.order('created_at DESC').paginate(page: params[:page], per_page: 5)   
end 

#paginate実装は即座にクエリを実行する可能性があり、結果はあなたがさらにスコープを適用することができますアクティブレコードオブジェクトではありません。

0

問題:

それが現在動作しない理由は、あなたが現在のフィルタ/スコープを保存しないです。 2番目のフィルタをクリックすると、以前レンダリングされたスコープがわかりません。

この問題を解決するには、クライアントにフィルタを保存して、次のリクエストでそれをparamとして送信する必要があります。これは一般にURLで行われます。この方法で、ウェブサイトをフィルタと共有することができます。他の誰かがリンクに行くと、フィルターは自動的に正しい位置にジャンプします。しかし、それはまた、クッキーを通じて行うことができます。見てみましょうたとえば

私は、彼らはあなた(オランダ)に外国語であってもよいが、近くで見るがかかる場合があります知っていますフィルタをオンまたはオフにするときにURLバーに表示されます。フィルターは保存され、次回の要求時に渡されます。

かのうソリューション:

現在あなたは、フィルタ用の専用ルートを作成し、私の推測では、次のとおりです。

resources :jobs do 
    get '/:scope/:format', on: :collection, as: :filtered, action: :index 
end 

あなたは何をすべきのようなのparamsでjobs_pathを使用していますso(ビュー):

あなたが最初に以前のフィルタを抽出する必要があり、以前のフィルタと新しいフィルタを組み合わせたい場合は

/jobs?number_of_days_past=7&experience=0-2+years 

このは、URLを生成します。これは、そのようなコントローラで行われます。

def index 
    @filters = params.permit(:number_of_days_past, :experience).to_h 
end 

は、あなたが(app/helpers/jobs_helper.rb)を適用または削除するフィルタと@filtersを組み合わせるためのヘルパーメソッドを作成します。以下の例では、フィルタのオンとオフを切り替えることができ、複数のフィルタをサポートしていますが、ではなく、特定のフィルタに対して複数の値がです。フィルタごとに複数の値をサポートする場合は、これを例として好みの値に編集してください。

def combine_filter(apply_filters) 
    apply_filters.each_with_object(@filters.deep_dup) do |(key, value), filters| 
    filters[key] == value ? filters.delete(key) : filters[key] = value 
    end 
end 

# OR, if the above did go to fast. 

def combine_filter(apply_filters) 
    # duplicate the @filters hash, this way multiple calls don't influence each other 
    filters = @filters.deep_dup 
    # loop through apply_filters (Hash) and check every filter 
    apply_filters.each do |key, value| 
    if filters[key] == value 
     # filter content was the same, toggle it off 
     filters.delete(key) 
    else 
     # filter content was not the same, replace value for this filter 
     filters[key] = value 
    end 
    end 
    # return the filters variable 
    filters 
end 

これは、このようなビューであなたを残します:あなたは、変数@filtersにすべてのフィルタを持っていますが、まだそれらを処理する必要がコントローラに要求を受信したときに、この時点で

<div class="well"> 
    <%= link_to "0-2 years", jobs_path(combine_filter(experience: '0-2 years')) %><br /> 
    <%= link_to "2-5 years", jobs_path(combine_filter(experience: '2-5 years')) %><br /> 
    <%= link_to "5-10 years", jobs_path(combine_filter(experience: '5-10 years')) %><br /> 
    <%= link_to "10+ years", jobs_path(combine_filter(experience: '10+ years')) %>   
</div> 

。下記のオンラインリソースで例を確認してください。

オンラインヘルプとリソース:

は簡易版(受信フィルタを処理し、正しいスコープを呼び出す)を実装する方法についてのブログ投稿です

しかし、あなたは仕事のための正しい宝石を探してみることもできます。ここで私は素早く見つけたものですGoogle search

関連する問題