2014-02-05 3 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])

I не проверял это, но я думаю, что он должен сделать трюк. Дайте мне знать, если это не так!

+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 Код не самый лучший, но вы можете улучшить его. с этим камнем. Вы даже можете создать новый класс, который будет отвечать за поиск сообщений и использование этого класса в вашем контроллере.

 Смежные вопросы

  • Нет связанных вопросов^_^