Прежде всего, часть вашей логики не имеет смысла:
def search(search, compare, year, rain_fall_type)
if search == 'All'
if rain_fall_type == 'All'
all
else
# rain_fall_type != 'All'
if year == 'All'
if rain_fall_type == "None"
where('Sector = ? OR Sector = ? OR Sector = ?', "Primary", 'Secondary', 'Tertiary').order('id')
else
where(Sector: rain_fall_type).order('id')
end
else
# in rain_fall_type != 'All' branch, so meaningless 'if'
if rain_fall_type == "All"
order("#{year} ")
elsif rain_fall_type == "None"
where('Sector = ? OR Sector = ? OR Sector = ?', "Primary", 'Secondary', 'Tertiary').order('id')
else
where(Sector: rain_fall_type).order("#{year} ")
end
end
end
elsif compare != "None"
# both are same, so meaningless 'if'
if year == 'All'
where('Sector = ? OR Sector = ?', rain_fall_type, compare).order(:id)
else
where('Sector = ? OR Sector = ?', rain_fall_type, compare).order(:id)
end
else
# search != 'All'
if rain_fall_type == 'All'
all.order('id')
else
if year == 'All'
if rain_fall_type == "None"
where('Sector = ? ', search).order('id')
else
where('Sector = ? ', rain_fall_type).order('id')
end
else
if rain_fall_type == "None"
# in search != 'All' branch, so meaningless 'if'
# AND both are same, so again meaningless 'if'
if search == "All"
where('Sector = ? ', search).order('id')
else
where('Sector = ? ', search).order('id')
end
else
where('Sector = ? ', rain_fall_type).order('id')
end
end
end
end
end
Это еще не все, и я не буду указывать на это все, потому что мы все равно выкидываем все эти if
вещи.
В конечном счете, мы собираемся отложить запрос до конца метода, например:
def search(search, compare, year, rain_fall_type)
...
@query = all
@query = @query.where(Sector: @sectors) if @sectors
@query = @query.order(@order) if @order
@query
end
Таким образом, вы берете все ваших where
и order
утверждений и делаете их только один раз в конце. Это экономит много печатать прямо там. Смотрите комментарий от muistooshort о том, почему (Sector: @sectors)
работает.
Итак, трюк заключается в установке @sectors
и @order
. Во-первых, я собираюсь назначить входные переменные переменным экземпляра, потому что мне это нравится (и чтобы избежать путаницы между переменной @search
и методом search
):
def search(search, compare, year, rain_fall_type)
@search, @compare, @year, @rain_fall_type = search, compare, year, rain_fall_type
...
@query = all
@query = @query.where(Sector: @sectors) if @sectors
@query = @query.order(@order) if @order
@query
end
Так вот, этот ответ продолжается слишком долго, поэтому я не буду тащить вас через все подробности. Но, добавив пару вспомогательных методов (sectors_to_use
и order_to_use
) и подставив их вместо @sectors
и @order
, вы в итоге получите следующее:
def search(search, compare, year, rain_fall_type)
@search, @compare, @year, @rain_fall_type = search, compare, year, rain_fall_type
@query = all
@query = @query.where(Sector: sectors_to_use) if sectors_to_use
@query = @query.order(order_to_use) if order_to_use
@query
end
private
def sectors_to_use
return [@rain_fall_type, @compare] if @search != 'All' && @compare != 'None'
unless @rain_fall_type == 'All'
if @rain_fall_type == 'None'
@search == 'All' ? ['Primary', 'Secondary', 'Tertiary'] : [@search]
else
[@rain_fall_type]
end
end
end
def order_to_use
return nil if (@search == 'All') && (@rain_fall_type == 'All')
return @year if (@search == 'All') && !(@year == 'All')
return :id
end
Это меньше половины строк кода, более тысячи символов и намного меньше ifs
.