Skip to content

amitree/where_conditioner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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) }

About

A Rails gem for DRYing up conditional where() expressions

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages