简体   繁体   中英

Ruby .where query with optional params

I want to display all user Notes but if in params I will have params[:activity_id].present? I want to display all Notes for given activity. The whole code, which works, looks like:

get do
  ::Notes::DetailedSerializer.new(
    params[:activity_id].present? ? activity_notes : all_notes,
  )
end

def all_notes
  Note.where(user_id: current_user.id)
end

def activity_notes
  Note.where(user_id: current_user.id, activity_id: params[:activity_id])
end

So is there a way to use this .where query in one line instead of using two methods? I cannot leave only Note.where(user_id: current_user.id, activity_id: params[:activity_id]) when activity_id is nil because it will not return all Notes but Notes with actvitity_id: nil

I would suggest that you add the conditions and then return 1 value at the end.

Example:

get do
  notes = Note.where(user_id: current_user.id)

  if params[:activity_id].present?
    notes = notes.where(activity_id: params[:activity_id])
  end

  ::Notes::DetailedSerializer.new(notes)
end

That way, you can add as many parameters as you want. You can also change the params[:activity_id] into a loop of params:

get do
  notes = Note.where(user_id: current_user.id)

  %i(activity_id).each do |param|
    if params[param].present?
      notes = notes.where(param => params[param])
    end
  end

  ::Notes::DetailedSerializer.new(notes)
end

so you can loop through whatever params you want

I suggest to use the hash for query and update hash with activity id if passed in params. Then use the query hash query from database by passing it to where method. This will reduce the number of queries to database as well.

Sample:

get do
  query = {user_id: current_user.id}
  query = query.merge({activity_id: params[:activity]}) if params[:activity_id]
  ::Notes::DetailedSerializer.new(Note.where(query))
end

The above query can be further improved by using allowed params check on before filters to make it dynamic. Assuming that params related to query is always passed under key 'query' and checking if the keys in query is mapped with table fields. Need to handle the exceptions as well.

Sample:

get do
  query = {user_id: current_user.id}
  params[:query].keys.each do |key| 
     query = query.merge({key => params[key]})
  end
  ::Notes::DetailedSerializer.new(Note.where(query))
end

Better to go with first option if this is only for one key.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM