我有一个名为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
答案 0 :(得分:9)
你最好遵循“胖模型,瘦调控制器”的惯例,这意味着你应该把这种逻辑放在模型本身。 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 :(得分: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 上面的代码不是最好的,但你可以用这个gem来改进它。 您甚至可以创建一个新类,负责查找帖子并在您的控制器中使用此类。