Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The usual advice is to move logic to the model and keep the controller as lean as possible. There are different approaches for the filter method, the first one:</p> <pre><code>class Record &lt; ActiveRecord::Base def self.filter(attributes) attributes.select { |k, v| v.present? }.reduce(all) do |scope, (key, value)| case key.to_sym when :id, :zip # direct search scope.where(key =&gt; value) when :city, :state # regexp search scope.where(["#{key} ILIKE ?", "%#{value}%"]) when :order # order=field-(ASC|DESC) attribute, order = value.split("-") scope.order("#{self.table_name}.#{attribute} #{order}") else # unknown key (do nothing or raise error, as you prefer to) scope end end end end </code></pre> <p>A second approach, write a bare <code>filter</code> that only uses existing scopes:</p> <pre><code>class Record &lt; ActiveRecord::Base SUPPORTED_FILTERS = [:id, :city, ...] scope :id, -&gt;(value) { where(id: value) } scope :city, -&gt;(value) { where(city: "%#{value}%") } ... def self.filter(attributes) attributes.slice(*SUPPORTED_FILTERS).reduce(all) do |scope, (key, value)| value.present? ? scope.send(key, value) : scope end end end </code></pre> <p>For Rails 5, which now uses ActionController::Parameters, the syntax for the filter method is:</p> <pre><code>def self.filter(attributes) attributes.permit(SUPPORTED_FILTERS).to_hash.reduce(all) do |scope, (key, value)| value.present? ? scope.send(key, value) : scope end end </code></pre> <p>Models can be called from anywhere in your app, so they are re-usable and easier to test. Now the controller looks as simple as:</p> <pre><code>class RecordsController &lt; ApplicationController::Base respond_to :html, :xml def index @records = Record.filter(params) end end </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload