Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/52.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 在控制器中干净地处理多个过滤器(参数)_Ruby On Rails_Ruby_Ruby On Rails 3_Ruby On Rails 3.1 - Fatal编程技术网

Ruby on rails 在控制器中干净地处理多个过滤器(参数)

Ruby on rails 在控制器中干净地处理多个过滤器(参数),ruby-on-rails,ruby,ruby-on-rails-3,ruby-on-rails-3.1,Ruby On Rails,Ruby,Ruby On Rails 3,Ruby On Rails 3.1,我有一个名为Post的类,我需要能够适应以下场景: 如果用户选择类别,则仅显示该类别中的帖子 如果用户选择一种类型,则仅显示该类型的帖子 如果用户选择类别和类型,则仅显示该类别中具有该类型的帖子 如果用户未选择任何内容,则显示所有帖子 我想知道我的控制器是否不可避免地会带有大量的条件句。。。这是我处理这个问题的有缺陷的方法——有人知道我如何做到这一点吗 class PostsController < ApplicationController def index @use

我有一个名为Post的类,我需要能够适应以下场景:

  • 如果用户选择类别,则仅显示该类别中的帖子
  • 如果用户选择一种类型,则仅显示该类型的帖子
  • 如果用户选择类别和类型,则仅显示该类别中具有该类型的帖子
  • 如果用户未选择任何内容,则显示所有帖子
我想知道我的控制器是否不可避免地会带有大量的条件句。。。这是我处理这个问题的有缺陷的方法——有人知道我如何做到这一点吗

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
class PostsController
遵循“胖模型,瘦控制器”的惯例会更好,这意味着您应该在模型本身中加入这种逻辑。
Post
类应该能够报告哪些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
class Post
然后,在控制器中,您可以直接调用

@posts=Post.by_category_和_type(params[:category],params[:type])


我还没有测试过这个,但我认为它应该可以。如果没有,请告诉我

您可以像这样重构代码:

控制器:

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

我建议你使用 上面的代码不是最好的,但是你可以用这个gem来改进它。
您甚至可以创建一个新类,负责查找帖子,并在您的控件中使用该类。

Cheezus!这绝对是我们应该使用的模式。