Search code examples
ruby-on-railssearchkick

Rails+Searchkick search on empty params


I am trying to create a document management system where the user can search for documents by subject or by date. It works fine when both parameters have values or both are empty. But when one is empty, things start to go awry.

I use params[:search] to search through the subject field while params[:date_filter] is used for the date fields.

Case 1: params[:search] is empty, params[:date_filter] is present. Search returns nothing.

Case 2: params[:search] is present, params[:date_filter] is empty. Search results in ArgumentError invalid date

While I think I can fix these problems by putting them inside nested if clauses, I would like to ask for help if there is a more elegant solution especially if I consider that more parameters would mean more if clauses.

Here is the code I'm using in my controller:

if params[:search].present? || params[:date_filter].present?

  @ingoing = Document.search(
    params[:search], 
    where: {
      outgoing: false,
      date: {
        gte: DateTime.strptime(params[:date_filter], '%m/%d/%Y %l:%M %p').beginning_of_day, 
        lte: DateTime.strptime(params[:date_filter], '%m/%d/%Y %l:%M %p').end_of_day
      } 
    }, 
    order: {created_at: :desc} )
  @outgoing = Document.search(
    params[:search], 
    where: {
      outgoing: true,
      date: {
        gte: DateTime.strptime(params[:date_filter], '%m/%d/%Y %l:%M %p').beginning_of_day, 
        lte: DateTime.strptime(params[:date_filter], '%m/%d/%Y %l:%M %p').end_of_day
      } 
    }, 
    order: {created_at: :desc} )
else
  @documents = Document.all
  @ingoing = @documents.where(outgoing: false).order('created_at desc')
  @outgoing = @documents.where(outgoing: true).order('created_at desc')
end

Update: Used a modified version of @CupawnTae's code to solve the problem

search = params[:search].present? ? params[:search] : "*"
#where = {order: {created_at: :desc}} 
#This kept throwing an unknown where operand error so I changed it
#Also can't put misspellings: false here since it keeps returning empty results
where = {}

if params[:date_filter].present?
  where[:date] = {
    gte: DateTime.strptime(params[:date_filter], '%m/%d/%Y %l:%M %p').beginning_of_day,
    lte: DateTime.strptime(params[:date_filter], '%m/%d/%Y %l:%M %p').end_of_day
  }
end

#Put the order here,  as well as the misspelling option since putting it at the top returned empty results.
@ingoing = Document.search( search, where: where.merge(:outgoing => false), order: {created_at: :desc}, misspellings: false )
@outgoing = Document.search( search, where: where.merge(:outgoing => true), order: {created_at: :desc}, misspellings: false )

Solution

  • How about something like this?

    search = params[:search].present? ? params[:search] : "*"
    where = {order: {created_at: :desc}}
    
    if params[:date_filter].present?
      where[:date] = {
        gte: DateTime.strptime(params[:date_filter], '%m/%d/%Y %l:%M %p').beginning_of_day,
        lte: DateTime.strptime(params[:date_filter], '%m/%d/%Y %l:%M %p').end_of_day
      }
    end
    
    @ingoing = Document.search search, where: where.merge(:outgoing => false)
    @outgoing = Document.search search, where: where.merge(:outgoing => true)