我的搜索方法被臭和肿,我需要一些帮助重构。我是Ruby的新手,我还没有弄清楚如何有效利用它,这导致了这样的方法:
# discussion.rb
def self.search(params)
# If there is a search query, use Tire gem for fulltext search
if params[:query].present?
tire.search(load: true) do
query { string params[:query] }
end
# Otherwise grab all discussions based on category and/or filter
else
# Grab all discussions and include the author
discussions = self.includes(:author)
# Filter by category if there is one specified
discussions = discussions.where(category: params[:category]) if params[:category]
# If params[:filter] is provided, user it
if params[:filter]
case params[:filter]
when 'hot'
discussions = discussions.open.order_by_hot
when 'new'
discussions = discussions.open.order_by_new
when 'top'
discussions = discussions.open.order_by_top
else
# If params[:filter] does not match the above three states, it's probably a status
discussions = discussions.order_by_new.where(status: params[:filter])
end
else
# If no filter is passed, just grab discussions by hot
discussions = discussions.open.order_by_hot
end
end
end
STATUSES = {
question: %w[answered],
suggestion: %w[started completed declined],
problem: %w[solved]
}
scope :order_by_hot, order('...') DESC, created_at DESC")
scope :order_by_new, order('created_at DESC')
scope :order_by_top, order('votes_count DESC, created_at DESC')
这是一个可以通过类别过滤(或不过滤)的讨论模型:question
,problem
,suggestion
。
所有讨论或单个类别都可以通过hot
,new
,votes
或status
进一步过滤。状态是模型中的哈希,它具有多个值,取决于类别(仅当存在params [:类别]时出现状态过滤器)。
复杂的问题是使用轮胎
的完整搜索功能但是我的控制器看起来不错且整洁:
def index
@discussions = Discussion.search(params)
end
我可以稍微将其干燥/重构,也许可以使用元编程或块?我设法将其从控制器中提取出来,但随后用完了想法。我对Ruby的了解不够好,无法进一步。
对于初学者,"基于类别和/或过滤器的所有讨论"可以是单独的方法。
params[:filter]
重复多次,因此将其取出:
filter = params[:filter]
您可以使用
if [:hot, :new, :top].incude? filter
discussions = discussions.open.send "order_by_#{filter}"
...
另外,如果其他情况否则,请考虑其他情况。我更喜欢分离单独的方法并提早返回:
def do_something
return 'foo' if ...
return 'bar' if ...
'baz'
end
discussions = discussions...
出现多次,但看起来很奇怪。您可以使用return discussions...
吗?
为什么常数STATUSES
出现在末尾?通常,常数出现在模型的顶部。
确保在重构之前写所有测试。
回应有关return 'foo' if ...
的评论:
考虑:
def evaluate_something
if a==1
return 'foo'
elsif b==2
return 'bar'
else
return 'baz'
end
end
我建议对此进行重构:
def evaluate_something
return 'foo' if a==1
return 'bar' if b==2
'baz'
end
也许您可以重构一些IF ..然后.. else..如果是语句。
推荐书:干净的代码