activerecord 3.2.22.4 → 4.0.13
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.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +2799 -617
 - data/MIT-LICENSE +1 -1
 - data/README.rdoc +23 -32
 - data/examples/performance.rb +1 -1
 - data/lib/active_record/aggregations.rb +40 -34
 - data/lib/active_record/association_relation.rb +22 -0
 - data/lib/active_record/associations/alias_tracker.rb +4 -2
 - data/lib/active_record/associations/association.rb +60 -46
 - data/lib/active_record/associations/association_scope.rb +46 -40
 - data/lib/active_record/associations/belongs_to_association.rb +17 -4
 - data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
 - data/lib/active_record/associations/builder/association.rb +81 -28
 - data/lib/active_record/associations/builder/belongs_to.rb +73 -56
 - data/lib/active_record/associations/builder/collection_association.rb +54 -40
 - data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +23 -41
 - data/lib/active_record/associations/builder/has_many.rb +8 -64
 - data/lib/active_record/associations/builder/has_one.rb +13 -50
 - data/lib/active_record/associations/builder/singular_association.rb +13 -13
 - data/lib/active_record/associations/collection_association.rb +130 -96
 - data/lib/active_record/associations/collection_proxy.rb +916 -63
 - data/lib/active_record/associations/has_and_belongs_to_many_association.rb +15 -13
 - data/lib/active_record/associations/has_many_association.rb +35 -8
 - data/lib/active_record/associations/has_many_through_association.rb +37 -17
 - data/lib/active_record/associations/has_one_association.rb +42 -19
 - data/lib/active_record/associations/has_one_through_association.rb +1 -1
 - data/lib/active_record/associations/join_dependency/join_association.rb +39 -22
 - data/lib/active_record/associations/join_dependency/join_base.rb +2 -2
 - data/lib/active_record/associations/join_dependency/join_part.rb +21 -8
 - data/lib/active_record/associations/join_dependency.rb +30 -9
 - data/lib/active_record/associations/join_helper.rb +1 -11
 - data/lib/active_record/associations/preloader/association.rb +29 -33
 - data/lib/active_record/associations/preloader/collection_association.rb +1 -1
 - data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +2 -2
 - data/lib/active_record/associations/preloader/has_many_through.rb +6 -2
 - data/lib/active_record/associations/preloader/has_one.rb +1 -1
 - data/lib/active_record/associations/preloader/through_association.rb +13 -17
 - data/lib/active_record/associations/preloader.rb +20 -43
 - data/lib/active_record/associations/singular_association.rb +11 -11
 - data/lib/active_record/associations/through_association.rb +3 -3
 - data/lib/active_record/associations.rb +223 -282
 - data/lib/active_record/attribute_assignment.rb +134 -154
 - data/lib/active_record/attribute_methods/before_type_cast.rb +44 -5
 - data/lib/active_record/attribute_methods/dirty.rb +36 -29
 - data/lib/active_record/attribute_methods/primary_key.rb +45 -31
 - data/lib/active_record/attribute_methods/query.rb +5 -4
 - data/lib/active_record/attribute_methods/read.rb +67 -90
 - data/lib/active_record/attribute_methods/serialization.rb +133 -70
 - data/lib/active_record/attribute_methods/time_zone_conversion.rb +51 -45
 - data/lib/active_record/attribute_methods/write.rb +34 -39
 - data/lib/active_record/attribute_methods.rb +268 -108
 - data/lib/active_record/autosave_association.rb +80 -73
 - data/lib/active_record/base.rb +54 -451
 - data/lib/active_record/callbacks.rb +60 -22
 - data/lib/active_record/coders/yaml_column.rb +18 -21
 - data/lib/active_record/connection_adapters/abstract/connection_pool.rb +347 -197
 - data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
 - data/lib/active_record/connection_adapters/abstract/database_statements.rb +146 -138
 - data/lib/active_record/connection_adapters/abstract/query_cache.rb +25 -19
 - data/lib/active_record/connection_adapters/abstract/quoting.rb +19 -3
 - data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +151 -142
 - data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
 - data/lib/active_record/connection_adapters/abstract/schema_statements.rb +499 -217
 - data/lib/active_record/connection_adapters/abstract/transaction.rb +208 -0
 - data/lib/active_record/connection_adapters/abstract_adapter.rb +209 -44
 - data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +169 -61
 - data/lib/active_record/connection_adapters/column.rb +67 -36
 - data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
 - data/lib/active_record/connection_adapters/mysql2_adapter.rb +28 -29
 - data/lib/active_record/connection_adapters/mysql_adapter.rb +200 -73
 - data/lib/active_record/connection_adapters/postgresql/array_parser.rb +98 -0
 - data/lib/active_record/connection_adapters/postgresql/cast.rb +160 -0
 - data/lib/active_record/connection_adapters/postgresql/database_statements.rb +240 -0
 - data/lib/active_record/connection_adapters/postgresql/oid.rb +374 -0
 - data/lib/active_record/connection_adapters/postgresql/quoting.rb +183 -0
 - data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
 - data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +508 -0
 - data/lib/active_record/connection_adapters/postgresql_adapter.rb +544 -899
 - data/lib/active_record/connection_adapters/schema_cache.rb +76 -16
 - data/lib/active_record/connection_adapters/sqlite3_adapter.rb +595 -16
 - data/lib/active_record/connection_handling.rb +98 -0
 - data/lib/active_record/core.rb +472 -0
 - data/lib/active_record/counter_cache.rb +107 -108
 - data/lib/active_record/dynamic_matchers.rb +115 -63
 - data/lib/active_record/errors.rb +36 -18
 - data/lib/active_record/explain.rb +15 -63
 - data/lib/active_record/explain_registry.rb +30 -0
 - data/lib/active_record/explain_subscriber.rb +8 -4
 - data/lib/active_record/fixture_set/file.rb +55 -0
 - data/lib/active_record/fixtures.rb +159 -155
 - data/lib/active_record/inheritance.rb +93 -59
 - data/lib/active_record/integration.rb +8 -8
 - data/lib/active_record/locale/en.yml +8 -1
 - data/lib/active_record/locking/optimistic.rb +39 -43
 - data/lib/active_record/locking/pessimistic.rb +4 -4
 - data/lib/active_record/log_subscriber.rb +19 -9
 - data/lib/active_record/migration/command_recorder.rb +102 -33
 - data/lib/active_record/migration/join_table.rb +15 -0
 - data/lib/active_record/migration.rb +411 -173
 - data/lib/active_record/model_schema.rb +81 -94
 - data/lib/active_record/nested_attributes.rb +173 -131
 - data/lib/active_record/null_relation.rb +67 -0
 - data/lib/active_record/persistence.rb +254 -106
 - data/lib/active_record/query_cache.rb +18 -36
 - data/lib/active_record/querying.rb +19 -15
 - data/lib/active_record/railtie.rb +113 -38
 - data/lib/active_record/railties/console_sandbox.rb +3 -4
 - data/lib/active_record/railties/controller_runtime.rb +4 -3
 - data/lib/active_record/railties/databases.rake +115 -368
 - data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
 - data/lib/active_record/readonly_attributes.rb +7 -3
 - data/lib/active_record/reflection.rb +110 -61
 - data/lib/active_record/relation/batches.rb +29 -29
 - data/lib/active_record/relation/calculations.rb +155 -125
 - data/lib/active_record/relation/delegation.rb +94 -18
 - data/lib/active_record/relation/finder_methods.rb +151 -203
 - data/lib/active_record/relation/merger.rb +188 -0
 - data/lib/active_record/relation/predicate_builder.rb +85 -42
 - data/lib/active_record/relation/query_methods.rb +793 -146
 - data/lib/active_record/relation/spawn_methods.rb +43 -150
 - data/lib/active_record/relation.rb +293 -173
 - data/lib/active_record/result.rb +48 -7
 - data/lib/active_record/runtime_registry.rb +17 -0
 - data/lib/active_record/sanitization.rb +41 -54
 - data/lib/active_record/schema.rb +19 -12
 - data/lib/active_record/schema_dumper.rb +41 -41
 - data/lib/active_record/schema_migration.rb +46 -0
 - data/lib/active_record/scoping/default.rb +56 -52
 - data/lib/active_record/scoping/named.rb +78 -103
 - data/lib/active_record/scoping.rb +54 -124
 - data/lib/active_record/serialization.rb +6 -2
 - data/lib/active_record/serializers/xml_serializer.rb +9 -15
 - data/lib/active_record/statement_cache.rb +26 -0
 - data/lib/active_record/store.rb +131 -15
 - data/lib/active_record/tasks/database_tasks.rb +204 -0
 - data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
 - data/lib/active_record/tasks/mysql_database_tasks.rb +144 -0
 - data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
 - data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
 - data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
 - data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
 - data/lib/active_record/test_case.rb +67 -38
 - data/lib/active_record/timestamp.rb +16 -11
 - data/lib/active_record/transactions.rb +73 -51
 - data/lib/active_record/validations/associated.rb +19 -13
 - data/lib/active_record/validations/presence.rb +65 -0
 - data/lib/active_record/validations/uniqueness.rb +110 -57
 - data/lib/active_record/validations.rb +18 -17
 - data/lib/active_record/version.rb +7 -6
 - data/lib/active_record.rb +63 -45
 - data/lib/rails/generators/active_record/migration/migration_generator.rb +45 -8
 - data/lib/rails/generators/active_record/{model/templates/migration.rb → migration/templates/create_table_migration.rb} +4 -0
 - data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
 - data/lib/rails/generators/active_record/model/model_generator.rb +5 -4
 - data/lib/rails/generators/active_record/model/templates/model.rb +4 -6
 - data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
 - data/lib/rails/generators/active_record.rb +3 -5
 - metadata +43 -29
 - data/examples/associations.png +0 -0
 - data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
 - data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
 - data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
 - data/lib/active_record/dynamic_finder_match.rb +0 -68
 - data/lib/active_record/dynamic_scope_match.rb +0 -23
 - data/lib/active_record/fixtures/file.rb +0 -65
 - data/lib/active_record/identity_map.rb +0 -162
 - data/lib/active_record/observer.rb +0 -121
 - data/lib/active_record/session_store.rb +0 -360
 - data/lib/rails/generators/active_record/migration.rb +0 -15
 - data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
 - data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
 - data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
 - data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
 
| 
         @@ -1,48 +1,185 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'active_support/core_ext/array/wrap'
         
     | 
| 
       2 
     | 
    
         
            -
            require ' 
     | 
| 
      
 2 
     | 
    
         
            +
            require 'active_model/forbidden_attributes_protection'
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       5 
5 
     | 
    
         
             
              module QueryMethods
         
     | 
| 
       6 
6 
     | 
    
         
             
                extend ActiveSupport::Concern
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
                 
     | 
| 
       9 
     | 
    
         
            -
                              :select_values, :group_values, :order_values, :joins_values,
         
     | 
| 
       10 
     | 
    
         
            -
                              :where_values, :having_values, :bind_values,
         
     | 
| 
       11 
     | 
    
         
            -
                              :limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value,
         
     | 
| 
       12 
     | 
    
         
            -
                              :from_value, :reordering_value, :reverse_order_value,
         
     | 
| 
       13 
     | 
    
         
            -
                              :uniq_value
         
     | 
| 
      
 8 
     | 
    
         
            +
                include ActiveModel::ForbiddenAttributesProtection
         
     | 
| 
       14 
9 
     | 
    
         | 
| 
      
 10 
     | 
    
         
            +
                # WhereChain objects act as placeholder for queries in which #where does not have any parameter.
         
     | 
| 
      
 11 
     | 
    
         
            +
                # In this case, #where must be chained with #not to return a new relation.
         
     | 
| 
      
 12 
     | 
    
         
            +
                class WhereChain
         
     | 
| 
      
 13 
     | 
    
         
            +
                  def initialize(scope)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @scope = scope
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  # Returns a new relation expressing WHERE + NOT condition according to
         
     | 
| 
      
 18 
     | 
    
         
            +
                  # the conditions in the arguments.
         
     | 
| 
      
 19 
     | 
    
         
            +
                  #
         
     | 
| 
      
 20 
     | 
    
         
            +
                  # +not+ accepts conditions as a string, array, or hash. See #where for
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # more details on each format.
         
     | 
| 
      
 22 
     | 
    
         
            +
                  #
         
     | 
| 
      
 23 
     | 
    
         
            +
                  #    User.where.not("name = 'Jon'")
         
     | 
| 
      
 24 
     | 
    
         
            +
                  #    # SELECT * FROM users WHERE NOT (name = 'Jon')
         
     | 
| 
      
 25 
     | 
    
         
            +
                  #
         
     | 
| 
      
 26 
     | 
    
         
            +
                  #    User.where.not(["name = ?", "Jon"])
         
     | 
| 
      
 27 
     | 
    
         
            +
                  #    # SELECT * FROM users WHERE NOT (name = 'Jon')
         
     | 
| 
      
 28 
     | 
    
         
            +
                  #
         
     | 
| 
      
 29 
     | 
    
         
            +
                  #    User.where.not(name: "Jon")
         
     | 
| 
      
 30 
     | 
    
         
            +
                  #    # SELECT * FROM users WHERE name != 'Jon'
         
     | 
| 
      
 31 
     | 
    
         
            +
                  #
         
     | 
| 
      
 32 
     | 
    
         
            +
                  #    User.where.not(name: nil)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  #    # SELECT * FROM users WHERE name IS NOT NULL
         
     | 
| 
      
 34 
     | 
    
         
            +
                  #
         
     | 
| 
      
 35 
     | 
    
         
            +
                  #    User.where.not(name: %w(Ko1 Nobu))
         
     | 
| 
      
 36 
     | 
    
         
            +
                  #    # SELECT * FROM users WHERE name NOT IN ('Ko1', 'Nobu')
         
     | 
| 
      
 37 
     | 
    
         
            +
                  #
         
     | 
| 
      
 38 
     | 
    
         
            +
                  #    User.where.not(name: "Jon", role: "admin")
         
     | 
| 
      
 39 
     | 
    
         
            +
                  #    # SELECT * FROM users WHERE name != 'Jon' AND role != 'admin'
         
     | 
| 
      
 40 
     | 
    
         
            +
                  def not(opts, *rest)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    where_value = @scope.send(:build_where, opts, rest).map do |rel|
         
     | 
| 
      
 42 
     | 
    
         
            +
                      case rel
         
     | 
| 
      
 43 
     | 
    
         
            +
                      when Arel::Nodes::In
         
     | 
| 
      
 44 
     | 
    
         
            +
                        Arel::Nodes::NotIn.new(rel.left, rel.right)
         
     | 
| 
      
 45 
     | 
    
         
            +
                      when Arel::Nodes::Equality
         
     | 
| 
      
 46 
     | 
    
         
            +
                        Arel::Nodes::NotEqual.new(rel.left, rel.right)
         
     | 
| 
      
 47 
     | 
    
         
            +
                      when String
         
     | 
| 
      
 48 
     | 
    
         
            +
                        Arel::Nodes::Not.new(Arel::Nodes::SqlLiteral.new(rel))
         
     | 
| 
      
 49 
     | 
    
         
            +
                      else
         
     | 
| 
      
 50 
     | 
    
         
            +
                        Arel::Nodes::Not.new(rel)
         
     | 
| 
      
 51 
     | 
    
         
            +
                      end
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
                    @scope.where_values += where_value
         
     | 
| 
      
 54 
     | 
    
         
            +
                    @scope
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                Relation::MULTI_VALUE_METHODS.each do |name|
         
     | 
| 
      
 59 
     | 
    
         
            +
                  class_eval <<-CODE, __FILE__, __LINE__ + 1
         
     | 
| 
      
 60 
     | 
    
         
            +
                    def #{name}_values                   # def select_values
         
     | 
| 
      
 61 
     | 
    
         
            +
                      @values[:#{name}] || []            #   @values[:select] || []
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end                                  # end
         
     | 
| 
      
 63 
     | 
    
         
            +
                                                         #
         
     | 
| 
      
 64 
     | 
    
         
            +
                    def #{name}_values=(values)          # def select_values=(values)
         
     | 
| 
      
 65 
     | 
    
         
            +
                      raise ImmutableRelation if @loaded #   raise ImmutableRelation if @loaded
         
     | 
| 
      
 66 
     | 
    
         
            +
                      @values[:#{name}] = values         #   @values[:select] = values
         
     | 
| 
      
 67 
     | 
    
         
            +
                    end                                  # end
         
     | 
| 
      
 68 
     | 
    
         
            +
                  CODE
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                (Relation::SINGLE_VALUE_METHODS - [:create_with]).each do |name|
         
     | 
| 
      
 72 
     | 
    
         
            +
                  class_eval <<-CODE, __FILE__, __LINE__ + 1
         
     | 
| 
      
 73 
     | 
    
         
            +
                    def #{name}_value                    # def readonly_value
         
     | 
| 
      
 74 
     | 
    
         
            +
                      @values[:#{name}]                  #   @values[:readonly]
         
     | 
| 
      
 75 
     | 
    
         
            +
                    end                                  # end
         
     | 
| 
      
 76 
     | 
    
         
            +
                  CODE
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                Relation::SINGLE_VALUE_METHODS.each do |name|
         
     | 
| 
      
 80 
     | 
    
         
            +
                  class_eval <<-CODE, __FILE__, __LINE__ + 1
         
     | 
| 
      
 81 
     | 
    
         
            +
                    def #{name}_value=(value)            # def readonly_value=(value)
         
     | 
| 
      
 82 
     | 
    
         
            +
                      raise ImmutableRelation if @loaded #   raise ImmutableRelation if @loaded
         
     | 
| 
      
 83 
     | 
    
         
            +
                      @values[:#{name}] = value          #   @values[:readonly] = value
         
     | 
| 
      
 84 
     | 
    
         
            +
                    end                                  # end
         
     | 
| 
      
 85 
     | 
    
         
            +
                  CODE
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                def create_with_value # :nodoc:
         
     | 
| 
      
 89 
     | 
    
         
            +
                  @values[:create_with] || {}
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                alias extensions extending_values
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                # Specify relationships to be included in the result set. For
         
     | 
| 
      
 95 
     | 
    
         
            +
                # example:
         
     | 
| 
      
 96 
     | 
    
         
            +
                #
         
     | 
| 
      
 97 
     | 
    
         
            +
                #   users = User.includes(:address)
         
     | 
| 
      
 98 
     | 
    
         
            +
                #   users.each do |user|
         
     | 
| 
      
 99 
     | 
    
         
            +
                #     user.address.city
         
     | 
| 
      
 100 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 101 
     | 
    
         
            +
                #
         
     | 
| 
      
 102 
     | 
    
         
            +
                # allows you to access the +address+ attribute of the +User+ model without
         
     | 
| 
      
 103 
     | 
    
         
            +
                # firing an additional query. This will often result in a
         
     | 
| 
      
 104 
     | 
    
         
            +
                # performance improvement over a simple +join+.
         
     | 
| 
      
 105 
     | 
    
         
            +
                #
         
     | 
| 
      
 106 
     | 
    
         
            +
                # === conditions
         
     | 
| 
      
 107 
     | 
    
         
            +
                #
         
     | 
| 
      
 108 
     | 
    
         
            +
                # If you want to add conditions to your included models you'll have
         
     | 
| 
      
 109 
     | 
    
         
            +
                # to explicitly reference them. For example:
         
     | 
| 
      
 110 
     | 
    
         
            +
                #
         
     | 
| 
      
 111 
     | 
    
         
            +
                #   User.includes(:posts).where('posts.name = ?', 'example')
         
     | 
| 
      
 112 
     | 
    
         
            +
                #
         
     | 
| 
      
 113 
     | 
    
         
            +
                # Will throw an error, but this will work:
         
     | 
| 
      
 114 
     | 
    
         
            +
                #
         
     | 
| 
      
 115 
     | 
    
         
            +
                #   User.includes(:posts).where('posts.name = ?', 'example').references(:posts)
         
     | 
| 
       15 
116 
     | 
    
         
             
                def includes(*args)
         
     | 
| 
       16 
     | 
    
         
            -
                   
     | 
| 
      
 117 
     | 
    
         
            +
                  check_if_method_has_arguments!("includes", args)
         
     | 
| 
      
 118 
     | 
    
         
            +
                  spawn.includes!(*args)
         
     | 
| 
      
 119 
     | 
    
         
            +
                end
         
     | 
| 
       17 
120 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
      
 121 
     | 
    
         
            +
                def includes!(*args) # :nodoc:
         
     | 
| 
      
 122 
     | 
    
         
            +
                  args.reject! {|a| a.blank? }
         
     | 
| 
       19 
123 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
                   
     | 
| 
       21 
     | 
    
         
            -
                   
     | 
| 
       22 
     | 
    
         
            -
                  relation
         
     | 
| 
      
 124 
     | 
    
         
            +
                  self.includes_values = (includes_values + args).flatten.uniq
         
     | 
| 
      
 125 
     | 
    
         
            +
                  self
         
     | 
| 
       23 
126 
     | 
    
         
             
                end
         
     | 
| 
       24 
127 
     | 
    
         | 
| 
      
 128 
     | 
    
         
            +
                # Forces eager loading by performing a LEFT OUTER JOIN on +args+:
         
     | 
| 
      
 129 
     | 
    
         
            +
                #
         
     | 
| 
      
 130 
     | 
    
         
            +
                #   User.eager_load(:posts)
         
     | 
| 
      
 131 
     | 
    
         
            +
                #   => SELECT "users"."id" AS t0_r0, "users"."name" AS t0_r1, ...
         
     | 
| 
      
 132 
     | 
    
         
            +
                #   FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" =
         
     | 
| 
      
 133 
     | 
    
         
            +
                #   "users"."id"
         
     | 
| 
       25 
134 
     | 
    
         
             
                def eager_load(*args)
         
     | 
| 
       26 
     | 
    
         
            -
                   
     | 
| 
      
 135 
     | 
    
         
            +
                  check_if_method_has_arguments!("eager_load", args)
         
     | 
| 
      
 136 
     | 
    
         
            +
                  spawn.eager_load!(*args)
         
     | 
| 
      
 137 
     | 
    
         
            +
                end
         
     | 
| 
       27 
138 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
                   
     | 
| 
       30 
     | 
    
         
            -
                   
     | 
| 
      
 139 
     | 
    
         
            +
                def eager_load!(*args) # :nodoc:
         
     | 
| 
      
 140 
     | 
    
         
            +
                  self.eager_load_values += args
         
     | 
| 
      
 141 
     | 
    
         
            +
                  self
         
     | 
| 
       31 
142 
     | 
    
         
             
                end
         
     | 
| 
       32 
143 
     | 
    
         | 
| 
      
 144 
     | 
    
         
            +
                # Allows preloading of +args+, in the same way that +includes+ does:
         
     | 
| 
      
 145 
     | 
    
         
            +
                #
         
     | 
| 
      
 146 
     | 
    
         
            +
                #   User.preload(:posts)
         
     | 
| 
      
 147 
     | 
    
         
            +
                #   => SELECT "posts".* FROM "posts" WHERE "posts"."user_id" IN (1, 2, 3)
         
     | 
| 
       33 
148 
     | 
    
         
             
                def preload(*args)
         
     | 
| 
       34 
     | 
    
         
            -
                   
     | 
| 
      
 149 
     | 
    
         
            +
                  check_if_method_has_arguments!("preload", args)
         
     | 
| 
      
 150 
     | 
    
         
            +
                  spawn.preload!(*args)
         
     | 
| 
      
 151 
     | 
    
         
            +
                end
         
     | 
| 
       35 
152 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                   
     | 
| 
       38 
     | 
    
         
            -
                   
     | 
| 
      
 153 
     | 
    
         
            +
                def preload!(*args) # :nodoc:
         
     | 
| 
      
 154 
     | 
    
         
            +
                  self.preload_values += args
         
     | 
| 
      
 155 
     | 
    
         
            +
                  self
         
     | 
| 
      
 156 
     | 
    
         
            +
                end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                # Used to indicate that an association is referenced by an SQL string, and should
         
     | 
| 
      
 159 
     | 
    
         
            +
                # therefore be JOINed in any query rather than loaded separately.
         
     | 
| 
      
 160 
     | 
    
         
            +
                #
         
     | 
| 
      
 161 
     | 
    
         
            +
                #   User.includes(:posts).where("posts.name = 'foo'")
         
     | 
| 
      
 162 
     | 
    
         
            +
                #   # => Doesn't JOIN the posts table, resulting in an error.
         
     | 
| 
      
 163 
     | 
    
         
            +
                #
         
     | 
| 
      
 164 
     | 
    
         
            +
                #   User.includes(:posts).where("posts.name = 'foo'").references(:posts)
         
     | 
| 
      
 165 
     | 
    
         
            +
                #   # => Query now knows the string references posts, so adds a JOIN
         
     | 
| 
      
 166 
     | 
    
         
            +
                def references(*args)
         
     | 
| 
      
 167 
     | 
    
         
            +
                  check_if_method_has_arguments!("references", args)
         
     | 
| 
      
 168 
     | 
    
         
            +
                  spawn.references!(*args)
         
     | 
| 
      
 169 
     | 
    
         
            +
                end
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                def references!(*args) # :nodoc:
         
     | 
| 
      
 172 
     | 
    
         
            +
                  args.flatten!
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
                  self.references_values = (references_values + args.map!(&:to_s)).uniq
         
     | 
| 
      
 175 
     | 
    
         
            +
                  self
         
     | 
| 
       39 
176 
     | 
    
         
             
                end
         
     | 
| 
       40 
177 
     | 
    
         | 
| 
       41 
178 
     | 
    
         
             
                # Works in two unique ways.
         
     | 
| 
       42 
179 
     | 
    
         
             
                #
         
     | 
| 
       43 
180 
     | 
    
         
             
                # First: takes a block so it can be used just like Array#select.
         
     | 
| 
       44 
181 
     | 
    
         
             
                #
         
     | 
| 
       45 
     | 
    
         
            -
                #   Model. 
     | 
| 
      
 182 
     | 
    
         
            +
                #   Model.all.select { |m| m.field == value }
         
     | 
| 
       46 
183 
     | 
    
         
             
                #
         
     | 
| 
       47 
184 
     | 
    
         
             
                # This will build an array of objects from the database for the scope,
         
     | 
| 
       48 
185 
     | 
    
         
             
                # converting them into an array and iterating through them using Array#select.
         
     | 
| 
         @@ -50,8 +187,8 @@ module ActiveRecord 
     | 
|
| 
       50 
187 
     | 
    
         
             
                # Second: Modifies the SELECT statement for the query so that only certain
         
     | 
| 
       51 
188 
     | 
    
         
             
                # fields are retrieved:
         
     | 
| 
       52 
189 
     | 
    
         
             
                #
         
     | 
| 
       53 
     | 
    
         
            -
                #    
     | 
| 
       54 
     | 
    
         
            -
                #   => [#<Model field:value>]
         
     | 
| 
      
 190 
     | 
    
         
            +
                #   Model.select(:field)
         
     | 
| 
      
 191 
     | 
    
         
            +
                #   # => [#<Model field:value>]
         
     | 
| 
       55 
192 
     | 
    
         
             
                #
         
     | 
| 
       56 
193 
     | 
    
         
             
                # Although in the above example it looks as though this method returns an
         
     | 
| 
       57 
194 
     | 
    
         
             
                # array, it actually returns a relation object and can have other query
         
     | 
| 
         @@ -59,38 +196,106 @@ module ActiveRecord 
     | 
|
| 
       59 
196 
     | 
    
         
             
                #
         
     | 
| 
       60 
197 
     | 
    
         
             
                # The argument to the method can also be an array of fields.
         
     | 
| 
       61 
198 
     | 
    
         
             
                #
         
     | 
| 
       62 
     | 
    
         
            -
                #    
     | 
| 
       63 
     | 
    
         
            -
                #   => [#<Model field: "value", other_field: "value", and_one_more: "value">]
         
     | 
| 
      
 199 
     | 
    
         
            +
                #   Model.select(:field, :other_field, :and_one_more)
         
     | 
| 
      
 200 
     | 
    
         
            +
                #   # => [#<Model field: "value", other_field: "value", and_one_more: "value">]
         
     | 
| 
       64 
201 
     | 
    
         
             
                #
         
     | 
| 
       65 
     | 
    
         
            -
                #  
     | 
| 
       66 
     | 
    
         
            -
                # will raise a ActiveModel::MissingAttributeError when the getter method for that attribute is used:
         
     | 
| 
      
 202 
     | 
    
         
            +
                # You can also use one or more strings, which will be used unchanged as SELECT fields.
         
     | 
| 
       67 
203 
     | 
    
         
             
                #
         
     | 
| 
       68 
     | 
    
         
            -
                #    
     | 
| 
       69 
     | 
    
         
            -
                #   =>  
     | 
| 
       70 
     | 
    
         
            -
                 
     | 
| 
      
 204 
     | 
    
         
            +
                #   Model.select('field AS field_one', 'other_field AS field_two')
         
     | 
| 
      
 205 
     | 
    
         
            +
                #   # => [#<Model field: "value", other_field: "value">]
         
     | 
| 
      
 206 
     | 
    
         
            +
                #
         
     | 
| 
      
 207 
     | 
    
         
            +
                # If an alias was specified, it will be accessible from the resulting objects:
         
     | 
| 
      
 208 
     | 
    
         
            +
                #
         
     | 
| 
      
 209 
     | 
    
         
            +
                #   Model.select('field AS field_one').first.field_one
         
     | 
| 
      
 210 
     | 
    
         
            +
                #   # => "value"
         
     | 
| 
      
 211 
     | 
    
         
            +
                #
         
     | 
| 
      
 212 
     | 
    
         
            +
                # Accessing attributes of an object that do not have fields retrieved by a select
         
     | 
| 
      
 213 
     | 
    
         
            +
                # will throw <tt>ActiveModel::MissingAttributeError</tt>:
         
     | 
| 
      
 214 
     | 
    
         
            +
                #
         
     | 
| 
      
 215 
     | 
    
         
            +
                #   Model.select(:field).first.other_field
         
     | 
| 
      
 216 
     | 
    
         
            +
                #   # => ActiveModel::MissingAttributeError: missing attribute: other_field
         
     | 
| 
      
 217 
     | 
    
         
            +
                def select(*fields)
         
     | 
| 
       71 
218 
     | 
    
         
             
                  if block_given?
         
     | 
| 
       72 
     | 
    
         
            -
                    to_a.select {|*block_args|  
     | 
| 
      
 219 
     | 
    
         
            +
                    to_a.select { |*block_args| yield(*block_args) }
         
     | 
| 
       73 
220 
     | 
    
         
             
                  else
         
     | 
| 
       74 
     | 
    
         
            -
                     
     | 
| 
       75 
     | 
    
         
            -
                     
     | 
| 
       76 
     | 
    
         
            -
                    relation
         
     | 
| 
      
 221 
     | 
    
         
            +
                    raise ArgumentError, 'Call this with at least one field' if fields.empty?
         
     | 
| 
      
 222 
     | 
    
         
            +
                    spawn._select!(*fields)
         
     | 
| 
       77 
223 
     | 
    
         
             
                  end
         
     | 
| 
       78 
224 
     | 
    
         
             
                end
         
     | 
| 
       79 
225 
     | 
    
         | 
| 
      
 226 
     | 
    
         
            +
                def _select!(*fields) # :nodoc:
         
     | 
| 
      
 227 
     | 
    
         
            +
                  self.select_values += fields.flatten
         
     | 
| 
      
 228 
     | 
    
         
            +
                  self
         
     | 
| 
      
 229 
     | 
    
         
            +
                end
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                # Allows to specify a group attribute:
         
     | 
| 
      
 232 
     | 
    
         
            +
                #
         
     | 
| 
      
 233 
     | 
    
         
            +
                #   User.group(:name)
         
     | 
| 
      
 234 
     | 
    
         
            +
                #   => SELECT "users".* FROM "users" GROUP BY name
         
     | 
| 
      
 235 
     | 
    
         
            +
                #
         
     | 
| 
      
 236 
     | 
    
         
            +
                # Returns an array with distinct records based on the +group+ attribute:
         
     | 
| 
      
 237 
     | 
    
         
            +
                #
         
     | 
| 
      
 238 
     | 
    
         
            +
                #   User.select([:id, :name])
         
     | 
| 
      
 239 
     | 
    
         
            +
                #   => [#<User id: 1, name: "Oscar">, #<User id: 2, name: "Oscar">, #<User id: 3, name: "Foo">
         
     | 
| 
      
 240 
     | 
    
         
            +
                #
         
     | 
| 
      
 241 
     | 
    
         
            +
                #   User.group(:name)
         
     | 
| 
      
 242 
     | 
    
         
            +
                #   => [#<User id: 3, name: "Foo", ...>, #<User id: 2, name: "Oscar", ...>]
         
     | 
| 
      
 243 
     | 
    
         
            +
                #
         
     | 
| 
      
 244 
     | 
    
         
            +
                #   User.group('name AS grouped_name, age')
         
     | 
| 
      
 245 
     | 
    
         
            +
                #   => [#<User id: 3, name: "Foo", age: 21, ...>, #<User id: 2, name: "Oscar", age: 21, ...>, #<User id: 5, name: "Foo", age: 23, ...>]
         
     | 
| 
       80 
246 
     | 
    
         
             
                def group(*args)
         
     | 
| 
       81 
     | 
    
         
            -
                   
     | 
| 
      
 247 
     | 
    
         
            +
                  check_if_method_has_arguments!("group", args)
         
     | 
| 
      
 248 
     | 
    
         
            +
                  spawn.group!(*args)
         
     | 
| 
      
 249 
     | 
    
         
            +
                end
         
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
      
 251 
     | 
    
         
            +
                def group!(*args) # :nodoc:
         
     | 
| 
      
 252 
     | 
    
         
            +
                  args.flatten!
         
     | 
| 
       82 
253 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
                   
     | 
| 
       84 
     | 
    
         
            -
                   
     | 
| 
       85 
     | 
    
         
            -
                  relation
         
     | 
| 
      
 254 
     | 
    
         
            +
                  self.group_values += args
         
     | 
| 
      
 255 
     | 
    
         
            +
                  self
         
     | 
| 
       86 
256 
     | 
    
         
             
                end
         
     | 
| 
       87 
257 
     | 
    
         | 
| 
      
 258 
     | 
    
         
            +
                # Allows to specify an order attribute:
         
     | 
| 
      
 259 
     | 
    
         
            +
                #
         
     | 
| 
      
 260 
     | 
    
         
            +
                #   User.order('name')
         
     | 
| 
      
 261 
     | 
    
         
            +
                #   => SELECT "users".* FROM "users" ORDER BY name
         
     | 
| 
      
 262 
     | 
    
         
            +
                #
         
     | 
| 
      
 263 
     | 
    
         
            +
                #   User.order('name DESC')
         
     | 
| 
      
 264 
     | 
    
         
            +
                #   => SELECT "users".* FROM "users" ORDER BY name DESC
         
     | 
| 
      
 265 
     | 
    
         
            +
                #
         
     | 
| 
      
 266 
     | 
    
         
            +
                #   User.order('name DESC, email')
         
     | 
| 
      
 267 
     | 
    
         
            +
                #   => SELECT "users".* FROM "users" ORDER BY name DESC, email
         
     | 
| 
      
 268 
     | 
    
         
            +
                #
         
     | 
| 
      
 269 
     | 
    
         
            +
                #   User.order(:name)
         
     | 
| 
      
 270 
     | 
    
         
            +
                #   => SELECT "users".* FROM "users" ORDER BY "users"."name" ASC
         
     | 
| 
      
 271 
     | 
    
         
            +
                #
         
     | 
| 
      
 272 
     | 
    
         
            +
                #   User.order(email: :desc)
         
     | 
| 
      
 273 
     | 
    
         
            +
                #   => SELECT "users".* FROM "users" ORDER BY "users"."email" DESC
         
     | 
| 
      
 274 
     | 
    
         
            +
                #
         
     | 
| 
      
 275 
     | 
    
         
            +
                #   User.order(:name, email: :desc)
         
     | 
| 
      
 276 
     | 
    
         
            +
                #   => SELECT "users".* FROM "users" ORDER BY "users"."name" ASC, "users"."email" DESC
         
     | 
| 
       88 
277 
     | 
    
         
             
                def order(*args)
         
     | 
| 
       89 
     | 
    
         
            -
                   
     | 
| 
      
 278 
     | 
    
         
            +
                  check_if_method_has_arguments!("order", args)
         
     | 
| 
      
 279 
     | 
    
         
            +
                  spawn.order!(*args)
         
     | 
| 
      
 280 
     | 
    
         
            +
                end
         
     | 
| 
      
 281 
     | 
    
         
            +
             
     | 
| 
      
 282 
     | 
    
         
            +
                def order!(*args) # :nodoc:
         
     | 
| 
      
 283 
     | 
    
         
            +
                  args.flatten!
         
     | 
| 
      
 284 
     | 
    
         
            +
                  validate_order_args args
         
     | 
| 
      
 285 
     | 
    
         
            +
             
     | 
| 
      
 286 
     | 
    
         
            +
                  references = args.reject { |arg| Arel::Node === arg }
         
     | 
| 
      
 287 
     | 
    
         
            +
                  references.map! { |arg| arg =~ /^([a-zA-Z]\w*)\.(\w+)/ && $1 }.compact!
         
     | 
| 
      
 288 
     | 
    
         
            +
                  references!(references) if references.any?
         
     | 
| 
       90 
289 
     | 
    
         | 
| 
       91 
     | 
    
         
            -
                   
     | 
| 
       92 
     | 
    
         
            -
                   
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
      
 290 
     | 
    
         
            +
                  # if a symbol is given we prepend the quoted table name
         
     | 
| 
      
 291 
     | 
    
         
            +
                  args = args.map! { |arg|
         
     | 
| 
      
 292 
     | 
    
         
            +
                    arg.is_a?(Symbol) ?
         
     | 
| 
      
 293 
     | 
    
         
            +
                      Arel::Nodes::Ascending.new(klass.arel_table[arg]) :
         
     | 
| 
      
 294 
     | 
    
         
            +
                      arg
         
     | 
| 
      
 295 
     | 
    
         
            +
                  }
         
     | 
| 
      
 296 
     | 
    
         
            +
             
     | 
| 
      
 297 
     | 
    
         
            +
                  self.order_values += args
         
     | 
| 
      
 298 
     | 
    
         
            +
                  self
         
     | 
| 
       94 
299 
     | 
    
         
             
                end
         
     | 
| 
       95 
300 
     | 
    
         | 
| 
       96 
301 
     | 
    
         
             
                # Replaces any existing order defined on the relation with the specified order.
         
     | 
| 
         @@ -102,90 +307,413 @@ module ActiveRecord 
     | 
|
| 
       102 
307 
     | 
    
         
             
                #   User.order('email DESC').reorder('id ASC').order('name ASC')
         
     | 
| 
       103 
308 
     | 
    
         
             
                #
         
     | 
| 
       104 
309 
     | 
    
         
             
                # generates a query with 'ORDER BY id ASC, name ASC'.
         
     | 
| 
       105 
     | 
    
         
            -
                #
         
     | 
| 
       106 
310 
     | 
    
         
             
                def reorder(*args)
         
     | 
| 
       107 
     | 
    
         
            -
                   
     | 
| 
      
 311 
     | 
    
         
            +
                  check_if_method_has_arguments!("reorder", args)
         
     | 
| 
      
 312 
     | 
    
         
            +
                  spawn.reorder!(*args)
         
     | 
| 
      
 313 
     | 
    
         
            +
                end
         
     | 
| 
      
 314 
     | 
    
         
            +
             
     | 
| 
      
 315 
     | 
    
         
            +
                def reorder!(*args) # :nodoc:
         
     | 
| 
      
 316 
     | 
    
         
            +
                  args.flatten!
         
     | 
| 
      
 317 
     | 
    
         
            +
                  validate_order_args args
         
     | 
| 
       108 
318 
     | 
    
         | 
| 
       109 
     | 
    
         
            -
                   
     | 
| 
       110 
     | 
    
         
            -
                   
     | 
| 
       111 
     | 
    
         
            -
                   
     | 
| 
       112 
     | 
    
         
            -
                  relation
         
     | 
| 
      
 319 
     | 
    
         
            +
                  self.reordering_value = true
         
     | 
| 
      
 320 
     | 
    
         
            +
                  self.order_values = args
         
     | 
| 
      
 321 
     | 
    
         
            +
                  self
         
     | 
| 
       113 
322 
     | 
    
         
             
                end
         
     | 
| 
       114 
323 
     | 
    
         | 
| 
       115 
     | 
    
         
            -
                 
     | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
      
 324 
     | 
    
         
            +
                VALID_UNSCOPING_VALUES = Set.new([:where, :select, :group, :order, :lock,
         
     | 
| 
      
 325 
     | 
    
         
            +
                                                 :limit, :offset, :joins, :includes, :from,
         
     | 
| 
      
 326 
     | 
    
         
            +
                                                 :readonly, :having])
         
     | 
| 
       117 
327 
     | 
    
         | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
      
 328 
     | 
    
         
            +
                # Removes an unwanted relation that is already defined on a chain of relations.
         
     | 
| 
      
 329 
     | 
    
         
            +
                # This is useful when passing around chains of relations and would like to
         
     | 
| 
      
 330 
     | 
    
         
            +
                # modify the relations without reconstructing the entire chain.
         
     | 
| 
      
 331 
     | 
    
         
            +
                #
         
     | 
| 
      
 332 
     | 
    
         
            +
                #   User.order('email DESC').unscope(:order) == User.all
         
     | 
| 
      
 333 
     | 
    
         
            +
                #
         
     | 
| 
      
 334 
     | 
    
         
            +
                # The method arguments are symbols which correspond to the names of the methods
         
     | 
| 
      
 335 
     | 
    
         
            +
                # which should be unscoped. The valid arguments are given in VALID_UNSCOPING_VALUES.
         
     | 
| 
      
 336 
     | 
    
         
            +
                # The method can also be called with multiple arguments. For example:
         
     | 
| 
      
 337 
     | 
    
         
            +
                #
         
     | 
| 
      
 338 
     | 
    
         
            +
                #   User.order('email DESC').select('id').where(name: "John")
         
     | 
| 
      
 339 
     | 
    
         
            +
                #       .unscope(:order, :select, :where) == User.all
         
     | 
| 
      
 340 
     | 
    
         
            +
                #
         
     | 
| 
      
 341 
     | 
    
         
            +
                # One can additionally pass a hash as an argument to unscope specific :where values.
         
     | 
| 
      
 342 
     | 
    
         
            +
                # This is done by passing a hash with a single key-value pair. The key should be
         
     | 
| 
      
 343 
     | 
    
         
            +
                # :where and the value should be the where value to unscope. For example:
         
     | 
| 
      
 344 
     | 
    
         
            +
                #
         
     | 
| 
      
 345 
     | 
    
         
            +
                #   User.where(name: "John", active: true).unscope(where: :name)
         
     | 
| 
      
 346 
     | 
    
         
            +
                #       == User.where(active: true)
         
     | 
| 
      
 347 
     | 
    
         
            +
                #
         
     | 
| 
      
 348 
     | 
    
         
            +
                # Note that this method is more generalized than ActiveRecord::SpawnMethods#except
         
     | 
| 
      
 349 
     | 
    
         
            +
                # because #except will only affect a particular relation's values. It won't wipe
         
     | 
| 
      
 350 
     | 
    
         
            +
                # the order, grouping, etc. when that relation is merged. For example:
         
     | 
| 
      
 351 
     | 
    
         
            +
                #
         
     | 
| 
      
 352 
     | 
    
         
            +
                #   Post.comments.except(:order)
         
     | 
| 
      
 353 
     | 
    
         
            +
                #
         
     | 
| 
      
 354 
     | 
    
         
            +
                # will still have an order if it comes from the default_scope on Comment.
         
     | 
| 
      
 355 
     | 
    
         
            +
                def unscope(*args)
         
     | 
| 
      
 356 
     | 
    
         
            +
                  check_if_method_has_arguments!("unscope", args)
         
     | 
| 
      
 357 
     | 
    
         
            +
                  spawn.unscope!(*args)
         
     | 
| 
      
 358 
     | 
    
         
            +
                end
         
     | 
| 
       119 
359 
     | 
    
         | 
| 
      
 360 
     | 
    
         
            +
                def unscope!(*args) # :nodoc:
         
     | 
| 
       120 
361 
     | 
    
         
             
                  args.flatten!
         
     | 
| 
       121 
     | 
    
         
            -
                  relation.joins_values += args
         
     | 
| 
       122 
362 
     | 
    
         | 
| 
       123 
     | 
    
         
            -
                   
     | 
| 
      
 363 
     | 
    
         
            +
                  args.each do |scope|
         
     | 
| 
      
 364 
     | 
    
         
            +
                    case scope
         
     | 
| 
      
 365 
     | 
    
         
            +
                    when Symbol
         
     | 
| 
      
 366 
     | 
    
         
            +
                      symbol_unscoping(scope)
         
     | 
| 
      
 367 
     | 
    
         
            +
                    when Hash
         
     | 
| 
      
 368 
     | 
    
         
            +
                      scope.each do |key, target_value|
         
     | 
| 
      
 369 
     | 
    
         
            +
                        if key != :where
         
     | 
| 
      
 370 
     | 
    
         
            +
                          raise ArgumentError, "Hash arguments in .unscope(*args) must have :where as the key."
         
     | 
| 
      
 371 
     | 
    
         
            +
                        end
         
     | 
| 
      
 372 
     | 
    
         
            +
             
     | 
| 
      
 373 
     | 
    
         
            +
                        Array(target_value).each do |val|
         
     | 
| 
      
 374 
     | 
    
         
            +
                          where_unscoping(val)
         
     | 
| 
      
 375 
     | 
    
         
            +
                        end
         
     | 
| 
      
 376 
     | 
    
         
            +
                      end
         
     | 
| 
      
 377 
     | 
    
         
            +
                    else
         
     | 
| 
      
 378 
     | 
    
         
            +
                      raise ArgumentError, "Unrecognized scoping: #{args.inspect}. Use .unscope(where: :attribute_name) or .unscope(:order), for example."
         
     | 
| 
      
 379 
     | 
    
         
            +
                    end
         
     | 
| 
      
 380 
     | 
    
         
            +
                  end
         
     | 
| 
      
 381 
     | 
    
         
            +
             
     | 
| 
      
 382 
     | 
    
         
            +
                  self
         
     | 
| 
      
 383 
     | 
    
         
            +
                end
         
     | 
| 
      
 384 
     | 
    
         
            +
             
     | 
| 
      
 385 
     | 
    
         
            +
                # Performs a joins on +args+:
         
     | 
| 
      
 386 
     | 
    
         
            +
                #
         
     | 
| 
      
 387 
     | 
    
         
            +
                #   User.joins(:posts)
         
     | 
| 
      
 388 
     | 
    
         
            +
                #   => SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id"
         
     | 
| 
      
 389 
     | 
    
         
            +
                #
         
     | 
| 
      
 390 
     | 
    
         
            +
                # You can use strings in order to customize your joins:
         
     | 
| 
      
 391 
     | 
    
         
            +
                #
         
     | 
| 
      
 392 
     | 
    
         
            +
                #   User.joins("LEFT JOIN bookmarks ON bookmarks.bookmarkable_type = 'Post' AND bookmarks.user_id = users.id")
         
     | 
| 
      
 393 
     | 
    
         
            +
                #   => SELECT "users".* FROM "users" LEFT JOIN bookmarks ON bookmarks.bookmarkable_type = 'Post' AND bookmarks.user_id = users.id
         
     | 
| 
      
 394 
     | 
    
         
            +
                def joins(*args)
         
     | 
| 
      
 395 
     | 
    
         
            +
                  check_if_method_has_arguments!("joins", args)
         
     | 
| 
      
 396 
     | 
    
         
            +
                  spawn.joins!(*args.compact.flatten)
         
     | 
| 
      
 397 
     | 
    
         
            +
                end
         
     | 
| 
      
 398 
     | 
    
         
            +
             
     | 
| 
      
 399 
     | 
    
         
            +
                def joins!(*args) # :nodoc:
         
     | 
| 
      
 400 
     | 
    
         
            +
                  self.joins_values += args
         
     | 
| 
      
 401 
     | 
    
         
            +
                  self
         
     | 
| 
       124 
402 
     | 
    
         
             
                end
         
     | 
| 
       125 
403 
     | 
    
         | 
| 
       126 
404 
     | 
    
         
             
                def bind(value)
         
     | 
| 
       127 
     | 
    
         
            -
                   
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
      
 405 
     | 
    
         
            +
                  spawn.bind!(value)
         
     | 
| 
      
 406 
     | 
    
         
            +
                end
         
     | 
| 
      
 407 
     | 
    
         
            +
             
     | 
| 
      
 408 
     | 
    
         
            +
                def bind!(value) # :nodoc:
         
     | 
| 
      
 409 
     | 
    
         
            +
                  self.bind_values += [value]
         
     | 
| 
      
 410 
     | 
    
         
            +
                  self
         
     | 
| 
      
 411 
     | 
    
         
            +
                end
         
     | 
| 
      
 412 
     | 
    
         
            +
             
     | 
| 
      
 413 
     | 
    
         
            +
                # Returns a new relation, which is the result of filtering the current relation
         
     | 
| 
      
 414 
     | 
    
         
            +
                # according to the conditions in the arguments.
         
     | 
| 
      
 415 
     | 
    
         
            +
                #
         
     | 
| 
      
 416 
     | 
    
         
            +
                # #where accepts conditions in one of several formats. In the examples below, the resulting
         
     | 
| 
      
 417 
     | 
    
         
            +
                # SQL is given as an illustration; the actual query generated may be different depending
         
     | 
| 
      
 418 
     | 
    
         
            +
                # on the database adapter.
         
     | 
| 
      
 419 
     | 
    
         
            +
                #
         
     | 
| 
      
 420 
     | 
    
         
            +
                # === string
         
     | 
| 
      
 421 
     | 
    
         
            +
                #
         
     | 
| 
      
 422 
     | 
    
         
            +
                # A single string, without additional arguments, is passed to the query
         
     | 
| 
      
 423 
     | 
    
         
            +
                # constructor as a SQL fragment, and used in the where clause of the query.
         
     | 
| 
      
 424 
     | 
    
         
            +
                #
         
     | 
| 
      
 425 
     | 
    
         
            +
                #    Client.where("orders_count = '2'")
         
     | 
| 
      
 426 
     | 
    
         
            +
                #    # SELECT * from clients where orders_count = '2';
         
     | 
| 
      
 427 
     | 
    
         
            +
                #
         
     | 
| 
      
 428 
     | 
    
         
            +
                # Note that building your own string from user input may expose your application
         
     | 
| 
      
 429 
     | 
    
         
            +
                # to injection attacks if not done properly. As an alternative, it is recommended
         
     | 
| 
      
 430 
     | 
    
         
            +
                # to use one of the following methods.
         
     | 
| 
      
 431 
     | 
    
         
            +
                #
         
     | 
| 
      
 432 
     | 
    
         
            +
                # === array
         
     | 
| 
      
 433 
     | 
    
         
            +
                #
         
     | 
| 
      
 434 
     | 
    
         
            +
                # If an array is passed, then the first element of the array is treated as a template, and
         
     | 
| 
      
 435 
     | 
    
         
            +
                # the remaining elements are inserted into the template to generate the condition.
         
     | 
| 
      
 436 
     | 
    
         
            +
                # Active Record takes care of building the query to avoid injection attacks, and will
         
     | 
| 
      
 437 
     | 
    
         
            +
                # convert from the ruby type to the database type where needed. Elements are inserted
         
     | 
| 
      
 438 
     | 
    
         
            +
                # into the string in the order in which they appear.
         
     | 
| 
      
 439 
     | 
    
         
            +
                #
         
     | 
| 
      
 440 
     | 
    
         
            +
                #   User.where(["name = ? and email = ?", "Joe", "joe@example.com"])
         
     | 
| 
      
 441 
     | 
    
         
            +
                #   # SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';
         
     | 
| 
      
 442 
     | 
    
         
            +
                #
         
     | 
| 
      
 443 
     | 
    
         
            +
                # Alternatively, you can use named placeholders in the template, and pass a hash as the
         
     | 
| 
      
 444 
     | 
    
         
            +
                # second element of the array. The names in the template are replaced with the corresponding
         
     | 
| 
      
 445 
     | 
    
         
            +
                # values from the hash.
         
     | 
| 
      
 446 
     | 
    
         
            +
                #
         
     | 
| 
      
 447 
     | 
    
         
            +
                #   User.where(["name = :name and email = :email", { name: "Joe", email: "joe@example.com" }])
         
     | 
| 
      
 448 
     | 
    
         
            +
                #   # SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';
         
     | 
| 
      
 449 
     | 
    
         
            +
                #
         
     | 
| 
      
 450 
     | 
    
         
            +
                # This can make for more readable code in complex queries.
         
     | 
| 
      
 451 
     | 
    
         
            +
                #
         
     | 
| 
      
 452 
     | 
    
         
            +
                # Lastly, you can use sprintf-style % escapes in the template. This works slightly differently
         
     | 
| 
      
 453 
     | 
    
         
            +
                # than the previous methods; you are responsible for ensuring that the values in the template
         
     | 
| 
      
 454 
     | 
    
         
            +
                # are properly quoted. The values are passed to the connector for quoting, but the caller
         
     | 
| 
      
 455 
     | 
    
         
            +
                # is responsible for ensuring they are enclosed in quotes in the resulting SQL. After quoting,
         
     | 
| 
      
 456 
     | 
    
         
            +
                # the values are inserted using the same escapes as the Ruby core method <tt>Kernel::sprintf</tt>.
         
     | 
| 
      
 457 
     | 
    
         
            +
                #
         
     | 
| 
      
 458 
     | 
    
         
            +
                #   User.where(["name = '%s' and email = '%s'", "Joe", "joe@example.com"])
         
     | 
| 
      
 459 
     | 
    
         
            +
                #   # SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';
         
     | 
| 
      
 460 
     | 
    
         
            +
                #
         
     | 
| 
      
 461 
     | 
    
         
            +
                # If #where is called with multiple arguments, these are treated as if they were passed as
         
     | 
| 
      
 462 
     | 
    
         
            +
                # the elements of a single array.
         
     | 
| 
      
 463 
     | 
    
         
            +
                #
         
     | 
| 
      
 464 
     | 
    
         
            +
                #   User.where("name = :name and email = :email", { name: "Joe", email: "joe@example.com" })
         
     | 
| 
      
 465 
     | 
    
         
            +
                #   # SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';
         
     | 
| 
      
 466 
     | 
    
         
            +
                #
         
     | 
| 
      
 467 
     | 
    
         
            +
                # When using strings to specify conditions, you can use any operator available from
         
     | 
| 
      
 468 
     | 
    
         
            +
                # the database. While this provides the most flexibility, you can also unintentionally introduce
         
     | 
| 
      
 469 
     | 
    
         
            +
                # dependencies on the underlying database. If your code is intended for general consumption,
         
     | 
| 
      
 470 
     | 
    
         
            +
                # test with multiple database backends.
         
     | 
| 
      
 471 
     | 
    
         
            +
                #
         
     | 
| 
      
 472 
     | 
    
         
            +
                # === hash
         
     | 
| 
      
 473 
     | 
    
         
            +
                #
         
     | 
| 
      
 474 
     | 
    
         
            +
                # #where will also accept a hash condition, in which the keys are fields and the values
         
     | 
| 
      
 475 
     | 
    
         
            +
                # are values to be searched for.
         
     | 
| 
      
 476 
     | 
    
         
            +
                #
         
     | 
| 
      
 477 
     | 
    
         
            +
                # Fields can be symbols or strings. Values can be single values, arrays, or ranges.
         
     | 
| 
      
 478 
     | 
    
         
            +
                #
         
     | 
| 
      
 479 
     | 
    
         
            +
                #    User.where({ name: "Joe", email: "joe@example.com" })
         
     | 
| 
      
 480 
     | 
    
         
            +
                #    # SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com'
         
     | 
| 
      
 481 
     | 
    
         
            +
                #
         
     | 
| 
      
 482 
     | 
    
         
            +
                #    User.where({ name: ["Alice", "Bob"]})
         
     | 
| 
      
 483 
     | 
    
         
            +
                #    # SELECT * FROM users WHERE name IN ('Alice', 'Bob')
         
     | 
| 
      
 484 
     | 
    
         
            +
                #
         
     | 
| 
      
 485 
     | 
    
         
            +
                #    User.where({ created_at: (Time.now.midnight - 1.day)..Time.now.midnight })
         
     | 
| 
      
 486 
     | 
    
         
            +
                #    # SELECT * FROM users WHERE (created_at BETWEEN '2012-06-09 07:00:00.000000' AND '2012-06-10 07:00:00.000000')
         
     | 
| 
      
 487 
     | 
    
         
            +
                #
         
     | 
| 
      
 488 
     | 
    
         
            +
                # In the case of a belongs_to relationship, an association key can be used
         
     | 
| 
      
 489 
     | 
    
         
            +
                # to specify the model if an ActiveRecord object is used as the value.
         
     | 
| 
      
 490 
     | 
    
         
            +
                #
         
     | 
| 
      
 491 
     | 
    
         
            +
                #    author = Author.find(1)
         
     | 
| 
      
 492 
     | 
    
         
            +
                #
         
     | 
| 
      
 493 
     | 
    
         
            +
                #    # The following queries will be equivalent:
         
     | 
| 
      
 494 
     | 
    
         
            +
                #    Post.where(author: author)
         
     | 
| 
      
 495 
     | 
    
         
            +
                #    Post.where(author_id: author)
         
     | 
| 
      
 496 
     | 
    
         
            +
                #
         
     | 
| 
      
 497 
     | 
    
         
            +
                # This also works with polymorphic belongs_to relationships:
         
     | 
| 
      
 498 
     | 
    
         
            +
                #
         
     | 
| 
      
 499 
     | 
    
         
            +
                #    treasure = Treasure.create(name: 'gold coins')
         
     | 
| 
      
 500 
     | 
    
         
            +
                #    treasure.price_estimates << PriceEstimate.create(price: 125)
         
     | 
| 
      
 501 
     | 
    
         
            +
                #
         
     | 
| 
      
 502 
     | 
    
         
            +
                #    # The following queries will be equivalent:
         
     | 
| 
      
 503 
     | 
    
         
            +
                #    PriceEstimate.where(estimate_of: treasure)
         
     | 
| 
      
 504 
     | 
    
         
            +
                #    PriceEstimate.where(estimate_of_type: 'Treasure', estimate_of_id: treasure)
         
     | 
| 
      
 505 
     | 
    
         
            +
                #
         
     | 
| 
      
 506 
     | 
    
         
            +
                # === Joins
         
     | 
| 
      
 507 
     | 
    
         
            +
                #
         
     | 
| 
      
 508 
     | 
    
         
            +
                # If the relation is the result of a join, you may create a condition which uses any of the
         
     | 
| 
      
 509 
     | 
    
         
            +
                # tables in the join. For string and array conditions, use the table name in the condition.
         
     | 
| 
      
 510 
     | 
    
         
            +
                #
         
     | 
| 
      
 511 
     | 
    
         
            +
                #    User.joins(:posts).where("posts.created_at < ?", Time.now)
         
     | 
| 
      
 512 
     | 
    
         
            +
                #
         
     | 
| 
      
 513 
     | 
    
         
            +
                # For hash conditions, you can either use the table name in the key, or use a sub-hash.
         
     | 
| 
      
 514 
     | 
    
         
            +
                #
         
     | 
| 
      
 515 
     | 
    
         
            +
                #    User.joins(:posts).where({ "posts.published" => true })
         
     | 
| 
      
 516 
     | 
    
         
            +
                #    User.joins(:posts).where({ posts: { published: true } })
         
     | 
| 
      
 517 
     | 
    
         
            +
                #
         
     | 
| 
      
 518 
     | 
    
         
            +
                # === no argument
         
     | 
| 
      
 519 
     | 
    
         
            +
                #
         
     | 
| 
      
 520 
     | 
    
         
            +
                # If no argument is passed, #where returns a new instance of WhereChain, that
         
     | 
| 
      
 521 
     | 
    
         
            +
                # can be chained with #not to return a new relation that negates the where clause.
         
     | 
| 
      
 522 
     | 
    
         
            +
                #
         
     | 
| 
      
 523 
     | 
    
         
            +
                #    User.where.not(name: "Jon")
         
     | 
| 
      
 524 
     | 
    
         
            +
                #    # SELECT * FROM users WHERE name != 'Jon'
         
     | 
| 
      
 525 
     | 
    
         
            +
                #
         
     | 
| 
      
 526 
     | 
    
         
            +
                # See WhereChain for more details on #not.
         
     | 
| 
      
 527 
     | 
    
         
            +
                #
         
     | 
| 
      
 528 
     | 
    
         
            +
                # === blank condition
         
     | 
| 
      
 529 
     | 
    
         
            +
                #
         
     | 
| 
      
 530 
     | 
    
         
            +
                # If the condition is any blank-ish object, then #where is a no-op and returns
         
     | 
| 
      
 531 
     | 
    
         
            +
                # the current relation.
         
     | 
| 
      
 532 
     | 
    
         
            +
                def where(opts = :chain, *rest)
         
     | 
| 
      
 533 
     | 
    
         
            +
                  if opts == :chain
         
     | 
| 
      
 534 
     | 
    
         
            +
                    WhereChain.new(spawn)
         
     | 
| 
      
 535 
     | 
    
         
            +
                  elsif opts.blank?
         
     | 
| 
      
 536 
     | 
    
         
            +
                    self
         
     | 
| 
      
 537 
     | 
    
         
            +
                  else
         
     | 
| 
      
 538 
     | 
    
         
            +
                    spawn.where!(opts, *rest)
         
     | 
| 
      
 539 
     | 
    
         
            +
                  end
         
     | 
| 
       130 
540 
     | 
    
         
             
                end
         
     | 
| 
       131 
541 
     | 
    
         | 
| 
       132 
     | 
    
         
            -
                def where(opts, *rest)
         
     | 
| 
       133 
     | 
    
         
            -
                   
     | 
| 
      
 542 
     | 
    
         
            +
                def where!(opts = :chain, *rest) # :nodoc:
         
     | 
| 
      
 543 
     | 
    
         
            +
                  if opts == :chain
         
     | 
| 
      
 544 
     | 
    
         
            +
                    WhereChain.new(self)
         
     | 
| 
      
 545 
     | 
    
         
            +
                  else
         
     | 
| 
      
 546 
     | 
    
         
            +
                    if Hash === opts
         
     | 
| 
      
 547 
     | 
    
         
            +
                      opts = sanitize_forbidden_attributes(opts)
         
     | 
| 
      
 548 
     | 
    
         
            +
                      references!(PredicateBuilder.references(opts))
         
     | 
| 
      
 549 
     | 
    
         
            +
                    end
         
     | 
| 
       134 
550 
     | 
    
         | 
| 
       135 
     | 
    
         
            -
             
     | 
| 
       136 
     | 
    
         
            -
             
     | 
| 
       137 
     | 
    
         
            -
                   
     | 
| 
      
 551 
     | 
    
         
            +
                    self.where_values += build_where(opts, rest)
         
     | 
| 
      
 552 
     | 
    
         
            +
                    self
         
     | 
| 
      
 553 
     | 
    
         
            +
                  end
         
     | 
| 
       138 
554 
     | 
    
         
             
                end
         
     | 
| 
       139 
555 
     | 
    
         | 
| 
      
 556 
     | 
    
         
            +
                # Allows to specify a HAVING clause. Note that you can't use HAVING
         
     | 
| 
      
 557 
     | 
    
         
            +
                # without also specifying a GROUP clause.
         
     | 
| 
      
 558 
     | 
    
         
            +
                #
         
     | 
| 
      
 559 
     | 
    
         
            +
                #   Order.having('SUM(price) > 30').group('user_id')
         
     | 
| 
       140 
560 
     | 
    
         
             
                def having(opts, *rest)
         
     | 
| 
       141 
     | 
    
         
            -
                   
     | 
| 
      
 561 
     | 
    
         
            +
                  opts.blank? ? self : spawn.having!(opts, *rest)
         
     | 
| 
      
 562 
     | 
    
         
            +
                end
         
     | 
| 
      
 563 
     | 
    
         
            +
             
     | 
| 
      
 564 
     | 
    
         
            +
                def having!(opts, *rest) # :nodoc:
         
     | 
| 
      
 565 
     | 
    
         
            +
                  references!(PredicateBuilder.references(opts)) if Hash === opts
         
     | 
| 
       142 
566 
     | 
    
         | 
| 
       143 
     | 
    
         
            -
                   
     | 
| 
       144 
     | 
    
         
            -
                   
     | 
| 
       145 
     | 
    
         
            -
                  relation
         
     | 
| 
      
 567 
     | 
    
         
            +
                  self.having_values += build_where(opts, rest)
         
     | 
| 
      
 568 
     | 
    
         
            +
                  self
         
     | 
| 
       146 
569 
     | 
    
         
             
                end
         
     | 
| 
       147 
570 
     | 
    
         | 
| 
      
 571 
     | 
    
         
            +
                # Specifies a limit for the number of records to retrieve.
         
     | 
| 
      
 572 
     | 
    
         
            +
                #
         
     | 
| 
      
 573 
     | 
    
         
            +
                #   User.limit(10) # generated SQL has 'LIMIT 10'
         
     | 
| 
      
 574 
     | 
    
         
            +
                #
         
     | 
| 
      
 575 
     | 
    
         
            +
                #   User.limit(10).limit(20) # generated SQL has 'LIMIT 20'
         
     | 
| 
       148 
576 
     | 
    
         
             
                def limit(value)
         
     | 
| 
       149 
     | 
    
         
            -
                   
     | 
| 
       150 
     | 
    
         
            -
             
     | 
| 
       151 
     | 
    
         
            -
             
     | 
| 
      
 577 
     | 
    
         
            +
                  spawn.limit!(value)
         
     | 
| 
      
 578 
     | 
    
         
            +
                end
         
     | 
| 
      
 579 
     | 
    
         
            +
             
     | 
| 
      
 580 
     | 
    
         
            +
                def limit!(value) # :nodoc:
         
     | 
| 
      
 581 
     | 
    
         
            +
                  self.limit_value = value
         
     | 
| 
      
 582 
     | 
    
         
            +
                  self
         
     | 
| 
       152 
583 
     | 
    
         
             
                end
         
     | 
| 
       153 
584 
     | 
    
         | 
| 
      
 585 
     | 
    
         
            +
                # Specifies the number of rows to skip before returning rows.
         
     | 
| 
      
 586 
     | 
    
         
            +
                #
         
     | 
| 
      
 587 
     | 
    
         
            +
                #   User.offset(10) # generated SQL has "OFFSET 10"
         
     | 
| 
      
 588 
     | 
    
         
            +
                #
         
     | 
| 
      
 589 
     | 
    
         
            +
                # Should be used with order.
         
     | 
| 
      
 590 
     | 
    
         
            +
                #
         
     | 
| 
      
 591 
     | 
    
         
            +
                #   User.offset(10).order("name ASC")
         
     | 
| 
       154 
592 
     | 
    
         
             
                def offset(value)
         
     | 
| 
       155 
     | 
    
         
            -
                   
     | 
| 
       156 
     | 
    
         
            -
                  relation.offset_value = value
         
     | 
| 
       157 
     | 
    
         
            -
                  relation
         
     | 
| 
      
 593 
     | 
    
         
            +
                  spawn.offset!(value)
         
     | 
| 
       158 
594 
     | 
    
         
             
                end
         
     | 
| 
       159 
595 
     | 
    
         | 
| 
      
 596 
     | 
    
         
            +
                def offset!(value) # :nodoc:
         
     | 
| 
      
 597 
     | 
    
         
            +
                  self.offset_value = value
         
     | 
| 
      
 598 
     | 
    
         
            +
                  self
         
     | 
| 
      
 599 
     | 
    
         
            +
                end
         
     | 
| 
      
 600 
     | 
    
         
            +
             
     | 
| 
      
 601 
     | 
    
         
            +
                # Specifies locking settings (default to +true+). For more information
         
     | 
| 
      
 602 
     | 
    
         
            +
                # on locking, please see +ActiveRecord::Locking+.
         
     | 
| 
       160 
603 
     | 
    
         
             
                def lock(locks = true)
         
     | 
| 
       161 
     | 
    
         
            -
                   
     | 
| 
      
 604 
     | 
    
         
            +
                  spawn.lock!(locks)
         
     | 
| 
      
 605 
     | 
    
         
            +
                end
         
     | 
| 
       162 
606 
     | 
    
         | 
| 
      
 607 
     | 
    
         
            +
                def lock!(locks = true) # :nodoc:
         
     | 
| 
       163 
608 
     | 
    
         
             
                  case locks
         
     | 
| 
       164 
609 
     | 
    
         
             
                  when String, TrueClass, NilClass
         
     | 
| 
       165 
     | 
    
         
            -
                     
     | 
| 
      
 610 
     | 
    
         
            +
                    self.lock_value = locks || true
         
     | 
| 
       166 
611 
     | 
    
         
             
                  else
         
     | 
| 
       167 
     | 
    
         
            -
                     
     | 
| 
      
 612 
     | 
    
         
            +
                    self.lock_value = false
         
     | 
| 
       168 
613 
     | 
    
         
             
                  end
         
     | 
| 
       169 
614 
     | 
    
         | 
| 
       170 
     | 
    
         
            -
                   
     | 
| 
      
 615 
     | 
    
         
            +
                  self
         
     | 
| 
       171 
616 
     | 
    
         
             
                end
         
     | 
| 
       172 
617 
     | 
    
         | 
| 
      
 618 
     | 
    
         
            +
                # Returns a chainable relation with zero records.
         
     | 
| 
      
 619 
     | 
    
         
            +
                #
         
     | 
| 
      
 620 
     | 
    
         
            +
                # The returned relation implements the Null Object pattern. It is an
         
     | 
| 
      
 621 
     | 
    
         
            +
                # object with defined null behavior and always returns an empty array of
         
     | 
| 
      
 622 
     | 
    
         
            +
                # records without querying the database.
         
     | 
| 
      
 623 
     | 
    
         
            +
                #
         
     | 
| 
      
 624 
     | 
    
         
            +
                # Any subsequent condition chained to the returned relation will continue
         
     | 
| 
      
 625 
     | 
    
         
            +
                # generating an empty relation and will not fire any query to the database.
         
     | 
| 
      
 626 
     | 
    
         
            +
                #
         
     | 
| 
      
 627 
     | 
    
         
            +
                # Used in cases where a method or scope could return zero records but the
         
     | 
| 
      
 628 
     | 
    
         
            +
                # result needs to be chainable.
         
     | 
| 
      
 629 
     | 
    
         
            +
                #
         
     | 
| 
      
 630 
     | 
    
         
            +
                # For example:
         
     | 
| 
      
 631 
     | 
    
         
            +
                #
         
     | 
| 
      
 632 
     | 
    
         
            +
                #   @posts = current_user.visible_posts.where(name: params[:name])
         
     | 
| 
      
 633 
     | 
    
         
            +
                #   # => the visible_posts method is expected to return a chainable Relation
         
     | 
| 
      
 634 
     | 
    
         
            +
                #
         
     | 
| 
      
 635 
     | 
    
         
            +
                #   def visible_posts
         
     | 
| 
      
 636 
     | 
    
         
            +
                #     case role
         
     | 
| 
      
 637 
     | 
    
         
            +
                #     when 'Country Manager'
         
     | 
| 
      
 638 
     | 
    
         
            +
                #       Post.where(country: country)
         
     | 
| 
      
 639 
     | 
    
         
            +
                #     when 'Reviewer'
         
     | 
| 
      
 640 
     | 
    
         
            +
                #       Post.published
         
     | 
| 
      
 641 
     | 
    
         
            +
                #     when 'Bad User'
         
     | 
| 
      
 642 
     | 
    
         
            +
                #       Post.none # => returning [] instead breaks the previous code
         
     | 
| 
      
 643 
     | 
    
         
            +
                #     end
         
     | 
| 
      
 644 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 645 
     | 
    
         
            +
                #
         
     | 
| 
      
 646 
     | 
    
         
            +
                def none
         
     | 
| 
      
 647 
     | 
    
         
            +
                  extending(NullRelation)
         
     | 
| 
      
 648 
     | 
    
         
            +
                end
         
     | 
| 
      
 649 
     | 
    
         
            +
             
     | 
| 
      
 650 
     | 
    
         
            +
                def none! # :nodoc:
         
     | 
| 
      
 651 
     | 
    
         
            +
                  extending!(NullRelation)
         
     | 
| 
      
 652 
     | 
    
         
            +
                end
         
     | 
| 
      
 653 
     | 
    
         
            +
             
     | 
| 
      
 654 
     | 
    
         
            +
                # Sets readonly attributes for the returned relation. If value is
         
     | 
| 
      
 655 
     | 
    
         
            +
                # true (default), attempting to update a record will result in an error.
         
     | 
| 
      
 656 
     | 
    
         
            +
                #
         
     | 
| 
      
 657 
     | 
    
         
            +
                #   users = User.readonly
         
     | 
| 
      
 658 
     | 
    
         
            +
                #   users.first.save
         
     | 
| 
      
 659 
     | 
    
         
            +
                #   => ActiveRecord::ReadOnlyRecord: ActiveRecord::ReadOnlyRecord
         
     | 
| 
       173 
660 
     | 
    
         
             
                def readonly(value = true)
         
     | 
| 
       174 
     | 
    
         
            -
                   
     | 
| 
       175 
     | 
    
         
            -
             
     | 
| 
       176 
     | 
    
         
            -
             
     | 
| 
      
 661 
     | 
    
         
            +
                  spawn.readonly!(value)
         
     | 
| 
      
 662 
     | 
    
         
            +
                end
         
     | 
| 
      
 663 
     | 
    
         
            +
             
     | 
| 
      
 664 
     | 
    
         
            +
                def readonly!(value = true) # :nodoc:
         
     | 
| 
      
 665 
     | 
    
         
            +
                  self.readonly_value = value
         
     | 
| 
      
 666 
     | 
    
         
            +
                  self
         
     | 
| 
       177 
667 
     | 
    
         
             
                end
         
     | 
| 
       178 
668 
     | 
    
         | 
| 
      
 669 
     | 
    
         
            +
                # Sets attributes to be used when creating new records from a
         
     | 
| 
      
 670 
     | 
    
         
            +
                # relation object.
         
     | 
| 
      
 671 
     | 
    
         
            +
                #
         
     | 
| 
      
 672 
     | 
    
         
            +
                #   users = User.where(name: 'Oscar')
         
     | 
| 
      
 673 
     | 
    
         
            +
                #   users.new.name # => 'Oscar'
         
     | 
| 
      
 674 
     | 
    
         
            +
                #
         
     | 
| 
      
 675 
     | 
    
         
            +
                #   users = users.create_with(name: 'DHH')
         
     | 
| 
      
 676 
     | 
    
         
            +
                #   users.new.name # => 'DHH'
         
     | 
| 
      
 677 
     | 
    
         
            +
                #
         
     | 
| 
      
 678 
     | 
    
         
            +
                # You can pass +nil+ to +create_with+ to reset attributes:
         
     | 
| 
      
 679 
     | 
    
         
            +
                #
         
     | 
| 
      
 680 
     | 
    
         
            +
                #   users = users.create_with(nil)
         
     | 
| 
      
 681 
     | 
    
         
            +
                #   users.new.name # => 'Oscar'
         
     | 
| 
       179 
682 
     | 
    
         
             
                def create_with(value)
         
     | 
| 
       180 
     | 
    
         
            -
                   
     | 
| 
       181 
     | 
    
         
            -
             
     | 
| 
       182 
     | 
    
         
            -
             
     | 
| 
      
 683 
     | 
    
         
            +
                  spawn.create_with!(value)
         
     | 
| 
      
 684 
     | 
    
         
            +
                end
         
     | 
| 
      
 685 
     | 
    
         
            +
             
     | 
| 
      
 686 
     | 
    
         
            +
                def create_with!(value) # :nodoc:
         
     | 
| 
      
 687 
     | 
    
         
            +
                  if value
         
     | 
| 
      
 688 
     | 
    
         
            +
                    value = sanitize_forbidden_attributes(value)
         
     | 
| 
      
 689 
     | 
    
         
            +
                    self.create_with_value = create_with_value.merge(value)
         
     | 
| 
      
 690 
     | 
    
         
            +
                  else
         
     | 
| 
      
 691 
     | 
    
         
            +
                    self.create_with_value = {}
         
     | 
| 
      
 692 
     | 
    
         
            +
                  end
         
     | 
| 
      
 693 
     | 
    
         
            +
             
     | 
| 
      
 694 
     | 
    
         
            +
                  self
         
     | 
| 
      
 695 
     | 
    
         
            +
                end
         
     | 
| 
      
 696 
     | 
    
         
            +
             
     | 
| 
      
 697 
     | 
    
         
            +
                # Specifies table from which the records will be fetched. For example:
         
     | 
| 
      
 698 
     | 
    
         
            +
                #
         
     | 
| 
      
 699 
     | 
    
         
            +
                #   Topic.select('title').from('posts')
         
     | 
| 
      
 700 
     | 
    
         
            +
                #   #=> SELECT title FROM posts
         
     | 
| 
      
 701 
     | 
    
         
            +
                #
         
     | 
| 
      
 702 
     | 
    
         
            +
                # Can accept other relation objects. For example:
         
     | 
| 
      
 703 
     | 
    
         
            +
                #
         
     | 
| 
      
 704 
     | 
    
         
            +
                #   Topic.select('title').from(Topic.approved)
         
     | 
| 
      
 705 
     | 
    
         
            +
                #   # => SELECT title FROM (SELECT * FROM topics WHERE approved = 't') subquery
         
     | 
| 
      
 706 
     | 
    
         
            +
                #
         
     | 
| 
      
 707 
     | 
    
         
            +
                #   Topic.select('a.title').from(Topic.approved, :a)
         
     | 
| 
      
 708 
     | 
    
         
            +
                #   # => SELECT a.title FROM (SELECT * FROM topics WHERE approved = 't') a
         
     | 
| 
      
 709 
     | 
    
         
            +
                #
         
     | 
| 
      
 710 
     | 
    
         
            +
                def from(value, subquery_name = nil)
         
     | 
| 
      
 711 
     | 
    
         
            +
                  spawn.from!(value, subquery_name)
         
     | 
| 
       183 
712 
     | 
    
         
             
                end
         
     | 
| 
       184 
713 
     | 
    
         | 
| 
       185 
     | 
    
         
            -
                def from(value)
         
     | 
| 
       186 
     | 
    
         
            -
                   
     | 
| 
       187 
     | 
    
         
            -
                   
     | 
| 
       188 
     | 
    
         
            -
                  relation
         
     | 
| 
      
 714 
     | 
    
         
            +
                def from!(value, subquery_name = nil) # :nodoc:
         
     | 
| 
      
 715 
     | 
    
         
            +
                  self.from_value = [value, subquery_name]
         
     | 
| 
      
 716 
     | 
    
         
            +
                  self
         
     | 
| 
       189 
717 
     | 
    
         
             
                end
         
     | 
| 
       190 
718 
     | 
    
         | 
| 
       191 
719 
     | 
    
         
             
                # Specifies whether the records should be unique or not. For example:
         
     | 
| 
         @@ -193,16 +721,22 @@ module ActiveRecord 
     | 
|
| 
       193 
721 
     | 
    
         
             
                #   User.select(:name)
         
     | 
| 
       194 
722 
     | 
    
         
             
                #   # => Might return two records with the same name
         
     | 
| 
       195 
723 
     | 
    
         
             
                #
         
     | 
| 
       196 
     | 
    
         
            -
                #   User.select(:name). 
     | 
| 
       197 
     | 
    
         
            -
                #   # => Returns 1 record per  
     | 
| 
      
 724 
     | 
    
         
            +
                #   User.select(:name).distinct
         
     | 
| 
      
 725 
     | 
    
         
            +
                #   # => Returns 1 record per distinct name
         
     | 
| 
       198 
726 
     | 
    
         
             
                #
         
     | 
| 
       199 
     | 
    
         
            -
                #   User.select(:name). 
     | 
| 
      
 727 
     | 
    
         
            +
                #   User.select(:name).distinct.distinct(false)
         
     | 
| 
       200 
728 
     | 
    
         
             
                #   # => You can also remove the uniqueness
         
     | 
| 
       201 
     | 
    
         
            -
                def  
     | 
| 
       202 
     | 
    
         
            -
                   
     | 
| 
       203 
     | 
    
         
            -
             
     | 
| 
       204 
     | 
    
         
            -
             
     | 
| 
      
 729 
     | 
    
         
            +
                def distinct(value = true)
         
     | 
| 
      
 730 
     | 
    
         
            +
                  spawn.distinct!(value)
         
     | 
| 
      
 731 
     | 
    
         
            +
                end
         
     | 
| 
      
 732 
     | 
    
         
            +
                alias uniq distinct
         
     | 
| 
      
 733 
     | 
    
         
            +
             
     | 
| 
      
 734 
     | 
    
         
            +
                # Like #distinct, but modifies relation in place.
         
     | 
| 
      
 735 
     | 
    
         
            +
                def distinct!(value = true) # :nodoc:
         
     | 
| 
      
 736 
     | 
    
         
            +
                  self.distinct_value = value
         
     | 
| 
      
 737 
     | 
    
         
            +
                  self
         
     | 
| 
       205 
738 
     | 
    
         
             
                end
         
     | 
| 
      
 739 
     | 
    
         
            +
                alias uniq! distinct!
         
     | 
| 
       206 
740 
     | 
    
         | 
| 
       207 
741 
     | 
    
         
             
                # Used to extend a scope with additional methods, either through
         
     | 
| 
       208 
742 
     | 
    
         
             
                # a module or through a block provided.
         
     | 
| 
         @@ -217,16 +751,16 @@ module ActiveRecord 
     | 
|
| 
       217 
751 
     | 
    
         
             
                #     end
         
     | 
| 
       218 
752 
     | 
    
         
             
                #   end
         
     | 
| 
       219 
753 
     | 
    
         
             
                #
         
     | 
| 
       220 
     | 
    
         
            -
                #   scope = Model. 
     | 
| 
      
 754 
     | 
    
         
            +
                #   scope = Model.all.extending(Pagination)
         
     | 
| 
       221 
755 
     | 
    
         
             
                #   scope.page(params[:page])
         
     | 
| 
       222 
756 
     | 
    
         
             
                #
         
     | 
| 
       223 
757 
     | 
    
         
             
                # You can also pass a list of modules:
         
     | 
| 
       224 
758 
     | 
    
         
             
                #
         
     | 
| 
       225 
     | 
    
         
            -
                #   scope = Model. 
     | 
| 
      
 759 
     | 
    
         
            +
                #   scope = Model.all.extending(Pagination, SomethingElse)
         
     | 
| 
       226 
760 
     | 
    
         
             
                #
         
     | 
| 
       227 
761 
     | 
    
         
             
                # === Using a block
         
     | 
| 
       228 
762 
     | 
    
         
             
                #
         
     | 
| 
       229 
     | 
    
         
            -
                #   scope = Model. 
     | 
| 
      
 763 
     | 
    
         
            +
                #   scope = Model.all.extending do
         
     | 
| 
       230 
764 
     | 
    
         
             
                #     def page(number)
         
     | 
| 
       231 
765 
     | 
    
         
             
                #       # pagination code goes here
         
     | 
| 
       232 
766 
     | 
    
         
             
                #     end
         
     | 
| 
         @@ -235,60 +769,106 @@ module ActiveRecord 
     | 
|
| 
       235 
769 
     | 
    
         
             
                #
         
     | 
| 
       236 
770 
     | 
    
         
             
                # You can also use a block and a module list:
         
     | 
| 
       237 
771 
     | 
    
         
             
                #
         
     | 
| 
       238 
     | 
    
         
            -
                #   scope = Model. 
     | 
| 
      
 772 
     | 
    
         
            +
                #   scope = Model.all.extending(Pagination) do
         
     | 
| 
       239 
773 
     | 
    
         
             
                #     def per_page(number)
         
     | 
| 
       240 
774 
     | 
    
         
             
                #       # pagination code goes here
         
     | 
| 
       241 
775 
     | 
    
         
             
                #     end
         
     | 
| 
       242 
776 
     | 
    
         
             
                #   end
         
     | 
| 
       243 
     | 
    
         
            -
                def extending(*modules)
         
     | 
| 
       244 
     | 
    
         
            -
                  modules 
     | 
| 
      
 777 
     | 
    
         
            +
                def extending(*modules, &block)
         
     | 
| 
      
 778 
     | 
    
         
            +
                  if modules.any? || block
         
     | 
| 
      
 779 
     | 
    
         
            +
                    spawn.extending!(*modules, &block)
         
     | 
| 
      
 780 
     | 
    
         
            +
                  else
         
     | 
| 
      
 781 
     | 
    
         
            +
                    self
         
     | 
| 
      
 782 
     | 
    
         
            +
                  end
         
     | 
| 
      
 783 
     | 
    
         
            +
                end
         
     | 
| 
       245 
784 
     | 
    
         | 
| 
       246 
     | 
    
         
            -
             
     | 
| 
      
 785 
     | 
    
         
            +
                def extending!(*modules, &block) # :nodoc:
         
     | 
| 
      
 786 
     | 
    
         
            +
                  modules << Module.new(&block) if block_given?
         
     | 
| 
       247 
787 
     | 
    
         | 
| 
       248 
     | 
    
         
            -
                   
     | 
| 
       249 
     | 
    
         
            -
                   
     | 
| 
       250 
     | 
    
         
            -
             
     | 
| 
      
 788 
     | 
    
         
            +
                  self.extending_values += modules.flatten
         
     | 
| 
      
 789 
     | 
    
         
            +
                  extend(*extending_values) if extending_values.any?
         
     | 
| 
      
 790 
     | 
    
         
            +
             
     | 
| 
      
 791 
     | 
    
         
            +
                  self
         
     | 
| 
       251 
792 
     | 
    
         
             
                end
         
     | 
| 
       252 
793 
     | 
    
         | 
| 
      
 794 
     | 
    
         
            +
                # Reverse the existing order clause on the relation.
         
     | 
| 
      
 795 
     | 
    
         
            +
                #
         
     | 
| 
      
 796 
     | 
    
         
            +
                #   User.order('name ASC').reverse_order # generated SQL has 'ORDER BY name DESC'
         
     | 
| 
       253 
797 
     | 
    
         
             
                def reverse_order
         
     | 
| 
       254 
     | 
    
         
            -
                   
     | 
| 
       255 
     | 
    
         
            -
                  relation.reverse_order_value = !relation.reverse_order_value
         
     | 
| 
       256 
     | 
    
         
            -
                  relation
         
     | 
| 
      
 798 
     | 
    
         
            +
                  spawn.reverse_order!
         
     | 
| 
       257 
799 
     | 
    
         
             
                end
         
     | 
| 
       258 
800 
     | 
    
         | 
| 
      
 801 
     | 
    
         
            +
                def reverse_order! # :nodoc:
         
     | 
| 
      
 802 
     | 
    
         
            +
                  self.reverse_order_value = !reverse_order_value
         
     | 
| 
      
 803 
     | 
    
         
            +
                  self
         
     | 
| 
      
 804 
     | 
    
         
            +
                end
         
     | 
| 
      
 805 
     | 
    
         
            +
             
     | 
| 
      
 806 
     | 
    
         
            +
                # Returns the Arel object associated with the relation.
         
     | 
| 
       259 
807 
     | 
    
         
             
                def arel
         
     | 
| 
       260 
808 
     | 
    
         
             
                  @arel ||= with_default_scope.build_arel
         
     | 
| 
       261 
809 
     | 
    
         
             
                end
         
     | 
| 
       262 
810 
     | 
    
         | 
| 
      
 811 
     | 
    
         
            +
                # Like #arel, but ignores the default scope of the model.
         
     | 
| 
       263 
812 
     | 
    
         
             
                def build_arel
         
     | 
| 
       264 
     | 
    
         
            -
                  arel = table. 
     | 
| 
      
 813 
     | 
    
         
            +
                  arel = Arel::SelectManager.new(table.engine, table)
         
     | 
| 
       265 
814 
     | 
    
         | 
| 
       266 
     | 
    
         
            -
                  build_joins(arel,  
     | 
| 
      
 815 
     | 
    
         
            +
                  build_joins(arel, joins_values.flatten) unless joins_values.empty?
         
     | 
| 
       267 
816 
     | 
    
         | 
| 
       268 
     | 
    
         
            -
                  collapse_wheres(arel, ( 
     | 
| 
      
 817 
     | 
    
         
            +
                  collapse_wheres(arel, (where_values - ['']).uniq)
         
     | 
| 
       269 
818 
     | 
    
         | 
| 
       270 
     | 
    
         
            -
                  arel.having( 
     | 
| 
      
 819 
     | 
    
         
            +
                  arel.having(*having_values.uniq.reject{|h| h.blank?}) unless having_values.empty?
         
     | 
| 
       271 
820 
     | 
    
         | 
| 
       272 
     | 
    
         
            -
                  arel.take(connection.sanitize_limit( 
     | 
| 
       273 
     | 
    
         
            -
                  arel.skip( 
     | 
| 
      
 821 
     | 
    
         
            +
                  arel.take(connection.sanitize_limit(limit_value)) if limit_value
         
     | 
| 
      
 822 
     | 
    
         
            +
                  arel.skip(offset_value.to_i) if offset_value
         
     | 
| 
       274 
823 
     | 
    
         | 
| 
       275 
     | 
    
         
            -
                  arel.group( 
     | 
| 
      
 824 
     | 
    
         
            +
                  arel.group(*group_values.uniq.reject{|g| g.blank?}) unless group_values.empty?
         
     | 
| 
       276 
825 
     | 
    
         | 
| 
       277 
     | 
    
         
            -
                   
     | 
| 
       278 
     | 
    
         
            -
                  order = reverse_sql_order(order) if @reverse_order_value
         
     | 
| 
       279 
     | 
    
         
            -
                  arel.order(*order.uniq.reject{|o| o.blank?}) unless order.empty?
         
     | 
| 
      
 826 
     | 
    
         
            +
                  build_order(arel)
         
     | 
| 
       280 
827 
     | 
    
         | 
| 
       281 
     | 
    
         
            -
                  build_select(arel,  
     | 
| 
      
 828 
     | 
    
         
            +
                  build_select(arel, select_values.uniq)
         
     | 
| 
       282 
829 
     | 
    
         | 
| 
       283 
     | 
    
         
            -
                  arel.distinct( 
     | 
| 
       284 
     | 
    
         
            -
                  arel.from( 
     | 
| 
       285 
     | 
    
         
            -
                  arel.lock( 
     | 
| 
      
 830 
     | 
    
         
            +
                  arel.distinct(distinct_value)
         
     | 
| 
      
 831 
     | 
    
         
            +
                  arel.from(build_from) if from_value
         
     | 
| 
      
 832 
     | 
    
         
            +
                  arel.lock(lock_value) if lock_value
         
     | 
| 
       286 
833 
     | 
    
         | 
| 
       287 
834 
     | 
    
         
             
                  arel
         
     | 
| 
       288 
835 
     | 
    
         
             
                end
         
     | 
| 
       289 
836 
     | 
    
         | 
| 
       290 
837 
     | 
    
         
             
                private
         
     | 
| 
       291 
838 
     | 
    
         | 
| 
      
 839 
     | 
    
         
            +
                def symbol_unscoping(scope)
         
     | 
| 
      
 840 
     | 
    
         
            +
                  if !VALID_UNSCOPING_VALUES.include?(scope)
         
     | 
| 
      
 841 
     | 
    
         
            +
                    raise ArgumentError, "Called unscope() with invalid unscoping argument ':#{scope}'. Valid arguments are :#{VALID_UNSCOPING_VALUES.to_a.join(", :")}."
         
     | 
| 
      
 842 
     | 
    
         
            +
                  end
         
     | 
| 
      
 843 
     | 
    
         
            +
             
     | 
| 
      
 844 
     | 
    
         
            +
                  single_val_method = Relation::SINGLE_VALUE_METHODS.include?(scope)
         
     | 
| 
      
 845 
     | 
    
         
            +
                  unscope_code = :"#{scope}_value#{'s' unless single_val_method}="
         
     | 
| 
      
 846 
     | 
    
         
            +
             
     | 
| 
      
 847 
     | 
    
         
            +
                  case scope
         
     | 
| 
      
 848 
     | 
    
         
            +
                  when :order
         
     | 
| 
      
 849 
     | 
    
         
            +
                    self.send(:reverse_order_value=, false)
         
     | 
| 
      
 850 
     | 
    
         
            +
                    result = []
         
     | 
| 
      
 851 
     | 
    
         
            +
                  else
         
     | 
| 
      
 852 
     | 
    
         
            +
                    result = [] unless single_val_method
         
     | 
| 
      
 853 
     | 
    
         
            +
                  end
         
     | 
| 
      
 854 
     | 
    
         
            +
             
     | 
| 
      
 855 
     | 
    
         
            +
                  self.send(unscope_code, result)
         
     | 
| 
      
 856 
     | 
    
         
            +
                end
         
     | 
| 
      
 857 
     | 
    
         
            +
             
     | 
| 
      
 858 
     | 
    
         
            +
                def where_unscoping(target_value)
         
     | 
| 
      
 859 
     | 
    
         
            +
                  target_value_sym = target_value.to_sym
         
     | 
| 
      
 860 
     | 
    
         
            +
             
     | 
| 
      
 861 
     | 
    
         
            +
                  where_values.reject! do |rel|
         
     | 
| 
      
 862 
     | 
    
         
            +
                    case rel
         
     | 
| 
      
 863 
     | 
    
         
            +
                    when Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual
         
     | 
| 
      
 864 
     | 
    
         
            +
                      subrelation = (rel.left.kind_of?(Arel::Attributes::Attribute) ? rel.left : rel.right)
         
     | 
| 
      
 865 
     | 
    
         
            +
                      subrelation.name.to_sym == target_value_sym
         
     | 
| 
      
 866 
     | 
    
         
            +
                    else
         
     | 
| 
      
 867 
     | 
    
         
            +
                      raise "unscope(where: #{target_value.inspect}) failed: unscoping #{rel.class} is unimplemented."
         
     | 
| 
      
 868 
     | 
    
         
            +
                    end
         
     | 
| 
      
 869 
     | 
    
         
            +
                  end
         
     | 
| 
      
 870 
     | 
    
         
            +
                end
         
     | 
| 
      
 871 
     | 
    
         
            +
             
     | 
| 
       292 
872 
     | 
    
         
             
                def custom_join_ast(table, joins)
         
     | 
| 
       293 
873 
     | 
    
         
             
                  joins = joins.reject { |join| join.blank? }
         
     | 
| 
       294 
874 
     | 
    
         | 
| 
         @@ -308,50 +888,71 @@ module ActiveRecord 
     | 
|
| 
       308 
888 
     | 
    
         
             
                end
         
     | 
| 
       309 
889 
     | 
    
         | 
| 
       310 
890 
     | 
    
         
             
                def collapse_wheres(arel, wheres)
         
     | 
| 
       311 
     | 
    
         
            -
                   
     | 
| 
       312 
     | 
    
         
            -
             
     | 
| 
       313 
     | 
    
         
            -
                  arel.where(Arel::Nodes::And.new(equalities)) unless equalities.empty?
         
     | 
| 
       314 
     | 
    
         
            -
             
     | 
| 
       315 
     | 
    
         
            -
                  (wheres - equalities).each do |where|
         
     | 
| 
      
 891 
     | 
    
         
            +
                  predicates = wheres.map do |where|
         
     | 
| 
      
 892 
     | 
    
         
            +
                    next where if ::Arel::Nodes::Equality === where
         
     | 
| 
       316 
893 
     | 
    
         
             
                    where = Arel.sql(where) if String === where
         
     | 
| 
       317 
     | 
    
         
            -
                     
     | 
| 
      
 894 
     | 
    
         
            +
                    Arel::Nodes::Grouping.new(where)
         
     | 
| 
       318 
895 
     | 
    
         
             
                  end
         
     | 
| 
      
 896 
     | 
    
         
            +
             
     | 
| 
      
 897 
     | 
    
         
            +
                  arel.where(Arel::Nodes::And.new(predicates)) if predicates.present?
         
     | 
| 
       319 
898 
     | 
    
         
             
                end
         
     | 
| 
       320 
899 
     | 
    
         | 
| 
       321 
900 
     | 
    
         
             
                def build_where(opts, other = [])
         
     | 
| 
       322 
901 
     | 
    
         
             
                  case opts
         
     | 
| 
       323 
902 
     | 
    
         
             
                  when String, Array
         
     | 
| 
      
 903 
     | 
    
         
            +
                    #TODO: Remove duplication with: /activerecord/lib/active_record/sanitization.rb:113
         
     | 
| 
      
 904 
     | 
    
         
            +
                    values = Hash === other.first ? other.first.values : other
         
     | 
| 
      
 905 
     | 
    
         
            +
             
     | 
| 
      
 906 
     | 
    
         
            +
                    values.grep(ActiveRecord::Relation) do |rel|
         
     | 
| 
      
 907 
     | 
    
         
            +
                      self.bind_values += rel.bind_values
         
     | 
| 
      
 908 
     | 
    
         
            +
                    end
         
     | 
| 
      
 909 
     | 
    
         
            +
             
     | 
| 
       324 
910 
     | 
    
         
             
                    [@klass.send(:sanitize_sql, other.empty? ? opts : ([opts] + other))]
         
     | 
| 
       325 
911 
     | 
    
         
             
                  when Hash
         
     | 
| 
       326 
912 
     | 
    
         
             
                    attributes = @klass.send(:expand_hash_conditions_for_aggregates, opts)
         
     | 
| 
       327 
     | 
    
         
            -
             
     | 
| 
      
 913 
     | 
    
         
            +
             
     | 
| 
      
 914 
     | 
    
         
            +
                    attributes.values.grep(ActiveRecord::Relation) do |rel|
         
     | 
| 
      
 915 
     | 
    
         
            +
                      self.bind_values += rel.bind_values
         
     | 
| 
      
 916 
     | 
    
         
            +
                    end
         
     | 
| 
      
 917 
     | 
    
         
            +
             
     | 
| 
      
 918 
     | 
    
         
            +
                    PredicateBuilder.build_from_hash(klass, attributes, table)
         
     | 
| 
       328 
919 
     | 
    
         
             
                  else
         
     | 
| 
       329 
920 
     | 
    
         
             
                    [opts]
         
     | 
| 
       330 
921 
     | 
    
         
             
                  end
         
     | 
| 
       331 
922 
     | 
    
         
             
                end
         
     | 
| 
       332 
923 
     | 
    
         | 
| 
      
 924 
     | 
    
         
            +
                def build_from
         
     | 
| 
      
 925 
     | 
    
         
            +
                  opts, name = from_value
         
     | 
| 
      
 926 
     | 
    
         
            +
                  case opts
         
     | 
| 
      
 927 
     | 
    
         
            +
                  when Relation
         
     | 
| 
      
 928 
     | 
    
         
            +
                    name ||= 'subquery'
         
     | 
| 
      
 929 
     | 
    
         
            +
                    self.bind_values = opts.bind_values + self.bind_values
         
     | 
| 
      
 930 
     | 
    
         
            +
                    opts.arel.as(name.to_s)
         
     | 
| 
      
 931 
     | 
    
         
            +
                  else
         
     | 
| 
      
 932 
     | 
    
         
            +
                    opts
         
     | 
| 
      
 933 
     | 
    
         
            +
                  end
         
     | 
| 
      
 934 
     | 
    
         
            +
                end
         
     | 
| 
      
 935 
     | 
    
         
            +
             
     | 
| 
       333 
936 
     | 
    
         
             
                def build_joins(manager, joins)
         
     | 
| 
       334 
937 
     | 
    
         
             
                  buckets = joins.group_by do |join|
         
     | 
| 
       335 
938 
     | 
    
         
             
                    case join
         
     | 
| 
       336 
939 
     | 
    
         
             
                    when String
         
     | 
| 
       337 
     | 
    
         
            -
                       
     | 
| 
      
 940 
     | 
    
         
            +
                      :string_join
         
     | 
| 
       338 
941 
     | 
    
         
             
                    when Hash, Symbol, Array
         
     | 
| 
       339 
     | 
    
         
            -
                       
     | 
| 
      
 942 
     | 
    
         
            +
                      :association_join
         
     | 
| 
       340 
943 
     | 
    
         
             
                    when ActiveRecord::Associations::JoinDependency::JoinAssociation
         
     | 
| 
       341 
     | 
    
         
            -
                       
     | 
| 
      
 944 
     | 
    
         
            +
                      :stashed_join
         
     | 
| 
       342 
945 
     | 
    
         
             
                    when Arel::Nodes::Join
         
     | 
| 
       343 
     | 
    
         
            -
                       
     | 
| 
      
 946 
     | 
    
         
            +
                      :join_node
         
     | 
| 
       344 
947 
     | 
    
         
             
                    else
         
     | 
| 
       345 
948 
     | 
    
         
             
                      raise 'unknown class: %s' % join.class.name
         
     | 
| 
       346 
949 
     | 
    
         
             
                    end
         
     | 
| 
       347 
950 
     | 
    
         
             
                  end
         
     | 
| 
       348 
951 
     | 
    
         | 
| 
       349 
     | 
    
         
            -
                  association_joins         = buckets[ 
     | 
| 
       350 
     | 
    
         
            -
                  stashed_association_joins = buckets[ 
     | 
| 
       351 
     | 
    
         
            -
                  join_nodes                = (buckets[ 
     | 
| 
       352 
     | 
    
         
            -
                  string_joins              = (buckets[ 
     | 
| 
       353 
     | 
    
         
            -
                    x.strip
         
     | 
| 
       354 
     | 
    
         
            -
                  }.uniq
         
     | 
| 
      
 952 
     | 
    
         
            +
                  association_joins         = buckets[:association_join] || []
         
     | 
| 
      
 953 
     | 
    
         
            +
                  stashed_association_joins = buckets[:stashed_join] || []
         
     | 
| 
      
 954 
     | 
    
         
            +
                  join_nodes                = (buckets[:join_node] || []).uniq
         
     | 
| 
      
 955 
     | 
    
         
            +
                  string_joins              = (buckets[:string_join] || []).map { |x| x.strip }.uniq
         
     | 
| 
       355 
956 
     | 
    
         | 
| 
       356 
957 
     | 
    
         
             
                  join_list = join_nodes + custom_join_ast(manager, string_joins)
         
     | 
| 
       357 
958 
     | 
    
         | 
| 
         @@ -384,34 +985,80 @@ module ActiveRecord 
     | 
|
| 
       384 
985 
     | 
    
         
             
                  end
         
     | 
| 
       385 
986 
     | 
    
         
             
                end
         
     | 
| 
       386 
987 
     | 
    
         | 
| 
       387 
     | 
    
         
            -
                def apply_modules(modules)
         
     | 
| 
       388 
     | 
    
         
            -
                  unless modules.empty?
         
     | 
| 
       389 
     | 
    
         
            -
                    @extensions += modules
         
     | 
| 
       390 
     | 
    
         
            -
                    modules.each {|extension| extend(extension) }
         
     | 
| 
       391 
     | 
    
         
            -
                  end
         
     | 
| 
       392 
     | 
    
         
            -
                end
         
     | 
| 
       393 
     | 
    
         
            -
             
     | 
| 
       394 
988 
     | 
    
         
             
                def reverse_sql_order(order_query)
         
     | 
| 
       395 
989 
     | 
    
         
             
                  order_query = ["#{quoted_table_name}.#{quoted_primary_key} ASC"] if order_query.empty?
         
     | 
| 
       396 
990 
     | 
    
         | 
| 
       397 
     | 
    
         
            -
                  order_query. 
     | 
| 
      
 991 
     | 
    
         
            +
                  order_query.flat_map do |o|
         
     | 
| 
       398 
992 
     | 
    
         
             
                    case o
         
     | 
| 
       399 
993 
     | 
    
         
             
                    when Arel::Nodes::Ordering
         
     | 
| 
       400 
994 
     | 
    
         
             
                      o.reverse
         
     | 
| 
       401 
     | 
    
         
            -
                    when String 
     | 
| 
      
 995 
     | 
    
         
            +
                    when String
         
     | 
| 
       402 
996 
     | 
    
         
             
                      o.to_s.split(',').collect do |s|
         
     | 
| 
       403 
997 
     | 
    
         
             
                        s.strip!
         
     | 
| 
       404 
998 
     | 
    
         
             
                        s.gsub!(/\sasc\Z/i, ' DESC') || s.gsub!(/\sdesc\Z/i, ' ASC') || s.concat(' DESC')
         
     | 
| 
       405 
999 
     | 
    
         
             
                      end
         
     | 
| 
      
 1000 
     | 
    
         
            +
                    when Symbol
         
     | 
| 
      
 1001 
     | 
    
         
            +
                      { o => :desc }
         
     | 
| 
      
 1002 
     | 
    
         
            +
                    when Hash
         
     | 
| 
      
 1003 
     | 
    
         
            +
                      o.each_with_object({}) do |(field, dir), memo|
         
     | 
| 
      
 1004 
     | 
    
         
            +
                        memo[field] = (dir == :asc ? :desc : :asc )
         
     | 
| 
      
 1005 
     | 
    
         
            +
                      end
         
     | 
| 
       406 
1006 
     | 
    
         
             
                    else
         
     | 
| 
       407 
1007 
     | 
    
         
             
                      o
         
     | 
| 
       408 
1008 
     | 
    
         
             
                    end
         
     | 
| 
       409 
     | 
    
         
            -
                  end 
     | 
| 
      
 1009 
     | 
    
         
            +
                  end
         
     | 
| 
       410 
1010 
     | 
    
         
             
                end
         
     | 
| 
       411 
1011 
     | 
    
         | 
| 
       412 
1012 
     | 
    
         
             
                def array_of_strings?(o)
         
     | 
| 
       413 
1013 
     | 
    
         
             
                  o.is_a?(Array) && o.all?{|obj| obj.is_a?(String)}
         
     | 
| 
       414 
1014 
     | 
    
         
             
                end
         
     | 
| 
       415 
1015 
     | 
    
         | 
| 
      
 1016 
     | 
    
         
            +
                def build_order(arel)
         
     | 
| 
      
 1017 
     | 
    
         
            +
                  orders = order_values
         
     | 
| 
      
 1018 
     | 
    
         
            +
                  orders = reverse_sql_order(orders) if reverse_order_value
         
     | 
| 
      
 1019 
     | 
    
         
            +
             
     | 
| 
      
 1020 
     | 
    
         
            +
                  orders = orders.uniq.reject(&:blank?).flat_map do |order|
         
     | 
| 
      
 1021 
     | 
    
         
            +
                    case order
         
     | 
| 
      
 1022 
     | 
    
         
            +
                    when Symbol
         
     | 
| 
      
 1023 
     | 
    
         
            +
                      table[order].asc
         
     | 
| 
      
 1024 
     | 
    
         
            +
                    when Hash
         
     | 
| 
      
 1025 
     | 
    
         
            +
                      order.map { |field, dir| table[field].send(dir) }
         
     | 
| 
      
 1026 
     | 
    
         
            +
                    else
         
     | 
| 
      
 1027 
     | 
    
         
            +
                      order
         
     | 
| 
      
 1028 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1029 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1030 
     | 
    
         
            +
             
     | 
| 
      
 1031 
     | 
    
         
            +
                  arel.order(*orders) unless orders.empty?
         
     | 
| 
      
 1032 
     | 
    
         
            +
                end
         
     | 
| 
      
 1033 
     | 
    
         
            +
             
     | 
| 
      
 1034 
     | 
    
         
            +
                def validate_order_args(args)
         
     | 
| 
      
 1035 
     | 
    
         
            +
                  args.select { |a| Hash === a  }.each do |h|
         
     | 
| 
      
 1036 
     | 
    
         
            +
                    unless (h.values - [:asc, :desc]).empty?
         
     | 
| 
      
 1037 
     | 
    
         
            +
                      raise ArgumentError, 'Direction should be :asc or :desc'
         
     | 
| 
      
 1038 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1039 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1040 
     | 
    
         
            +
                end
         
     | 
| 
      
 1041 
     | 
    
         
            +
             
     | 
| 
      
 1042 
     | 
    
         
            +
                # Checks to make sure that the arguments are not blank. Note that if some
         
     | 
| 
      
 1043 
     | 
    
         
            +
                # blank-like object were initially passed into the query method, then this
         
     | 
| 
      
 1044 
     | 
    
         
            +
                # method will not raise an error.
         
     | 
| 
      
 1045 
     | 
    
         
            +
                #
         
     | 
| 
      
 1046 
     | 
    
         
            +
                # Example:
         
     | 
| 
      
 1047 
     | 
    
         
            +
                #
         
     | 
| 
      
 1048 
     | 
    
         
            +
                #    Post.references()   # => raises an error
         
     | 
| 
      
 1049 
     | 
    
         
            +
                #    Post.references([]) # => does not raise an error
         
     | 
| 
      
 1050 
     | 
    
         
            +
                #
         
     | 
| 
      
 1051 
     | 
    
         
            +
                # This particular method should be called with a method_name and the args
         
     | 
| 
      
 1052 
     | 
    
         
            +
                # passed into that method as an input. For example:
         
     | 
| 
      
 1053 
     | 
    
         
            +
                #
         
     | 
| 
      
 1054 
     | 
    
         
            +
                # def references(*args)
         
     | 
| 
      
 1055 
     | 
    
         
            +
                #   check_if_method_has_arguments!("references", args)
         
     | 
| 
      
 1056 
     | 
    
         
            +
                #   ...
         
     | 
| 
      
 1057 
     | 
    
         
            +
                # end
         
     | 
| 
      
 1058 
     | 
    
         
            +
                def check_if_method_has_arguments!(method_name, args)
         
     | 
| 
      
 1059 
     | 
    
         
            +
                  if args.blank?
         
     | 
| 
      
 1060 
     | 
    
         
            +
                    raise ArgumentError, "The method .#{method_name}() must contain arguments."
         
     | 
| 
      
 1061 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1062 
     | 
    
         
            +
                end
         
     | 
| 
       416 
1063 
     | 
    
         
             
              end
         
     | 
| 
       417 
1064 
     | 
    
         
             
            end
         
     |