Reputation: 149
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
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