Jackson
Jackson

Reputation: 6841

Optional Rails Params in Controller Query

I have a question in regards to Rails params. I currently have only one filter on one of my views that allows users to filter data by a date range. I am adding two more filters to that view so that users can filter by code and country. However, I want those filters to be optional.

My current query looks something like this:

@data = Games
      .where("date BETWEEN ? AND ?", *date_range_array)
      .includes(:synced_country)
      .order(sort_column + " " + sort_direction)
      .page(params[:page])

The params for code and country will be something like, params[:code] and params[:country]. I would like to put them in the query like:

  @data = Games
          .where("date BETWEEN ? AND ?", *date_range_array)
          .where("unique_code in ?" params[:code])
          .where("country in ?" params[:country])
          .includes(:synced_country)
          .order(sort_column + " " + sort_direction)
          .page(params[:page])

The issue I am having is that if the user does not input anything for params[:code] and params[:country] I get an error because they are nil. Any idea on how to handle this kind of situation?

Upvotes: 0

Views: 562

Answers (3)

peipei
peipei

Reputation: 21

I usually use the same method with Agis. But sometimes I trend to use scope(as arieljuod said):

class Games

  scope :in_contry, lambda{|contry| where("contry in ?", contry) if contry.present?}

  scope :in_code, lambda{|code| where("unique_code in ?", code) if code.present?}

  //other codes
end

//call lambdas as follows:
@data = Games.where("date BETWEEN ? AND ?", *date_range_array)
          .in_code(params[:code])
          .in_contry(params[:country])
          .includes(:synced_country)
          .order(sort_column + " " + sort_direction)
          .page(params[:page])

Upvotes: 0

Agis
Agis

Reputation: 33626

I would build it incrementally:

@data = Games.where("date BETWEEN ? AND ?", *date_range_array)

@data = @data.where("unique_code in ?", params[:code]) if params[:code]
@data = @data.where("country in ?", params[:country])  if params[:country]

@data = @data.includes(:synced_country)
             .order(sort_column + " " + sort_direction)
             .page(params[:page])

Note that you are missing two commas right before params[:code] and params[:country] which I've fixed in the above code.

Upvotes: 1

arieljuod
arieljuod

Reputation: 15838

@data = Games.where("date BETWEEN ? AND ?", *date_range_array).scoped
@data = @data.where("unique_code in ?" params[:code]).scoped if params[:code].present?
@data = @data.where("country in ?" params[:country]).scoped if params[:coutry].present?
@data = @data.includes(:synced_country)
             .order(sort_column + " " + sort_direction)
             .page(params[:page])

Anyway, I would move that complex query to a named scope or something inside the Game Model.

EDIT: added the "scoped" method, i'm not sure if needed, try it without .scoped if you want

Upvotes: 0

Related Questions