Select data through query-obzekt:
app/controllers/movies_controller.rb :
class MoviesController < ApplicationController def index @movies = MoviesQuery.new(movies_query_params, Movie.all) end private def movies_query_params params.permit(:ratings, :sort_by) end end
app/queries/movies_query.rb :
class MoviesQuery < ApplicationQuery action :filter_by_ratings, :sort_by_attribute def filter_by_ratings return unless query_params[:ratings].present? where(rating: query_params[:ratings].each_key.to_a) end def sort_by_attribute return unless query_params[:sort_by].in?(%w(created_at title rating)) order(query_params[:sort_by]) end end
app/queries/application_query.rb - this file does not change, you can copy it from project to project, and inherit from it already project query objects:
class ApplicationQuery < SimpleDelegator attr_accessor :query_params def initialize(query_params, relation) @query_params = query_params self.relation = relation apply_actions end class_attribute :actions class << self def action(*args, &block) if block_given? actions << block elsif args.first.is_a?(Array) actions.push(*args.first) else actions.push(*args) end end def remove_action(action) actions.delete(action) end def actions @actions ||= [] end end private attr_reader :relation def relation=(value) @relation = value __setobj__(@relation) end def apply_actions self.actions.each do |action| self.relation = evaluate_action(action) || relation end end def evaluate_action(action) if action.is_a?(Proc) instance_eval(&action) else send(action.to_sym) end end end
config/application.rb - for the rail to see the ruby files in the queries folder - add it to the autoload_paths :
module YourApp class Application < Rails::Application config.autoload_paths += %W( #{config.root}/app/queries ) end end