amoks
amoks

Reputation: 103

Ruby: How to write nested ifs in a concise way?

Is there a more concise way to write the following nested conditionals?

def sort_column
  if Product.column_names.include?(params[:sort])
    if params[:sort] == "price_latest" || params[:sort] == "price_average"
      "#{params[:sort]}->'#{cookies[:store_id]}'"
    else
      params[:sort]
    end
  else
    "name"
  end
end

Upvotes: 1

Views: 121

Answers (3)

Cary Swoveland
Cary Swoveland

Reputation: 110755

A linear search is required to determine if Product.column_names contains a given element. If that array is large and will not change during execution of the code, and sort_column is to be called multiple times, performance can be improved by converting that array to a set. Determining whether a set contains a given element is very fast, lookup times being comparable to those for determining if a hash has a given key.

require 'set'
names_set = Product.column_names.to_set

def sort_column(params, names_set)
  ps = params[:sort]
  return "name" unless names_set.include?(ps)
  ["price_latest", "price_average"].include?(ps) ? 
    "#{ps}->'#{cookies[:store_id]}'" : "home"
end

Upvotes: 0

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121020

With early return and case.

def sort_column
  return "name" unless Product.column_names.include?(params[:sort])

  case params[:sort]
  when "price_latest", "price_average"
    "#{params[:sort]}->'#{cookies[:store_id]}'"
  else
    params[:sort]
  end
end

Upvotes: 1

Sebastián Palma
Sebastián Palma

Reputation: 33491

You can replace the if-else conditions by guard clause, altering the statement depending on the case (if, unless):

def sort_column
  sort = params[:sort]
  return 'name' unless Product.column_names.include?(sort)
  return "#{sort}->'#{cookies[:store_id]}'" if sort.in?(%w[price_latest price_average])

  sort
end

With return name unless ... you get rid of if Product.column_names.include?(params[:sort]) else ... end.

With sort.in?(%w[price_latest price_average]) you shorten the params[:sort] == "price_latest" || params[:sort] == "price_average" condition and return #{sort}->'#{cookies[:store_id]}'" just if it returns true.

If none of the other conditions are evaluated as true, return just the value of params[:sort].

Upvotes: 2

Related Questions