Как мне изменить этот громоздкий набор операторов if? - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть следующий код, который работает, но я бы хотел, чтобы он был более СУХИМ и элегантным.Это кажется ужасным из-за большого количества запахов кода.

В идеале я не хочу использовать операторы 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

Мысли?

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Сначала признайте, что это:

@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_to и add_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)
0 голосов
/ 03 декабря 2018

Я не проверял это, но я думаю что-то вроде:

def results
  return results_for_rent if for_rent?
  return results_for_sale if for_sale?
  default_results
end

def for_rent?
  @property_status.eql? :rent
end

def for_sale?
  @property_status.eql? :sale
end

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

def results_for_rent
  if [:residential, :commercial].includes?(@property_type)
    results(@property_type, type: :for_rent)
    return 
  end
  @results = @search.results.for_rent.commercial.order("#{ @sort_by } #{ 
  @sort_order }").all.paginate(page: @page, per_page: @per_page)
end

def results_for_sale
  if [:residential, :commercial].includes?(@property_type)
    results(kind, type: :for_sale)
    return
  end
  @results = @search.results.for_sale.order("#{ @sort_by } #{ @sort_order 
  }").all.paginate(page: @page, per_page: @per_page)
end

def results(kind:, type: )
  @results = @search.results.send(kind).send(type).order("#{ @sort_by } #{ 
  @sort_order }").all.paginate(page: @page, per_page: @per_page)
end

Вы также можете реорганизовать часть .all.pagination, которая такая же, но вы поняли идею.Вы также можете изменить методы results_for_rent и results_for_sale, добавив один аргумент

...