2017-09-04 57 views
0

我遇到了軌道中的示波器問題。目前我在索引控制器中有一個case語句,它導致應用程序要麼過濾1個類別另一個類別。 但我需要能夠一次過濾多件事。基本上,鏈接範圍是這樣,當用戶點擊鏈接A時,範圍A被應用,然後當他們點擊鏈接B時,範圍B被添加到範圍A之上以進行更多的過濾。最終,我想在視圖中添加一個複選框,以便在檢查範圍應用時以及未選中時刪除範圍。使用示波器過濾導軌中的結果5

我有一堆條件邏輯(if \ else)語句,我現在使用,因爲我不僅需要過濾說「經驗」,我需要篩選4種不同的體驗選項(0 - 2年,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 />   

這裏是我的控制器的索引操作,我認爲需要改變發生,以便一次應用多個範圍。

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

所以我最終使用的幾種答案的組合。感謝奧斯卡解釋關於分頁直到最後,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 

在我看來,我已經加入了經驗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實現可能被立即執行查詢,結果不會是,你可以在應用範圍進一步的Active Record對象。

0

問題:

目前不工作的原因是你沒有保存當前的過濾器/範圍。如果你點擊第二個過濾器,你不知道之前渲染的範圍。

要解決此問題,您需要將過濾器存儲在客戶端上,並在下一個請求中將其作爲參數發送。這通常在URL中完成,這樣您可以使用篩選器共享網站。如果有其他人前往鏈接,過濾器會自動跳到正確的位置。但它也可以通過cookie來完成。

例如看一看:

我知道他們可能是外語你(荷蘭),但仔細看在打開和關閉過濾器時在URL欄處。過濾器會保存下來,並隨着下一個請求傳遞。

一個更多鈔票的解決方案:

目前您創建了一個專門的路線的過濾器,我的猜測是:

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

你應該做的就是使用jobs_path與像PARAMS so(view):

如果你想一個新的過濾器,你必須先提取以前的過濾器過濾器之前的組合

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

這將生成的URL。這是在控制器完成,像這樣:

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

,用於組合@filters您要應用或刪除(app/helpers/jobs_helper.rb)過濾器創建一個輔助方法。下面的示例可以打開和關閉過濾器並支持多個過濾器,但對於給定的過濾器而言,不是多個值。如果您希望支持每個過濾器的多個值,請以此爲例並根據您的喜好進行編輯。

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 

這將留給你一個視圖這樣的:

<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> 

此時接收你把所有的過濾器在變量@filters控制器的請求時,但仍然需要處理它們。查看下面的在線資源以查看示例。

在線幫助和資源:

這裏是關於一個博客帖子是如何實現一個簡單的版本(處理輸入的過濾器和調用正確的範圍):

但是你也可以嘗試找到合適的工作,下面是我發現的一個快速的Google search