2014-02-05 50 views
4

我有一個名爲Post類,我需要能夠適應以下情況:如果用戶選擇一個類別處理多個過濾器(PARAMS)乾淨利落地控制

  • ,只顯示從該類別的職位
  • 如果用戶選擇一個類型,只顯示與該類型
  • 帖子如果用戶選擇一個類別,類型,只顯示從該類別的職位與該類型
  • 如果用戶選擇了什麼,顯示所有帖子

我想知道,如果它是不可避免的,我的控制器只是去看看毛一噸的條件句...這裏是我在處理這一缺陷的方法 - 沒有人知道我能做到這一點?

class PostsController < ApplicationController 

    def index 
    @user = current_user 

    # If a user has not specified a type or category, 
    # show them everything 
    @posts = Post.all 

    # If a user has selected a category, but no type, only 
    # show posts from that category. 
    if params[:category] && !params[:type] 
     category = Category.find(params[:category]) 
     @posts = @category.posts 
    end 

    # If a user has selected a category and a type, only show 
    # posts from that category with that type 
    if params[:category] && params[:type] 
     category = Category.find(params[:category]) 
     type = params[:type] 
     @posts = category.posts.where(post_type: type) 
    end 

    # If a user has selected a type but not a category, show all 
    # of the posts with that type 
    if params[:type] && !params[:category] 
     type = params[:type] 
     @posts = Post.where(post_type: post_type) 
    end 
    end 

end 

回答

8

你最好遵循「胖模型,瘦身控制器」的慣例,這意味着你應該把這種邏輯放在模型本身。該Post類應該能夠報告哪些職位符合您的條件,所以你可以定義這樣做的方法:

class Post < ActiveRecord::Base 
    ... 
    def self.by_category_and_type(category = nil, type = nil) 
    return where(category: category, type: type) if category && type 
    return where(category: category) if category 
    return where(type: type) if type 
    all 
    end 
    ... 
end 

然後在你的控制器,你可以叫

@posts = Post.by_category_and_type(params[:category], params[:type])

我還沒有測試過這個,但我認爲它應該做到這一點。讓我知道如果它不是!

+1

Cheezus!這絕對是我們應該使用的模式。 – goo

0

你可以重構你的代碼有點像這樣:

控制器:

def index 
    @user = current_user 
    @posts = find_posts 
    end 

    private 

    def category 
    Category.find(params[:category]) 
    end 

    def find_posts 
    if type = params[:type] 
     if params[:category] 
     category.posts.of_type(type) 
     else 
     Post.of_type(type) 
     end 
    elsif params[:category] 
     category.posts 
    else 
     Post.all 
    end 
    end 

範圍添加到您的Post模型,將其命名爲你喜歡:

scope :of_type, ->(type) { where(post_type: type) }

我建議你使用https://github.com/voxdolo/decent_exposure 上面的代碼不是最好的,但你可以改進它w ith這顆寶石。 你甚至可以創建一個新的類,它將負責發現帖子並在你的控制器中使用這個類。