Alejandro Araujo
Alejandro Araujo

Reputation: 149

How order by selected by the users on search bar? Rails

I'm creating a customers directory with a search bar and dropdown to select how you want to order the results. The code is the following:

customers_controller.rb

  def index
    if params[:search]
      @customers = Customer.search(params[:search]).order("id DESC")
    else
      @customers = Customer.order("id DESC").all
    end
  end

customer.rb

      def self.search(query)
        where("name like ?", "%#{query}%")
        where("email like ?", "%#{query}%")
        where("username like ?", "%#{query}%") 
      end

View

<div class="row">
  <div class="col-lg-8">

    <%= form_tag(customers_path, :method => "get", id: "customer-search-form", role: "search") do %>

      <div class="input-group">
        <span class="input-group-btn">

          <%= button_tag(type: 'submit', class: "btn btn-default") do %>
            Buscar
          <% end %>

        </span>

        <%= text_field_tag :search, params[:search], class: "form-control" %>

      </div><!-- /input-group -->

    <% end %>

  </div><!-- /.col-lg-8 -->

  <div class="col-lg-4">
    <select class="form-control">
      <option>Ordenar por...</option>
      <option>Mas antiguo</option>
      <option>Mas reciente</option>
      <option>Nombre A-Z</option>
      <option>Nombre Z-A</option>
      <option>Correo A-Z</option>
      <option>Correo Z-A</option>
      <option>Usuario A-Z</option>
      <option>Usuario Z-A</option>
    </select>
  </div>
</div>

I don't have idea how to order the results.

Thanks

Upvotes: 0

Views: 458

Answers (1)

Robert Nubel
Robert Nubel

Reputation: 7522

First, your .query method has a bug -- the scopes are just repeated, not joined in any way, so it will always just be filtering on the last one. You can fix it by combining the conditions with ORs, like so:

def self.search(query)
  where(["name LIKE ? OR email LIKE ? OR username LIKE ?", query, query, query])
end

Now, for ordering, you first of all need to move the select statement inside your form, and give it a name so that it will populate into your params hash. You can use Rails form helpers for that, or just make it:

<select class="form-control" name="ordering">

Secondly, I'd give each option a unique value... possibly a numeric index, so you can reference elements from an array:

<option value="0">Ordenar por...</option>
<option value="1">Mas antiguo</option>
<option value="2">Mas reciente</option>

We're almost there! The last and trickiest step is to make that ordering parameter matter. Put a constant into your controller where each index lines up with the value of the tags, above (remember that the first element is 0, which I would make your default sort):

ORDERS = [ "id DESC", "id ASC", "id DESC", "name ASC", "name DESC" ] # etc.

Then, use that when invoking .order in your index action (I've refactored your querying to be more DRY, too):

def index
  scope = Customer

  if params[:search]
    scope = scope.search(params[:search])
  end

  if params[:ordering] && ordering = ORDERS[params[:ordering].to_i]
    scope = scope.order(ordering)
  end

  @customers = scope.all
end

Hope that helps! There might be typos in the above code, but altogether it should accomplish what you're looking to do. Let me know if any part of it needs more explaining.

Upvotes: 1

Related Questions