4

I'm querying orders by date range. It is working now but I have the logic in the controller not in the model. I know that this should be in the model instead. I've tried several approaches but I've had no luck.

Question: What is the proper way of doing this?

I'm looking at the Rails Guides Active Record Querying section 2.2 Array Conditions: http://guides.rubyonrails.org/active_record_querying.html

Also researched several question here in Stack overflow: undefined local variable or method `params' for #<Result:0x3904b18>

undefined local variable or method `user_params' rails 4

ruby query between two date parameters

orders.rb Empty now to avoid errors

  def self.search_range

  end

orders_controller.rb

  def search_range

    @orders = Order.where("created_at >= :start_date AND created_at <= :end_date",{start_date:  params[:start_date], end_date: params[:end_date]}).order("created_at desc")

  end

search_range.html.erb Here I'm entering the date range

<div class="container-fluid events-container">
    <div class="row">
        <div class="col-sm-12">
            <h1>Orders</h1>
        </div>
    </div>
    <div class="row">
        <div class="col-sm-6 form-group">
            <%= form_tag search_range_path, :method => 'get', class:"" do %>
            <p>
                <%= text_field_tag :start_date, params[:start_date] %>
                <%= text_field_tag :end_date, params[:end_date] %>
                <%= submit_tag "Search", :name => nil, class:"btn btn-primary" %>
            </p>
            <% end %>
        </div> 

    </div>
    <table class="table">
        <tr>
            <th>amount</th>
            <th>status</th>
            <th>Last Updated</th>
            <th>Order Id</th>
            <th>manage</th>
        </tr>
        <% @orders.each do |order| %>
            <tr>            
            <td><%= order.total %></td>
            <td><%= order.order_status.name %></td>
            <td><%= order.created_at.strftime("%m/%d/%Y") %></td>
            <td><%= order.id %></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>


    <div class="row">
        <div class="col-sm-12">

            <hr>
        </div>
    </div>
</div>
Community
  • 1
  • 1
Asan
  • 151
  • 2
  • 16

1 Answers1

1

I took the liberty to also eager load the association, order_status, because in your view it looks like you are referencing that table. Here is a solid guide on eager loading.

Below should get you to your solution. Good for you for writing the correct query in your controller, and recognizing the need to refactor to your model. The below is also not tested, so let me know if it doesn't produce the results you need. The code below can also lead to errors, if the params are not valid dates, so you may want to go further to ensure it correctly handles errors.

# controller
@orders = Order.includes(:order_status).
  filter_between_dates(params[:start_date], params[:end_date]).
  recent

# model
scope :filter_between_dates, (lambda do |start_date, end_date|
  return all unless start_date.present? && end_date.present?

  where('created_at >= ? AND created_at <= ?', start_date, end_date)
end)

# Order based on created_at date.
#
# examples:
# Order.recent
# Order.recent('asc')
scope :recent, -> (default = 'desc') { order(created_at: default.to_sym) }

You could even go one step further and refactor this using the query object pattern.

# app/finders/orders/search_finder.rb
module Orders
  class SearchFinder
    attr_reader :params

    def initialize(params)
      @params = params
    end

    def execute
      Order.includes(:order_status).
        filter_between_dates(params[:start_date], params[:end_date]).
        recent
    end
  end
end

# controller
@orders = Orders::SearchFinder.new(params).execute
Justin
  • 4,922
  • 2
  • 27
  • 69
  • Thanks Justin for the life saver. I'll definitely study more about scopes. Also, thanks for the additional code. – Asan Mar 21 '16 at 01:12