首页 > 解决方案 > 如何重构这组庞大的 if 语句?

问题描述

我有以下有效的代码,但我希望它更加干燥和优雅。感觉很丑,有很多代码气味。

理想情况下,我不想使用 CASE 语句,因为这也不太像红宝石。

if @property_status.eql? :rent
  if @property_type.eql? :residential
    @results = @search.results.for_rent.residential.order("#{ @sort_by } #{ @sort_order }").all.paginate(page: @page, per_page: @per_page)
  elsif @property_type.eql? :commercial
    @results = @search.results.for_rent.commercial.order("#{ @sort_by } #{ @sort_order }").all.paginate(page: @page, per_page: @per_page)
  else
    @results = @search.results.for_rent.order("#{ @sort_by } #{ @sort_order }").all.paginate(page: @page, per_page: @per_page)
  end
elsif @property_status.eql? :sale
  if @property_type.eql? :residential
    @results = @search.results.for_sale.residential.order("#{ @sort_by } #{ @sort_order }").all.paginate(page: @page, per_page: @per_page)
  elsif @property_type.eql? :commercial
    @results = @search.results.for_sale.commercial.order("#{ @sort_by } #{ @sort_order }").all.paginate(page: @page, per_page: @per_page)
  else
    @results = @search.results.for_sale.order("#{ @sort_by } #{ @sort_order }").all.paginate(page: @page, per_page: @per_page)
  end
else
  @results = @search.results.order("#{ @sort_by } #{ @sort_order }").all.paginate(page: @page, per_page: @per_page)
end

想法?

标签: ruby-on-railsruby-on-rails-3ruby-on-rails-3.2refactoringdry

解决方案


首先认识到这一点:

@results = @search.results.for_rent.residential.order("#{ @sort_by } #{ @sort_order }").all.paginate(page: @page, per_page: @per_page)

相当于:

@results = @search.results
@results = @results.for_rent
@results = @results.residential
@results = @results.order(@sort_by => @sort_order).paginate(page: @page, per_page: @per_page)

假设@sort_by并且@sort_order总是设置当然。重要的是您可以逐个构建查询,并根据您的实例变量选择要添加的部分。您可以添加几个简单的助手:

def add_property_status_to(query)
  case @property_status
  when :rent, :sale
    query.public_send("for_#{@property_type}")
  else
    query
  end
end

def add_property_type_to(query)
  case @property_type
  when :residential, :commercial
    query.public_send(@property_type)
  else
    query
  end
end

然后这样说:

query = @search.results
query = add_property_status_to(query)
query = add_property_type_to(query)

@results = query.order(@sort_by => @sort_order).paginate(page: @page, per_page: @per_page)

您可以将add_property_status_toandadd_property_type_to方法视为本地单次使用范围。如果您需要在多个地方使用它们,那么您可以将它们设为类方法,@search.results并说出以下内容:

query = @search.results
query = query.with_property_status(@property_status)
query = query.with_property_type(@property_type)

@results = query.order(@sort_by => @sort_order).paginate(page: @page, per_page: @per_page)

推荐阅读