random_user_0891
random_user_0891

Reputation: 2071

remove empty params from url

I have an 'advanced search' feature in my rails app where users can filter results. the page is located at https://myurl/users/search. The search form filter is working fine and it redirects to https://myurl/users which is the index page showing the filtered results.

My only concern is that the url gets populated with all of the empty parameters when there are no values chosen by the user for those parameters like this https://myurl/users?cert=CCNA&ed=&ex=&job=NetworkEng&lang=&maj=&s=&u=

what I would like to see is just the params that have a value. For example https://myurl/users?cert=CCNA&job=NetworkEng

here is an example of what I have in my view. This will create a button with the search term in it that the user selected and when they click on the button that particular search filter is removed.

I would like to only have the params that the user actually has populated show in the url if possible and hide all of the others. I'm thinking that maybe i have to use hidden_field_tag somehow or possibly check that each value is present before showing in the link_to?

currently if i do not list all of the params in the link_to then when a user clicks on a button to remove one search filter they all get removed.

<% if params[:job].present? %>
  <%= link_to  users_path( c: params[:c], ex: params[:ex], s: params[:s], sk: params[:sk], lang: params[:lang], 
                           cert: params[:cert], u: params[:u], relo: params[:relo], ed: params[:ed], maj: params[:maj], user_search: params[:user_search] ) , class: "btn btn-outline-danger" do %>
    <i class="fa fa-times"></i> <%= "#{params[:job]}"  %>
  <% end %>        
<% end %>      

<% if params[:user_search].present? %>
  <%= link_to  users_path( c: params[:c], ex: params[:ex], s: params[:s], sk: params[:sk], lang: params[:lang], 
                           cert: params[:cert], u: params[:u], relo: params[:relo], ed: params[:ed], maj: params[:maj], job: params[:job] ) , class: "btn btn-outline-danger" do %>
    <i class="fa fa-times"></i> <%= "#{params[:user_search]}"  %>
  <% end %>        
<% end %>   

example of what's in my users_controller

  if params[:user_search].present? 
    @users = @users.by_keyword(params[:user_search])
  end 

example of scopes in my user model

  scope :by_will_relocate, ->(relo) { where(will_relocate: true).order(updated_at: :desc) if relo.present? }
  scope :by_current_job_title, ->(job) { where('current_job_title LIKE ?', "%#{job}%").order(updated_at: :desc) if job.present? }

   scope :by_keyword, ->(k) { by_skill(k) | by_language(k) | by_certification_or_cert_authority(k) | by_education_level(k) | by_university_major(k)}

Upvotes: 1

Views: 728

Answers (1)

mu is too short
mu is too short

Reputation: 434985

Your problem is that you're extracting keys from params without regard for their values or whether they're specified or not:

c: params[:c], ex: params[:ex], s: params[:s], sk: params[:sk], lang: params[:lang], cert: params[:cert], u: params[:u], relo: params[:relo], ed: params[:ed], maj: params[:maj]

If you want to ignore things that aren't specified then use slice:

params.to_unsafe_h.slice(:c, :ex, :s, :sk, :lang, :cert, :u, :relo, :ed, :maj)
params.to_unsafe_h.slice(*%i[c ex s sk lang cert u relo ed maj])

Just to be safe, you might want to also remove values that there but explicitly nil:

base = params.to_unsafe_h
             .slice(*%i[c ex s sk lang cert u relo ed maj])
             .select { |_, v| !v.nil? }

Then when you're building your links, merge in the extras:

<% if params[:job].present? %>
  <%= link_to users_path(base.merge(user_search: params[:user_search])), class: "btn btn-outline-danger" do %>
    <i class="fa fa-times"></i> <%= "#{params[:job]}"  %>
  <% end %>        
<% end %>

This also cleans up the duplication in your users_path calls by putting all that commonality into base.

You could also use params.permit(:c, :ex, ...) rather than params.to_unsafe_h but you're filtering them anyway it doesn't matter that much.

Also, are you sure you have the :user_search and :job parameters added to the right links? Seems that your first conditional would include job: params[:job] rather than user_search: params[:user_search].

Upvotes: 0

Related Questions