No commit activity in last 3 years
No release in over 3 years
Where Conditioner allows you to write conditional `where` expressions in a DRY manner.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 3.0.0.beta

Runtime

>= 4.0.0
 Project Readme

where_conditioner

Here at Amitree, we've found that some of our controllers end up with a lot of duplication stemming from the fact that where is being invoked conditionally:

purchases = Purchase.all
purchases = purchases.where('start_date > ?', params[:start_date])
  if params[:start_date].present?

The where_conditioner gem allows us to write more simply:

purchases = Purchase.all
  .where_if_present('start_date > ?', params[:start_date])

See more details on our blog: http://thesource.amitree.com/2014/04/where-conditioner.html.

Installation

Simply add to your Gemfile:

gem 'where_conditioner'

Usage

where_if_present

...with a parameterized SQL string

Apply the conditions if all parameters are non-nil:

start_date = Date.yesterday
end_date = nil
Purchase.all.where_if_present('date BETWEEN ? and ?', start_date, end_date)
 # => Purchase.all

start_date = Date.yesterday
end_date = Date.today
Purchase.all.where_if_present('date BETWEEN ? and ?', start_date, end_date)
 # => Purchase.where('date BETWEEN ? and ?', start_date, end_date)

...with a hash

Apply only those conditions where the value is non-nil:

status = 'shipped'
customer_id = nil
Purchase.all.where_if_present(status: status, customer_id: customer_id)
 # => Purchase.all.where(status: 'shipped')

if

show_pending = false
Purchase.all
  .if(!show_pending)
    .where(status: 'shipped')
 # => Purchase.all.where(status: 'shipped')

show_pending = true
Purchase.all
  .if(!show_pending)
    .where(status: 'shipped')
 # => Purchase.all

unless

Like if, but the opposite! :)

show_pending = false
Purchase.all
  .unless(show_pending)
    .where(status: 'shipped')
 # => Purchase.all.where(status: 'shipped')

show_pending = true
Purchase.all
  .unless(show_pending)
    .where(status: 'shipped')
 # => Purchase.all

else

wacky_order = false
Purchase.all
  .if(wacky_order)
    .order(customer_id: :desc)
  .else
    .order(:date)
 # => Purchase.all.order(:date)

Passing blocks

If the result of a condition is more than one method call, you can pass in a block instead:

recent = false
Purchase.all
  .if(recent) { where('date > ?', 30.days.ago).order(date: :desc) }
  .else { where.not('date > ?', 30.days.ago).order(:date) }