class ArticlesController < ApplicationController
def index
@articles = Article.by_popularity
if params[:category] == 'popular'
@articles = @articles.by_popularity
end
if params[:category] == 'recent'
@articles = @articles.by_recent
end
if params[:category] == 'local'
index_by_local and return
end
if params[:genre]
index_by_genre and return
end
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @articles }
end
end
def index_by_local
# 10 lines of code here
render :template => 'articles/index_by_local'
end
def index_by_genre
# ANOTHER 10 lines of code here
render :template => 'articles/index_by_genre'
end
end
从上面可以看出。我的控制器不完全瘦。它的作用是,根据传递的参数,它与模型交互以过滤掉记录。
如果params[:local]
或params[:genre]
通过了。然后它分别调用自己的方法(def index_by_local
和def index_by_genre
)来进行进一步处理。这些方法也会加载自己的模板,而不是index.html.erb
。
控制器看起来很典型吗?或者我应该以某种方式重构这个?
答案 0 :(得分:1)
我们可以将前几行移到模型中(article.rb):
def get_by_category(category)
# Return articles based on the category.
end
通过这种方式,我们可以使用单元测试完全测试文章获取逻辑。
通常移动与获取模型内部记录相关的所有代码。 一般的控制器
答案 1 :(得分:1)
我将为您要使用的每个集合定义范围。
class Article < ActiveRecord::Base
...
scope :popular, where("articles.popular = ?", true) # or whatever you need
scope :recent, where(...)
scope :by_genre, where(...)
scope :local, where(...)
...
def self.filtered(filter)
case filter
when 'popular'
Article.popular, 'articles/index'
when 'recent'
Article.recent, 'articles/index'
when 'genre'
Article.by_genre, 'articles/index_by_genre'
when 'local'
Article.local, 'articles/index_by_local'
else
raise "Unknown Filter"
end
end
end
然后在你的控制器动作中,像这样:
def index
@articles, template = Article.filtered(params[:category] || params[:genre])
respond_to do |format|
format.html { render :template => template }
format.xml { render :xml => @articles }
end
end