activerecord 3.0.0.beta2 → 3.0.0.beta3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG +11 -1
 - data/lib/active_record/associations.rb +26 -54
 - data/lib/active_record/associations/association_collection.rb +13 -2
 - data/lib/active_record/associations/association_proxy.rb +3 -1
 - data/lib/active_record/associations/through_association_scope.rb +1 -1
 - data/lib/active_record/attribute_methods/dirty.rb +6 -0
 - data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -4
 - data/lib/active_record/base.rb +66 -62
 - data/lib/active_record/callbacks.rb +4 -2
 - data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -3
 - data/lib/active_record/connection_adapters/abstract/schema_statements.rb +5 -3
 - data/lib/active_record/connection_adapters/abstract_adapter.rb +1 -0
 - data/lib/active_record/connection_adapters/postgresql_adapter.rb +45 -45
 - data/lib/active_record/migration.rb +1 -1
 - data/lib/active_record/named_scope.rb +26 -109
 - data/lib/active_record/railties/databases.rake +3 -7
 - data/lib/active_record/reflection.rb +11 -0
 - data/lib/active_record/relation.rb +20 -1
 - data/lib/active_record/relation/finder_methods.rb +18 -2
 - data/lib/active_record/relation/predicate_builder.rb +4 -2
 - data/lib/active_record/relation/query_methods.rb +26 -8
 - data/lib/active_record/relation/spawn_methods.rb +9 -6
 - data/lib/active_record/serializers/xml_serializer.rb +2 -1
 - data/lib/active_record/validations/uniqueness.rb +3 -1
 - data/lib/active_record/version.rb +1 -1
 - data/lib/rails/generators/active_record/model/model_generator.rb +5 -0
 - data/lib/rails/generators/active_record/model/templates/module.rb +5 -0
 - metadata +8 -7
 
| 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'active_support/core_ext/array/wrap'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       2 
4 
     | 
    
         
             
              # Callbacks are hooks into the lifecycle of an Active Record object that allow you to trigger logic
         
     | 
| 
       3 
5 
     | 
    
         
             
              # before or after an alteration of the object state. This can be used to make sure that associated and
         
     | 
| 
         @@ -250,7 +252,7 @@ module ActiveRecord 
     | 
|
| 
       250 
252 
     | 
    
         
             
                  def before_validation(*args, &block)
         
     | 
| 
       251 
253 
     | 
    
         
             
                    options = args.last
         
     | 
| 
       252 
254 
     | 
    
         
             
                    if options.is_a?(Hash) && options[:on]
         
     | 
| 
       253 
     | 
    
         
            -
                      options[:if] = Array(options[:if])
         
     | 
| 
      
 255 
     | 
    
         
            +
                      options[:if] = Array.wrap(options[:if])
         
     | 
| 
       254 
256 
     | 
    
         
             
                      options[:if] << "@_on_validate == :#{options[:on]}"
         
     | 
| 
       255 
257 
     | 
    
         
             
                    end
         
     | 
| 
       256 
258 
     | 
    
         
             
                    set_callback(:validation, :before, *args, &block)
         
     | 
| 
         @@ -259,7 +261,7 @@ module ActiveRecord 
     | 
|
| 
       259 
261 
     | 
    
         
             
                  def after_validation(*args, &block)
         
     | 
| 
       260 
262 
     | 
    
         
             
                    options = args.extract_options!
         
     | 
| 
       261 
263 
     | 
    
         
             
                    options[:prepend] = true
         
     | 
| 
       262 
     | 
    
         
            -
                    options[:if] = Array(options[:if])
         
     | 
| 
      
 264 
     | 
    
         
            +
                    options[:if] = Array.wrap(options[:if])
         
     | 
| 
       263 
265 
     | 
    
         
             
                    options[:if] << "!halted && value != false"
         
     | 
| 
       264 
266 
     | 
    
         
             
                    options[:if] << "@_on_validate == :#{options[:on]}" if options[:on]
         
     | 
| 
       265 
267 
     | 
    
         
             
                    set_callback(:validation, :after, *(args << options), &block)
         
     | 
| 
         @@ -15,7 +15,7 @@ module ActiveRecord 
     | 
|
| 
       15 
15 
     | 
    
         | 
| 
       16 
16 
     | 
    
         
             
                    def dirties_query_cache(base, *method_names)
         
     | 
| 
       17 
17 
     | 
    
         
             
                      method_names.each do |method_name|
         
     | 
| 
       18 
     | 
    
         
            -
                        base.class_eval <<-end_code, __FILE__, __LINE__
         
     | 
| 
      
 18 
     | 
    
         
            +
                        base.class_eval <<-end_code, __FILE__, __LINE__ + 1
         
     | 
| 
       19 
19 
     | 
    
         
             
                          def #{method_name}_with_query_dirty(*args)        # def update_with_query_dirty(*args)
         
     | 
| 
       20 
20 
     | 
    
         
             
                            clear_query_cache if @query_cache_enabled       #   clear_query_cache if @query_cache_enabled
         
     | 
| 
       21 
21 
     | 
    
         
             
                            #{method_name}_without_query_dirty(*args)       #   update_without_query_dirty(*args)
         
     | 
| 
         @@ -32,7 +32,6 @@ module ActiveRecord 
     | 
|
| 
       32 
32 
     | 
    
         
             
                  # Enable the query cache within the block.
         
     | 
| 
       33 
33 
     | 
    
         
             
                  def cache
         
     | 
| 
       34 
34 
     | 
    
         
             
                    old, @query_cache_enabled = @query_cache_enabled, true
         
     | 
| 
       35 
     | 
    
         
            -
                    @query_cache ||= {}
         
     | 
| 
       36 
35 
     | 
    
         
             
                    yield
         
     | 
| 
       37 
36 
     | 
    
         
             
                  ensure
         
     | 
| 
       38 
37 
     | 
    
         
             
                    clear_query_cache
         
     | 
| 
         @@ -54,7 +53,7 @@ module ActiveRecord 
     | 
|
| 
       54 
53 
     | 
    
         
             
                  # the same SQL query and repeatedly return the same result each time, silently
         
     | 
| 
       55 
54 
     | 
    
         
             
                  # undermining the randomness you were expecting.
         
     | 
| 
       56 
55 
     | 
    
         
             
                  def clear_query_cache
         
     | 
| 
       57 
     | 
    
         
            -
                    @query_cache.clear 
     | 
| 
      
 56 
     | 
    
         
            +
                    @query_cache.clear
         
     | 
| 
       58 
57 
     | 
    
         
             
                  end
         
     | 
| 
       59 
58 
     | 
    
         | 
| 
       60 
59 
     | 
    
         
             
                  def select_all_with_query_cache(*args)
         
     | 
| 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'active_support/core_ext/array/wrap'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       2 
4 
     | 
    
         
             
              module ConnectionAdapters # :nodoc:
         
     | 
| 
       3 
5 
     | 
    
         
             
                module SchemaStatements
         
     | 
| 
         @@ -267,7 +269,7 @@ module ActiveRecord 
     | 
|
| 
       267 
269 
     | 
    
         
             
                  # generates
         
     | 
| 
       268 
270 
     | 
    
         
             
                  #  CREATE UNIQUE INDEX by_branch_party ON accounts(branch_id, party_id)
         
     | 
| 
       269 
271 
     | 
    
         
             
                  def add_index(table_name, column_name, options = {})
         
     | 
| 
       270 
     | 
    
         
            -
                    column_names = Array(column_name)
         
     | 
| 
      
 272 
     | 
    
         
            +
                    column_names = Array.wrap(column_name)
         
     | 
| 
       271 
273 
     | 
    
         
             
                    index_name   = index_name(table_name, :column => column_names)
         
     | 
| 
       272 
274 
     | 
    
         | 
| 
       273 
275 
     | 
    
         
             
                    if Hash === options # legacy support, since this param was a string
         
     | 
| 
         @@ -291,13 +293,13 @@ module ActiveRecord 
     | 
|
| 
       291 
293 
     | 
    
         
             
                  # Remove the index named by_branch_party in the accounts table.
         
     | 
| 
       292 
294 
     | 
    
         
             
                  #   remove_index :accounts, :name => :by_branch_party
         
     | 
| 
       293 
295 
     | 
    
         
             
                  def remove_index(table_name, options = {})
         
     | 
| 
       294 
     | 
    
         
            -
                    execute "DROP INDEX #{quote_column_name(index_name(table_name, options))} ON #{table_name}"
         
     | 
| 
      
 296 
     | 
    
         
            +
                    execute "DROP INDEX #{quote_column_name(index_name(table_name, options))} ON #{quote_table_name(table_name)}"
         
     | 
| 
       295 
297 
     | 
    
         
             
                  end
         
     | 
| 
       296 
298 
     | 
    
         | 
| 
       297 
299 
     | 
    
         
             
                  def index_name(table_name, options) #:nodoc:
         
     | 
| 
       298 
300 
     | 
    
         
             
                    if Hash === options # legacy support
         
     | 
| 
       299 
301 
     | 
    
         
             
                      if options[:column]
         
     | 
| 
       300 
     | 
    
         
            -
                        "index_#{table_name}_on_#{Array(options[:column]) * '_and_'}"
         
     | 
| 
      
 302 
     | 
    
         
            +
                        "index_#{table_name}_on_#{Array.wrap(options[:column]) * '_and_'}"
         
     | 
| 
       301 
303 
     | 
    
         
             
                      elsif options[:name]
         
     | 
| 
       302 
304 
     | 
    
         
             
                        options[:name]
         
     | 
| 
       303 
305 
     | 
    
         
             
                      else
         
     | 
| 
         @@ -54,6 +54,12 @@ module ActiveRecord 
     | 
|
| 
       54 
54 
     | 
    
         
             
                    super(name, self.class.extract_value_from_default(default), sql_type, null)
         
     | 
| 
       55 
55 
     | 
    
         
             
                  end
         
     | 
| 
       56 
56 
     | 
    
         | 
| 
      
 57 
     | 
    
         
            +
                  # :stopdoc:
         
     | 
| 
      
 58 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 59 
     | 
    
         
            +
                    attr_accessor :money_precision
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
                  # :startdoc:
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
       57 
63 
     | 
    
         
             
                  private
         
     | 
| 
       58 
64 
     | 
    
         
             
                    def extract_limit(sql_type)
         
     | 
| 
       59 
65 
     | 
    
         
             
                      case sql_type
         
     | 
| 
         @@ -71,9 +77,11 @@ module ActiveRecord 
     | 
|
| 
       71 
77 
     | 
    
         | 
| 
       72 
78 
     | 
    
         
             
                    # Extracts the precision from PostgreSQL-specific data types.
         
     | 
| 
       73 
79 
     | 
    
         
             
                    def extract_precision(sql_type)
         
     | 
| 
       74 
     | 
    
         
            -
                       
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
                       
     | 
| 
      
 80 
     | 
    
         
            +
                      if sql_type == 'money'
         
     | 
| 
      
 81 
     | 
    
         
            +
                        self.class.money_precision
         
     | 
| 
      
 82 
     | 
    
         
            +
                      else
         
     | 
| 
      
 83 
     | 
    
         
            +
                        super
         
     | 
| 
      
 84 
     | 
    
         
            +
                      end
         
     | 
| 
       77 
85 
     | 
    
         
             
                    end
         
     | 
| 
       78 
86 
     | 
    
         | 
| 
       79 
87 
     | 
    
         
             
                    # Maps PostgreSQL-specific data types to logical Rails types.
         
     | 
| 
         @@ -83,18 +91,18 @@ module ActiveRecord 
     | 
|
| 
       83 
91 
     | 
    
         
             
                        when /^(?:real|double precision)$/
         
     | 
| 
       84 
92 
     | 
    
         
             
                          :float
         
     | 
| 
       85 
93 
     | 
    
         
             
                        # Monetary types
         
     | 
| 
       86 
     | 
    
         
            -
                        when  
     | 
| 
      
 94 
     | 
    
         
            +
                        when 'money'
         
     | 
| 
       87 
95 
     | 
    
         
             
                          :decimal
         
     | 
| 
       88 
96 
     | 
    
         
             
                        # Character types
         
     | 
| 
       89 
97 
     | 
    
         
             
                        when /^(?:character varying|bpchar)(?:\(\d+\))?$/
         
     | 
| 
       90 
98 
     | 
    
         
             
                          :string
         
     | 
| 
       91 
99 
     | 
    
         
             
                        # Binary data types
         
     | 
| 
       92 
     | 
    
         
            -
                        when  
     | 
| 
      
 100 
     | 
    
         
            +
                        when 'bytea'
         
     | 
| 
       93 
101 
     | 
    
         
             
                          :binary
         
     | 
| 
       94 
102 
     | 
    
         
             
                        # Date/time types
         
     | 
| 
       95 
103 
     | 
    
         
             
                        when /^timestamp with(?:out)? time zone$/
         
     | 
| 
       96 
104 
     | 
    
         
             
                          :datetime
         
     | 
| 
       97 
     | 
    
         
            -
                        when  
     | 
| 
      
 105 
     | 
    
         
            +
                        when 'interval'
         
     | 
| 
       98 
106 
     | 
    
         
             
                          :string
         
     | 
| 
       99 
107 
     | 
    
         
             
                        # Geometric types
         
     | 
| 
       100 
108 
     | 
    
         
             
                        when /^(?:point|line|lseg|box|"?path"?|polygon|circle)$/
         
     | 
| 
         @@ -106,16 +114,16 @@ module ActiveRecord 
     | 
|
| 
       106 
114 
     | 
    
         
             
                        when /^bit(?: varying)?(?:\(\d+\))?$/
         
     | 
| 
       107 
115 
     | 
    
         
             
                          :string
         
     | 
| 
       108 
116 
     | 
    
         
             
                        # XML type
         
     | 
| 
       109 
     | 
    
         
            -
                        when  
     | 
| 
      
 117 
     | 
    
         
            +
                        when 'xml'
         
     | 
| 
       110 
118 
     | 
    
         
             
                          :xml
         
     | 
| 
       111 
119 
     | 
    
         
             
                        # Arrays
         
     | 
| 
       112 
120 
     | 
    
         
             
                        when /^\D+\[\]$/
         
     | 
| 
       113 
121 
     | 
    
         
             
                          :string
         
     | 
| 
       114 
122 
     | 
    
         
             
                        # Object identifier types
         
     | 
| 
       115 
     | 
    
         
            -
                        when  
     | 
| 
      
 123 
     | 
    
         
            +
                        when 'oid'
         
     | 
| 
       116 
124 
     | 
    
         
             
                          :integer
         
     | 
| 
       117 
125 
     | 
    
         
             
                        # UUID type
         
     | 
| 
       118 
     | 
    
         
            -
                        when  
     | 
| 
      
 126 
     | 
    
         
            +
                        when 'uuid'
         
     | 
| 
       119 
127 
     | 
    
         
             
                          :string
         
     | 
| 
       120 
128 
     | 
    
         
             
                        # Small and big integer types
         
     | 
| 
       121 
129 
     | 
    
         
             
                        when /^(?:small|big)int$/
         
     | 
| 
         @@ -383,9 +391,9 @@ module ActiveRecord 
     | 
|
| 
       383 
391 
     | 
    
         
             
                  def quote(value, column = nil) #:nodoc:
         
     | 
| 
       384 
392 
     | 
    
         
             
                    if value.kind_of?(String) && column && column.type == :binary
         
     | 
| 
       385 
393 
     | 
    
         
             
                      "#{quoted_string_prefix}'#{escape_bytea(value)}'"
         
     | 
| 
       386 
     | 
    
         
            -
                    elsif value.kind_of?(String) && column && column.sql_type  
     | 
| 
      
 394 
     | 
    
         
            +
                    elsif value.kind_of?(String) && column && column.sql_type == 'xml'
         
     | 
| 
       387 
395 
     | 
    
         
             
                      "xml E'#{quote_string(value)}'"
         
     | 
| 
       388 
     | 
    
         
            -
                    elsif value.kind_of?(Numeric) && column && column.sql_type  
     | 
| 
      
 396 
     | 
    
         
            +
                    elsif value.kind_of?(Numeric) && column && column.sql_type == 'money'
         
     | 
| 
       389 
397 
     | 
    
         
             
                      # Not truly string input, so doesn't require (or allow) escape string syntax.
         
     | 
| 
       390 
398 
     | 
    
         
             
                      "'#{value.to_s}'"
         
     | 
| 
       391 
399 
     | 
    
         
             
                    elsif value.kind_of?(String) && column && column.sql_type =~ /^bit/
         
     | 
| 
         @@ -658,33 +666,34 @@ module ActiveRecord 
     | 
|
| 
       658 
666 
     | 
    
         
             
                    end
         
     | 
| 
       659 
667 
     | 
    
         
             
                  end
         
     | 
| 
       660 
668 
     | 
    
         | 
| 
       661 
     | 
    
         
            -
                  # Creates a schema for the given user
         
     | 
| 
       662 
     | 
    
         
            -
                  #
         
     | 
| 
       663 
     | 
    
         
            -
                  # Example:
         
     | 
| 
       664 
     | 
    
         
            -
                  #   create_schema('products', 'postgres')
         
     | 
| 
       665 
     | 
    
         
            -
                  def create_schema(schema_name, pg_username)
         
     | 
| 
       666 
     | 
    
         
            -
                    execute("CREATE SCHEMA \"#{schema_name}\" AUTHORIZATION \"#{pg_username}\"")
         
     | 
| 
       667 
     | 
    
         
            -
                  end
         
     | 
| 
       668 
     | 
    
         
            -
             
     | 
| 
       669 
     | 
    
         
            -
                  # Drops a schema
         
     | 
| 
       670 
     | 
    
         
            -
                  #
         
     | 
| 
       671 
     | 
    
         
            -
                  # Example:
         
     | 
| 
       672 
     | 
    
         
            -
                  #   drop_schema('products')
         
     | 
| 
       673 
     | 
    
         
            -
                  def drop_schema(schema_name)
         
     | 
| 
       674 
     | 
    
         
            -
                    execute("DROP SCHEMA \"#{schema_name}\"")
         
     | 
| 
       675 
     | 
    
         
            -
                  end
         
     | 
| 
       676 
     | 
    
         
            -
             
     | 
| 
       677 
     | 
    
         
            -
                  # Returns an array of all schemas in the database
         
     | 
| 
       678 
     | 
    
         
            -
                  def all_schemas
         
     | 
| 
       679 
     | 
    
         
            -
                    query('SELECT schema_name FROM information_schema.schemata').flatten
         
     | 
| 
       680 
     | 
    
         
            -
                  end
         
     | 
| 
       681 
     | 
    
         
            -
             
     | 
| 
       682 
669 
     | 
    
         
             
                  # Returns the list of all tables in the schema search path or a specified schema.
         
     | 
| 
       683 
670 
     | 
    
         
             
                  def tables(name = nil)
         
     | 
| 
       684 
671 
     | 
    
         
             
                    query(<<-SQL, name).map { |row| row[0] }
         
     | 
| 
       685 
672 
     | 
    
         
             
                      SELECT tablename
         
     | 
| 
      
 673 
     | 
    
         
            +
                      FROM pg_tables
         
     | 
| 
      
 674 
     | 
    
         
            +
                      WHERE schemaname = ANY (current_schemas(false))
         
     | 
| 
      
 675 
     | 
    
         
            +
                    SQL
         
     | 
| 
      
 676 
     | 
    
         
            +
                  end
         
     | 
| 
      
 677 
     | 
    
         
            +
             
     | 
| 
      
 678 
     | 
    
         
            +
                  def table_exists?(name)
         
     | 
| 
      
 679 
     | 
    
         
            +
                    name          = name.to_s
         
     | 
| 
      
 680 
     | 
    
         
            +
                    schema, table = name.split('.', 2)
         
     | 
| 
      
 681 
     | 
    
         
            +
             
     | 
| 
      
 682 
     | 
    
         
            +
                    unless table # A table was provided without a schema
         
     | 
| 
      
 683 
     | 
    
         
            +
                      table  = schema
         
     | 
| 
      
 684 
     | 
    
         
            +
                      schema = nil
         
     | 
| 
      
 685 
     | 
    
         
            +
                    end
         
     | 
| 
      
 686 
     | 
    
         
            +
             
     | 
| 
      
 687 
     | 
    
         
            +
                    if name =~ /^"/ # Handle quoted table names
         
     | 
| 
      
 688 
     | 
    
         
            +
                      table  = name
         
     | 
| 
      
 689 
     | 
    
         
            +
                      schema = nil
         
     | 
| 
      
 690 
     | 
    
         
            +
                    end
         
     | 
| 
      
 691 
     | 
    
         
            +
             
     | 
| 
      
 692 
     | 
    
         
            +
                    query(<<-SQL).first[0].to_i > 0
         
     | 
| 
      
 693 
     | 
    
         
            +
                        SELECT COUNT(*)
         
     | 
| 
       686 
694 
     | 
    
         
             
                        FROM pg_tables
         
     | 
| 
       687 
     | 
    
         
            -
             
     | 
| 
      
 695 
     | 
    
         
            +
                        WHERE tablename = '#{table.gsub(/(^"|"$)/,'')}'
         
     | 
| 
      
 696 
     | 
    
         
            +
                        #{schema ? "AND schemaname = '#{schema}'" : ''}
         
     | 
| 
       688 
697 
     | 
    
         
             
                    SQL
         
     | 
| 
       689 
698 
     | 
    
         
             
                  end
         
     | 
| 
       690 
699 
     | 
    
         | 
| 
         @@ -946,7 +955,7 @@ module ActiveRecord 
     | 
|
| 
       946 
955 
     | 
    
         
             
                    # Construct a clean list of column names from the ORDER BY clause, removing
         
     | 
| 
       947 
956 
     | 
    
         
             
                    # any ASC/DESC modifiers
         
     | 
| 
       948 
957 
     | 
    
         
             
                    order_columns = order_by.split(',').collect { |s| s.split.first }
         
     | 
| 
       949 
     | 
    
         
            -
                    order_columns.delete_if 
     | 
| 
      
 958 
     | 
    
         
            +
                    order_columns.delete_if(&:blank?)
         
     | 
| 
       950 
959 
     | 
    
         
             
                    order_columns = order_columns.zip((0...order_columns.size).to_a).map { |s,i| "#{s} AS alias_#{i}" }
         
     | 
| 
       951 
960 
     | 
    
         | 
| 
       952 
961 
     | 
    
         
             
                    # Return a DISTINCT ON() clause that's distinct on the columns we want but includes
         
     | 
| 
         @@ -1010,17 +1019,8 @@ module ActiveRecord 
     | 
|
| 
       1010 
1019 
     | 
    
         
             
                      # Money type has a fixed precision of 10 in PostgreSQL 8.2 and below, and as of
         
     | 
| 
       1011 
1020 
     | 
    
         
             
                      # PostgreSQL 8.3 it has a fixed precision of 19. PostgreSQLColumn.extract_precision
         
     | 
| 
       1012 
1021 
     | 
    
         
             
                      # should know about this but can't detect it there, so deal with it here.
         
     | 
| 
       1013 
     | 
    
         
            -
                      money_precision = 
     | 
| 
       1014 
     | 
    
         
            -
             
     | 
| 
       1015 
     | 
    
         
            -
                        def extract_precision(sql_type)  # def extract_precision(sql_type)
         
     | 
| 
       1016 
     | 
    
         
            -
                          if sql_type =~ /^money$/       #   if sql_type =~ /^money$/
         
     | 
| 
       1017 
     | 
    
         
            -
                            #{money_precision}           #     19
         
     | 
| 
       1018 
     | 
    
         
            -
                          else                           #   else
         
     | 
| 
       1019 
     | 
    
         
            -
                            super                        #     super
         
     | 
| 
       1020 
     | 
    
         
            -
                          end                            #   end
         
     | 
| 
       1021 
     | 
    
         
            -
                        end                              # end
         
     | 
| 
       1022 
     | 
    
         
            -
                      end_eval
         
     | 
| 
       1023 
     | 
    
         
            -
             
     | 
| 
      
 1022 
     | 
    
         
            +
                      PostgreSQLColumn.money_precision =
         
     | 
| 
      
 1023 
     | 
    
         
            +
                        (postgresql_version >= 80300) ? 19 : 10
         
     | 
| 
       1024 
1024 
     | 
    
         
             
                      configure_connection
         
     | 
| 
       1025 
1025 
     | 
    
         
             
                    end
         
     | 
| 
       1026 
1026 
     | 
    
         | 
| 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'active_support/core_ext/array'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'active_support/core_ext/hash/except'
         
     | 
| 
       3 
     | 
    
         
            -
            require 'active_support/core_ext/ 
     | 
| 
      
 3 
     | 
    
         
            +
            require 'active_support/core_ext/kernel/singleton_class'
         
     | 
| 
       4 
4 
     | 
    
         
             
            require 'active_support/core_ext/object/blank'
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
         @@ -8,16 +8,15 @@ module ActiveRecord 
     | 
|
| 
       8 
8 
     | 
    
         
             
                extend ActiveSupport::Concern
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
                module ClassMethods
         
     | 
| 
       11 
     | 
    
         
            -
                  # Returns  
     | 
| 
      
 11 
     | 
    
         
            +
                  # Returns an anonymous scope.
         
     | 
| 
       12 
12 
     | 
    
         
             
                  #
         
     | 
| 
       13 
13 
     | 
    
         
             
                  #   posts = Post.scoped
         
     | 
| 
       14 
14 
     | 
    
         
             
                  #   posts.size # Fires "select count(*) from  posts" and returns the count
         
     | 
| 
       15 
15 
     | 
    
         
             
                  #   posts.each {|p| puts p.name } # Fires "select * from posts" and loads post objects
         
     | 
| 
       16 
16 
     | 
    
         
             
                  #
         
     | 
| 
       17 
     | 
    
         
            -
                  #  
     | 
| 
       18 
     | 
    
         
            -
                  #
         
     | 
| 
       19 
     | 
    
         
            -
                  #    
     | 
| 
       20 
     | 
    
         
            -
                  #   shirts = shirts.scoped(:include => :washing_instructions)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #   fruits = Fruit.scoped
         
     | 
| 
      
 18 
     | 
    
         
            +
                  #   fruits = fruits.where(:colour => 'red') if options[:red_only]
         
     | 
| 
      
 19 
     | 
    
         
            +
                  #   fruits = fruits.limit(10) if limited?
         
     | 
| 
       21 
20 
     | 
    
         
             
                  #
         
     | 
| 
       22 
21 
     | 
    
         
             
                  # Anonymous \scopes tend to be useful when procedurally generating complex queries, where passing
         
     | 
| 
       23 
22 
     | 
    
         
             
                  # intermediate values (scopes) around as first-class objects is convenient.
         
     | 
| 
         @@ -25,7 +24,8 @@ module ActiveRecord 
     | 
|
| 
       25 
24 
     | 
    
         
             
                  # You can define a scope that applies to all finders using ActiveRecord::Base.default_scope.
         
     | 
| 
       26 
25 
     | 
    
         
             
                  def scoped(options = {}, &block)
         
     | 
| 
       27 
26 
     | 
    
         
             
                    if options.present?
         
     | 
| 
       28 
     | 
    
         
            -
                       
     | 
| 
      
 27 
     | 
    
         
            +
                      relation = scoped.apply_finder_options(options)
         
     | 
| 
      
 28 
     | 
    
         
            +
                      block_given? ? relation.extending(Module.new(&block)) : relation
         
     | 
| 
       29 
29 
     | 
    
         
             
                    else
         
     | 
| 
       30 
30 
     | 
    
         
             
                      current_scoped_methods ? unscoped.merge(current_scoped_methods) : unscoped.clone
         
     | 
| 
       31 
31 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -36,21 +36,21 @@ module ActiveRecord 
     | 
|
| 
       36 
36 
     | 
    
         
             
                  end
         
     | 
| 
       37 
37 
     | 
    
         | 
| 
       38 
38 
     | 
    
         
             
                  # Adds a class method for retrieving and querying objects. A scope represents a narrowing of a database query,
         
     | 
| 
       39 
     | 
    
         
            -
                  # such as <tt 
     | 
| 
      
 39 
     | 
    
         
            +
                  # such as <tt>where(:color => :red).select('shirts.*').includes(:washing_instructions)</tt>.
         
     | 
| 
       40 
40 
     | 
    
         
             
                  #
         
     | 
| 
       41 
41 
     | 
    
         
             
                  #   class Shirt < ActiveRecord::Base
         
     | 
| 
       42 
     | 
    
         
            -
                  #     scope :red, : 
     | 
| 
       43 
     | 
    
         
            -
                  #     scope :dry_clean_only,  
     | 
| 
      
 42 
     | 
    
         
            +
                  #     scope :red, where(:color => 'red')
         
     | 
| 
      
 43 
     | 
    
         
            +
                  #     scope :dry_clean_only, joins(:washing_instructions).where('washing_instructions.dry_clean_only = ?', true)
         
     | 
| 
       44 
44 
     | 
    
         
             
                  #   end
         
     | 
| 
       45 
45 
     | 
    
         
             
                  #
         
     | 
| 
       46 
46 
     | 
    
         
             
                  # The above calls to <tt>scope</tt> define class methods Shirt.red and Shirt.dry_clean_only. Shirt.red,
         
     | 
| 
       47 
     | 
    
         
            -
                  # in effect, represents the query <tt>Shirt. 
     | 
| 
      
 47 
     | 
    
         
            +
                  # in effect, represents the query <tt>Shirt.where(:color => 'red')</tt>.
         
     | 
| 
       48 
48 
     | 
    
         
             
                  #
         
     | 
| 
       49 
49 
     | 
    
         
             
                  # Unlike <tt>Shirt.find(...)</tt>, however, the object returned by Shirt.red is not an Array; it resembles the association object
         
     | 
| 
       50 
     | 
    
         
            -
                  # constructed by a <tt>has_many</tt> declaration. For instance, you can invoke <tt>Shirt.red. 
     | 
| 
       51 
     | 
    
         
            -
                  # <tt>Shirt.red. 
     | 
| 
       52 
     | 
    
         
            -
                  #  
     | 
| 
       53 
     | 
    
         
            -
                  #  
     | 
| 
      
 50 
     | 
    
         
            +
                  # constructed by a <tt>has_many</tt> declaration. For instance, you can invoke <tt>Shirt.red.first</tt>, <tt>Shirt.red.count</tt>,
         
     | 
| 
      
 51 
     | 
    
         
            +
                  # <tt>Shirt.red.where(:size => 'small')</tt>. Also, just as with the association objects, named \scopes act like an Array,
         
     | 
| 
      
 52 
     | 
    
         
            +
                  # implementing Enumerable; <tt>Shirt.red.each(&block)</tt>, <tt>Shirt.red.first</tt>, and <tt>Shirt.red.inject(memo, &block)</tt>
         
     | 
| 
      
 53 
     | 
    
         
            +
                  # all behave as if Shirt.red really was an Array.
         
     | 
| 
       54 
54 
     | 
    
         
             
                  #
         
     | 
| 
       55 
55 
     | 
    
         
             
                  # These named \scopes are composable. For instance, <tt>Shirt.red.dry_clean_only</tt> will produce all shirts that are both red and dry clean only.
         
     | 
| 
       56 
56 
     | 
    
         
             
                  # Nested finds and calculations also work with these compositions: <tt>Shirt.red.dry_clean_only.count</tt> returns the number of garments
         
     | 
| 
         @@ -69,9 +69,7 @@ module ActiveRecord 
     | 
|
| 
       69 
69 
     | 
    
         
             
                  # Named \scopes can also be procedural:
         
     | 
| 
       70 
70 
     | 
    
         
             
                  #
         
     | 
| 
       71 
71 
     | 
    
         
             
                  #   class Shirt < ActiveRecord::Base
         
     | 
| 
       72 
     | 
    
         
            -
                  #     scope :colored, lambda { 
     | 
| 
       73 
     | 
    
         
            -
                  #       { :conditions => { :color => color } }
         
     | 
| 
       74 
     | 
    
         
            -
                  #     }
         
     | 
| 
      
 72 
     | 
    
         
            +
                  #     scope :colored, lambda {|color| where(:color => color) }
         
     | 
| 
       75 
73 
     | 
    
         
             
                  #   end
         
     | 
| 
       76 
74 
     | 
    
         
             
                  #
         
     | 
| 
       77 
75 
     | 
    
         
             
                  # In this example, <tt>Shirt.colored('puce')</tt> finds all puce shirts.
         
     | 
| 
         @@ -79,26 +77,13 @@ module ActiveRecord 
     | 
|
| 
       79 
77 
     | 
    
         
             
                  # Named \scopes can also have extensions, just as with <tt>has_many</tt> declarations:
         
     | 
| 
       80 
78 
     | 
    
         
             
                  #
         
     | 
| 
       81 
79 
     | 
    
         
             
                  #   class Shirt < ActiveRecord::Base
         
     | 
| 
       82 
     | 
    
         
            -
                  #     scope :red, : 
     | 
| 
      
 80 
     | 
    
         
            +
                  #     scope :red, where(:color => 'red') do
         
     | 
| 
       83 
81 
     | 
    
         
             
                  #       def dom_id
         
     | 
| 
       84 
82 
     | 
    
         
             
                  #         'red_shirts'
         
     | 
| 
       85 
83 
     | 
    
         
             
                  #       end
         
     | 
| 
       86 
84 
     | 
    
         
             
                  #     end
         
     | 
| 
       87 
85 
     | 
    
         
             
                  #   end
         
     | 
| 
       88 
     | 
    
         
            -
                   
     | 
| 
       89 
     | 
    
         
            -
                  #
         
     | 
| 
       90 
     | 
    
         
            -
                  # For testing complex named \scopes, you can examine the scoping options using the
         
     | 
| 
       91 
     | 
    
         
            -
                  # <tt>proxy_options</tt> method on the proxy itself.
         
     | 
| 
       92 
     | 
    
         
            -
                  #
         
     | 
| 
       93 
     | 
    
         
            -
                  #   class Shirt < ActiveRecord::Base
         
     | 
| 
       94 
     | 
    
         
            -
                  #     scope :colored, lambda { |color|
         
     | 
| 
       95 
     | 
    
         
            -
                  #       { :conditions => { :color => color } }
         
     | 
| 
       96 
     | 
    
         
            -
                  #     }
         
     | 
| 
       97 
     | 
    
         
            -
                  #   end
         
     | 
| 
       98 
     | 
    
         
            -
                  #
         
     | 
| 
       99 
     | 
    
         
            -
                  #   expected_options = { :conditions => { :colored => 'red' } }
         
     | 
| 
       100 
     | 
    
         
            -
                  #   assert_equal expected_options, Shirt.colored('red').proxy_options
         
     | 
| 
       101 
     | 
    
         
            -
                  def scope(name, options = {}, &block)
         
     | 
| 
      
 86 
     | 
    
         
            +
                  def scope(name, scope_options = {}, &block)
         
     | 
| 
       102 
87 
     | 
    
         
             
                    name = name.to_sym
         
     | 
| 
       103 
88 
     | 
    
         | 
| 
       104 
89 
     | 
    
         
             
                    if !scopes[name] && respond_to?(name, true)
         
     | 
| 
         @@ -106,17 +91,17 @@ module ActiveRecord 
     | 
|
| 
       106 
91 
     | 
    
         
             
                                  "Overwriting existing method #{self.name}.#{name}."
         
     | 
| 
       107 
92 
     | 
    
         
             
                    end
         
     | 
| 
       108 
93 
     | 
    
         | 
| 
       109 
     | 
    
         
            -
                    scopes[name] = lambda do  
     | 
| 
       110 
     | 
    
         
            -
                       
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
                      end, &block)
         
     | 
| 
      
 94 
     | 
    
         
            +
                    scopes[name] = lambda do |*args|
         
     | 
| 
      
 95 
     | 
    
         
            +
                      options = scope_options.is_a?(Proc) ? scope_options.call(*args) : scope_options
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                      relation = scoped
         
     | 
| 
      
 98 
     | 
    
         
            +
                      relation = options.is_a?(Hash) ? relation.apply_finder_options(options) : scoped.merge(options) if options
         
     | 
| 
      
 99 
     | 
    
         
            +
                      block_given? ? relation.extending(Module.new(&block)) : relation
         
     | 
| 
       116 
100 
     | 
    
         
             
                    end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
       117 
102 
     | 
    
         
             
                    singleton_class.instance_eval do
         
     | 
| 
       118 
103 
     | 
    
         
             
                      define_method name do |*args|
         
     | 
| 
       119 
     | 
    
         
            -
                        scopes[name].call( 
     | 
| 
      
 104 
     | 
    
         
            +
                        scopes[name].call(*args)
         
     | 
| 
       120 
105 
     | 
    
         
             
                      end
         
     | 
| 
       121 
106 
     | 
    
         
             
                    end
         
     | 
| 
       122 
107 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -127,73 +112,5 @@ module ActiveRecord 
     | 
|
| 
       127 
112 
     | 
    
         
             
                  end
         
     | 
| 
       128 
113 
     | 
    
         
             
                end
         
     | 
| 
       129 
114 
     | 
    
         | 
| 
       130 
     | 
    
         
            -
                class Scope < Relation
         
     | 
| 
       131 
     | 
    
         
            -
                  attr_accessor :current_scoped_methods_when_defined
         
     | 
| 
       132 
     | 
    
         
            -
             
     | 
| 
       133 
     | 
    
         
            -
                  delegate :scopes, :with_scope, :with_exclusive_scope, :scoped_methods, :scoped, :to => :klass
         
     | 
| 
       134 
     | 
    
         
            -
             
     | 
| 
       135 
     | 
    
         
            -
                  def self.init(klass, options, &block)
         
     | 
| 
       136 
     | 
    
         
            -
                    relation = new(klass, klass.arel_table)
         
     | 
| 
       137 
     | 
    
         
            -
             
     | 
| 
       138 
     | 
    
         
            -
                    scope = if options.is_a?(Hash)
         
     | 
| 
       139 
     | 
    
         
            -
                      klass.scoped.apply_finder_options(options.except(:extend))
         
     | 
| 
       140 
     | 
    
         
            -
                    else
         
     | 
| 
       141 
     | 
    
         
            -
                      options ? klass.scoped.merge(options) : klass.scoped
         
     | 
| 
       142 
     | 
    
         
            -
                    end
         
     | 
| 
       143 
     | 
    
         
            -
             
     | 
| 
       144 
     | 
    
         
            -
                    relation = relation.merge(scope)
         
     | 
| 
       145 
     | 
    
         
            -
             
     | 
| 
       146 
     | 
    
         
            -
                    Array.wrap(options[:extend]).each {|extension| relation.send(:extend, extension) } if options.is_a?(Hash)
         
     | 
| 
       147 
     | 
    
         
            -
                    relation.send(:extend, Module.new(&block)) if block_given?
         
     | 
| 
       148 
     | 
    
         
            -
             
     | 
| 
       149 
     | 
    
         
            -
                    relation.current_scoped_methods_when_defined = klass.send(:current_scoped_methods)
         
     | 
| 
       150 
     | 
    
         
            -
                    relation
         
     | 
| 
       151 
     | 
    
         
            -
                  end
         
     | 
| 
       152 
     | 
    
         
            -
             
     | 
| 
       153 
     | 
    
         
            -
                  def first(*args)
         
     | 
| 
       154 
     | 
    
         
            -
                    if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
         
     | 
| 
       155 
     | 
    
         
            -
                      to_a.first(*args)
         
     | 
| 
       156 
     | 
    
         
            -
                    else
         
     | 
| 
       157 
     | 
    
         
            -
                      args.first.present? ? apply_finder_options(args.first).first : super
         
     | 
| 
       158 
     | 
    
         
            -
                    end
         
     | 
| 
       159 
     | 
    
         
            -
                  end
         
     | 
| 
       160 
     | 
    
         
            -
             
     | 
| 
       161 
     | 
    
         
            -
                  def last(*args)
         
     | 
| 
       162 
     | 
    
         
            -
                    if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
         
     | 
| 
       163 
     | 
    
         
            -
                      to_a.last(*args)
         
     | 
| 
       164 
     | 
    
         
            -
                    else
         
     | 
| 
       165 
     | 
    
         
            -
                      args.first.present? ? apply_finder_options(args.first).last : super
         
     | 
| 
       166 
     | 
    
         
            -
                    end
         
     | 
| 
       167 
     | 
    
         
            -
                  end
         
     | 
| 
       168 
     | 
    
         
            -
             
     | 
| 
       169 
     | 
    
         
            -
                  def ==(other)
         
     | 
| 
       170 
     | 
    
         
            -
                    case other
         
     | 
| 
       171 
     | 
    
         
            -
                    when Scope
         
     | 
| 
       172 
     | 
    
         
            -
                      to_sql == other.to_sql
         
     | 
| 
       173 
     | 
    
         
            -
                    when Relation
         
     | 
| 
       174 
     | 
    
         
            -
                      other == self
         
     | 
| 
       175 
     | 
    
         
            -
                    when Array
         
     | 
| 
       176 
     | 
    
         
            -
                      to_a == other.to_a
         
     | 
| 
       177 
     | 
    
         
            -
                    end
         
     | 
| 
       178 
     | 
    
         
            -
                  end
         
     | 
| 
       179 
     | 
    
         
            -
             
     | 
| 
       180 
     | 
    
         
            -
                  private
         
     | 
| 
       181 
     | 
    
         
            -
             
     | 
| 
       182 
     | 
    
         
            -
                  def method_missing(method, *args, &block)
         
     | 
| 
       183 
     | 
    
         
            -
                    if klass.respond_to?(method)
         
     | 
| 
       184 
     | 
    
         
            -
                      with_scope(self) do
         
     | 
| 
       185 
     | 
    
         
            -
                        if current_scoped_methods_when_defined && !scoped_methods.include?(current_scoped_methods_when_defined) && !scopes.include?(method)
         
     | 
| 
       186 
     | 
    
         
            -
                          with_scope(current_scoped_methods_when_defined) { klass.send(method, *args, &block) }
         
     | 
| 
       187 
     | 
    
         
            -
                        else
         
     | 
| 
       188 
     | 
    
         
            -
                          klass.send(method, *args, &block)
         
     | 
| 
       189 
     | 
    
         
            -
                        end
         
     | 
| 
       190 
     | 
    
         
            -
                      end
         
     | 
| 
       191 
     | 
    
         
            -
                    else
         
     | 
| 
       192 
     | 
    
         
            -
                      super
         
     | 
| 
       193 
     | 
    
         
            -
                    end
         
     | 
| 
       194 
     | 
    
         
            -
                  end
         
     | 
| 
       195 
     | 
    
         
            -
             
     | 
| 
       196 
     | 
    
         
            -
                end
         
     | 
| 
       197 
     | 
    
         
            -
             
     | 
| 
       198 
115 
     | 
    
         
             
              end
         
     | 
| 
       199 
116 
     | 
    
         
             
            end
         
     |