Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 3646

Show
Ignore:
Timestamp:
02/25/06 23:06:04 (3 years ago)
Author:
david
Message:

Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Base.maxmium, and the generic Base.calculate. All can be used with :group and :having. Calculations and statitics need no longer require custom SQL. #3958 [Rick Olson]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/CHANGELOG

    r3639 r3646  
    11*SVN* 
     2 
     3* Added calculations: Base.count, Base.average, Base.sum, Base.minimum, Base.maxmium, and the generic Base.calculate. All can be used with :group and :having. Calculations and statitics need no longer require custom SQL. #3958 [Rick Olson]. Examples: 
     4 
     5    Person.average :age 
     6    Person.minimum :age 
     7    Person.maximum :age 
     8    Person.sum :salary, :group => :last_name 
    29 
    310* Renamed Errors#count to Errors#size but kept an alias for the old name (and included an alias for length too) #3920 [contact@lukeredpath.co.uk] 
  • trunk/activerecord/lib/active_record.rb

    r3347 r3646  
    5050require 'active_record/migration' 
    5151require 'active_record/schema' 
     52require 'active_record/calculations' 
    5253 
    5354ActiveRecord::Base.class_eval do 
     
    6465  include ActiveRecord::Acts::List 
    6566  include ActiveRecord::Acts::NestedSet 
     67  include ActiveRecord::Calculations 
    6668end 
    6769 
  • trunk/activerecord/lib/active_record/base.rb

    r3637 r3646  
    496496      end 
    497497 
    498       # Count operates using three different approaches.  
    499       # 
    500       # * Count all: By not passing any parameters to count, it will return a count of all the rows for the model. 
    501       # * Count by conditions or joins: For backwards compatibility, you can pass in +conditions+ and +joins+ as individual parameters. 
    502       # * Count using options will find the row count matched by the options used. 
    503       # 
    504       # The last approach, count using options, accepts an option hash as the only parameter. The options are: 
    505       # 
    506       # * <tt>:conditions</tt>: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro. 
    507       # * <tt>:joins</tt>: An SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id". (Rarely needed). 
    508       #   The records will be returned read-only since they will have attributes that do not correspond to the table's columns. 
    509       # * <tt>:include</tt>: Named associations that should be loaded alongside using LEFT OUTER JOINs. The symbols named refer 
    510       #   to already defined associations. When using named associations count returns the number DISTINCT items for the model you're counting. 
    511       #   See eager loading under Associations. 
    512       # 
    513       # Examples for counting all: 
    514       #   Person.count         # returns the total count of all people 
    515       # 
    516       # Examples for count by +conditions+ and +joins+ (for backwards compatibility): 
    517       #   Person.count("age > 26")  # returns the number of people older than 26 
    518       #   Person.find("age > 26 AND job.salary > 60000", "LEFT JOIN jobs on jobs.person_id = person.id") # returns the total number of rows matching the conditions and joins fetched by SELECT COUNT(*). 
    519       # 
    520       # Examples for count with options: 
    521       #   Person.count(:conditions => "age > 26") 
    522       #   Person.count(:conditions => "age > 26 AND job.salary > 60000", :include => :job) # because of the named association, it finds the DISTINCT count using LEFT OUTER JOIN. 
    523       #   Person.count(:conditions => "age > 26 AND job.salary > 60000", :joins => "LEFT JOIN jobs on jobs.person_id = person.id") # finds the number of rows matching the conditions and joins.  
    524       def count(*args)  
    525         options = {} 
    526          
    527         #For backwards compatibility, we need to handle both count(conditions=nil, joins=nil) or count(options={}). 
    528         if args.size >= 0 and args.size <= 2 
    529           if args.first.is_a?(Hash) 
    530             options = args.first 
    531             #should we verify the options hash??? 
    532           else 
    533             #Handle legacy paramter options: def count(conditions=nil, joins=nil)  
    534             options.merge!(:conditions => args[0]) if args.length > 0 
    535             options.merge!(:joins => args[1]) if args.length > 1 
    536           end 
    537         else 
    538           raise(ArgumentError, "Unexpected parameters passed to count(*args): expected either count(conditions=nil, joins=nil) or count(options={})") 
    539         end 
    540          
    541         options[:include] ? count_with_associations(options) : count_by_sql(construct_counter_sql(options)) 
    542       end 
    543        
    544       def construct_counter_sql(options) 
    545         sql  = "SELECT COUNT("  
    546         sql << "DISTINCT " if options[:distinct] 
    547         sql << "#{options[:select] || "#{table_name}.#{primary_key}"}) FROM #{table_name} " 
    548         sql << " #{options[:joins]} " if options[:joins] 
    549         add_conditions!(sql, options[:conditions]) 
    550         sql 
    551       end 
    552  
    553498      # Returns the result of an SQL statement that should only include a COUNT(*) in the SELECT part. 
    554499      #   Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id" 
  • trunk/activerecord/test/fixtures/accounts.yml

    r3463 r3646  
    1717  firm_id: 2 
    1818  credit_limit: 60 
     19 
     20rails_core_account_2: 
     21  id: 5 
     22  firm_id: 6 
     23  credit_limit: 55 
  • trunk/activesupport/lib/active_support/ordered_options.rb

    r2661 r3646  
    1 class OrderedOptions < Array #:nodoc: 
    2   def []=(key, value) 
    3     key = key.to_sym 
    4      
     1class OrderedHash < Array #:nodoc: 
     2  def []=(key, value)     
    53    if pair = find_pair(key) 
    64      pair.pop 
     
    1210   
    1311  def [](key) 
    14     pair = find_pair(key.to_sym
     12    pair = find_pair(key
    1513    pair ? pair.last : nil 
     14  end 
     15 
     16  def keys 
     17    self.collect { |i| i.first } 
     18  end 
     19 
     20  private 
     21    def find_pair(key) 
     22      self.each { |i| return i if i.first == key } 
     23      return false 
     24    end 
     25end 
     26 
     27class OrderedOptions < OrderedHash #:nodoc: 
     28  def []=(key, value) 
     29    super(key.to_sym, value) 
     30  end 
     31   
     32  def [](key) 
     33    super(key.to_sym) 
    1634  end 
    1735 
     
    2341    end 
    2442  end 
    25  
    26   private 
    27     def find_pair(key) 
    28       self.each { |i| return i if i.first == key } 
    29       return false 
    30     end 
    3143end