module BetterAr module ClassMethods # Breaks down the hash to do a {ActiveRecord::Relation} query # # example: # User.all(:age => 10, :limit! => 2, :offset! => 3, :order! => :name) # # is the same as: # User.where(:age => 10).limit(2).offset(3).order(:name) # # if the key :conditions is present it will fall back to legacy # # any key with the '!' at the end will be assumed to be a sql operator. The key should match either an {ActiveRecord::Relation} instance method or an ARel predicate. # # Implicit joins are supported. # example: # User.all(:records => {:name => 'test'}) # # is the same as: # User.joins(:records).where(:records => {:name => 'test'}) # # @param [Hash] # Optional # @return [ActiveRecord::Relation] def all(opts = {}) relation = scoped.clone unless opts.key?(:conditions) unless opts.empty? opts.keys.select { |key| key.to_s =~ /!$/ }.each do |predicate| if value = opts.delete(predicate) relation = relation.send(predicate.to_s.sub('!',''), value) end end reflect_on_all_associations.map(&:name).each do |name| if opts.key?(name) relation = relation.joins(name) end end relation.where(opts) end if opts.empty? relation else relation.where(opts) end else relation.all(opts) end end # Forces a limit of 1 on the collection # # example: # User.first(:age => 10, :name => 'Brian') # # is the same as: # User.where(:age => 10, :name => 'Brian').limit(1).first # # if the key :conditions is present it will fall back to legacy # # @param [Hash] # Optional follows same convention as {#all} # @return [ActiveRecord::Base] def first(opts = {}) unless opts.key?(:conditions) all(opts.merge(:limit! => 1)).first else scoped.first(opts) end end # Does a count on the query # # example: # User.count(:age => 20) # # is the same as: # User.where(:age => 20).count # # if the key :conditions is present it will fall back to legacy # # @param [Hash] # Optional follows same convention as {#all} # @return [Integer] def count(opts = {}) unless opts.key?(:conditions) all(opts).count else scoped.count(opts) end end end end ActiveRecord::Base.class_eval do class << self remove_method :all remove_method :first remove_method :count end end ActiveRecord::Base.send(:extend, BetterAr::ClassMethods)