Reputation: 151
I would like to be able to search orders by id or by order status. My current code is working but not 100%.
There is a has_many relationship between the Order and the Order Status models. The order status model has four entries: 1.Processing , 2.Completed, 3.Cancelled, 4.Refunded
Example:
I have a simple form to enter the order id and another form with a select tag with all the Order Statuses to search by order status.
If I search for order id 1, I get all the orders with a number 1 in the id and I also get all the orders with order status 1.
I would like get a result of either order id or order status.
Order model
class Order < ActiveRecord::Base
belongs_to :order_status
def self.search(search)
where("cast(id as text) LIKE ? OR order_status_id LIKE ? ", "%#{search}%", "%#{search}%")
end
end
Order Status model
class OrderStatus < ActiveRecord::Base
has_many :orders
end
Orders Controller
def index
@order_statuses = OrderStatus.all
if params[:search]
@orders = Order.search(params[:search])
else
@orders = Order.all
end
end
Order index view
<div class="row">
<div class="col-sm-6 form-group">
<%= form_tag orders_path, :method => 'get', class:"" do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil, class:"btn btn-primary" %>
</p>
<% end %>
</div>
<div class="col-sm-6 form-group">
<%= form_tag orders_path, :method => 'get', class:"" do %>
<p>
<%= select_tag :search, options_from_collection_for_select(OrderStatus.all, :id, :name, params[:search]) %>
<%= submit_tag "Search", :name => nil, class:"btn btn-primary" %>
</p>
<% end %>
</div>
</div>
<table class="table">
<tr>
<th>Order Id</th>
<th>amount</th>
<th>status</th>
<th>Last Updated</th>
<th>manage</th>
</tr>
<% @orders.each do |order| %>
<tr>
<td><%= order.id %></td>
<td><%= order.total %></td>
<td><%= order.order_status.name %></td>
<td><%= order.updated_at %></td>
<td><%= link_to 'details', order %> |
<%= link_to 'edit', edit_order_path(order) %> |
<%= link_to 'delete', order_path(order), method: :delete, data: { confirm: 'Are you sure?' } %>
</td>
</tr>
<% end %>
<tr><td colspan="4"></td></tr>
</table>
I've researched the following links but I'm not finding or understanding a solution.
Links:
http://railscasts.com/episodes/37-simple-search-form?autoplay=true
http://railscasts.com/episodes/111-advanced-search-form-revised?autoplay=true
http://guides.rubyonrails.org/active_record_querying.html
Build static dropdown menu for simple search Rails 3
Upvotes: 0
Views: 1248
Reputation: 36211
There's no need to cast the id into text and then using like to match it. This should be enough to get what you need.
class Order < ActiveRecord::Base
belongs_to :order_status
def self.search(search)
where("id = ? OR order_status_id LIKE ? ", search, "%#{search}%")
end
end
Upvotes: 0
Reputation: 4639
You can do a search by either order_id
or order_status :name
attribute with the following
class Order < ActiveRecord::Base
belongs_to :order_status
def self.search(query)
query.to_s.is_i? ? where(id: query) : joins(:order_status).where('order_statuses.name LIKE ?', "%#{query}%")
end
end
In order to use the is_i?
method you will need to extend the String class by creating an initializer file to require a new String
extension file
# config/initializers/core_extensions.rb
Dir[File.join(Rails.root, "lib", "core_extensions", "*.rb")].each {|f| require f }
and then create your new String
extension file and is_i?
method
# lib/core_extensions/string.rb
class String
def is_i?
/\A[-+]?\d+\z/ === self
end
end
credit this SO answer for the is_i?
method
Upvotes: 2