activerecord 3.2.6 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/CHANGELOG.md +611 -6417
- data/MIT-LICENSE +4 -2
- data/README.rdoc +44 -47
- data/examples/performance.rb +79 -71
- data/examples/simple.rb +6 -5
- data/lib/active_record/aggregations.rb +268 -238
- data/lib/active_record/association_relation.rb +40 -0
- data/lib/active_record/associations/alias_tracker.rb +47 -42
- data/lib/active_record/associations/association.rb +173 -81
- data/lib/active_record/associations/association_scope.rb +124 -92
- data/lib/active_record/associations/belongs_to_association.rb +83 -38
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +11 -9
- data/lib/active_record/associations/builder/association.rb +113 -32
- data/lib/active_record/associations/builder/belongs_to.rb +105 -60
- data/lib/active_record/associations/builder/collection_association.rb +53 -56
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +98 -41
- data/lib/active_record/associations/builder/has_many.rb +11 -63
- data/lib/active_record/associations/builder/has_one.rb +47 -45
- data/lib/active_record/associations/builder/singular_association.rb +30 -18
- data/lib/active_record/associations/collection_association.rb +217 -295
- data/lib/active_record/associations/collection_proxy.rb +1074 -77
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +78 -50
- data/lib/active_record/associations/has_many_through_association.rb +99 -61
- data/lib/active_record/associations/has_one_association.rb +75 -30
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +45 -119
- data/lib/active_record/associations/join_dependency/join_base.rb +11 -12
- data/lib/active_record/associations/join_dependency/join_part.rb +35 -42
- data/lib/active_record/associations/join_dependency.rb +208 -164
- data/lib/active_record/associations/preloader/association.rb +93 -87
- data/lib/active_record/associations/preloader/through_association.rb +87 -38
- data/lib/active_record/associations/preloader.rb +134 -110
- data/lib/active_record/associations/singular_association.rb +19 -24
- data/lib/active_record/associations/through_association.rb +61 -27
- data/lib/active_record/associations.rb +1766 -1505
- data/lib/active_record/attribute_assignment.rb +57 -193
- data/lib/active_record/attribute_decorators.rb +90 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +58 -8
- data/lib/active_record/attribute_methods/dirty.rb +187 -67
- data/lib/active_record/attribute_methods/primary_key.rb +100 -78
- data/lib/active_record/attribute_methods/query.rb +10 -8
- data/lib/active_record/attribute_methods/read.rb +29 -118
- data/lib/active_record/attribute_methods/serialization.rb +60 -72
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +69 -42
- data/lib/active_record/attribute_methods/write.rb +36 -44
- data/lib/active_record/attribute_methods.rb +306 -161
- data/lib/active_record/attributes.rb +279 -0
- data/lib/active_record/autosave_association.rb +324 -238
- data/lib/active_record/base.rb +114 -507
- data/lib/active_record/callbacks.rb +147 -83
- data/lib/active_record/coders/json.rb +15 -0
- data/lib/active_record/coders/yaml_column.rb +32 -23
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +962 -279
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +32 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +331 -209
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +95 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +201 -65
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +510 -289
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1182 -313
- data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +585 -120
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +610 -463
- data/lib/active_record/connection_adapters/column.rb +58 -233
- data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +75 -207
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +182 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +695 -1052
- data/lib/active_record/connection_adapters/schema_cache.rb +115 -24
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +528 -26
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +267 -0
- data/lib/active_record/core.rb +599 -0
- data/lib/active_record/counter_cache.rb +177 -103
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +107 -64
- data/lib/active_record/enum.rb +274 -0
- data/lib/active_record/errors.rb +254 -61
- data/lib/active_record/explain.rb +35 -70
- data/lib/active_record/explain_registry.rb +32 -0
- data/lib/active_record/explain_subscriber.rb +18 -8
- data/lib/active_record/fixture_set/file.rb +82 -0
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +291 -475
- data/lib/active_record/gem_version.rb +17 -0
- data/lib/active_record/inheritance.rb +219 -100
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +175 -17
- data/lib/active_record/internal_metadata.rb +53 -0
- data/lib/active_record/legacy_yaml_adapter.rb +48 -0
- data/lib/active_record/locale/en.yml +9 -1
- data/lib/active_record/locking/optimistic.rb +106 -92
- data/lib/active_record/locking/pessimistic.rb +23 -11
- data/lib/active_record/log_subscriber.rb +80 -30
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/migration/command_recorder.rb +235 -56
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +17 -0
- data/lib/active_record/migration.rb +917 -301
- data/lib/active_record/model_schema.rb +351 -175
- data/lib/active_record/nested_attributes.rb +366 -235
- data/lib/active_record/no_touching.rb +65 -0
- data/lib/active_record/null_relation.rb +68 -0
- data/lib/active_record/persistence.rb +761 -166
- data/lib/active_record/query_cache.rb +22 -44
- data/lib/active_record/querying.rb +55 -31
- data/lib/active_record/railtie.rb +185 -47
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +5 -4
- data/lib/active_record/railties/controller_runtime.rb +35 -33
- data/lib/active_record/railties/databases.rake +366 -463
- data/lib/active_record/readonly_attributes.rb +4 -6
- data/lib/active_record/reflection.rb +736 -228
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +252 -52
- data/lib/active_record/relation/calculations.rb +340 -270
- data/lib/active_record/relation/delegation.rb +117 -36
- data/lib/active_record/relation/finder_methods.rb +439 -286
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +184 -0
- data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder.rb +131 -39
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +1163 -221
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +49 -120
- data/lib/active_record/relation/where_clause.rb +190 -0
- data/lib/active_record/relation/where_clause_factory.rb +33 -0
- data/lib/active_record/relation.rb +671 -349
- data/lib/active_record/result.rb +149 -15
- data/lib/active_record/runtime_registry.rb +24 -0
- data/lib/active_record/sanitization.rb +153 -133
- data/lib/active_record/schema.rb +22 -19
- data/lib/active_record/schema_dumper.rb +178 -112
- data/lib/active_record/schema_migration.rb +60 -0
- data/lib/active_record/scoping/default.rb +107 -98
- data/lib/active_record/scoping/named.rb +130 -115
- data/lib/active_record/scoping.rb +77 -123
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +10 -6
- data/lib/active_record/statement_cache.rb +148 -0
- data/lib/active_record/store.rb +256 -16
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +75 -0
- data/lib/active_record/tasks/database_tasks.rb +506 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +93 -39
- data/lib/active_record/touch_later.rb +66 -0
- data/lib/active_record/transactions.rb +260 -129
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +129 -0
- data/lib/active_record/type/date.rb +9 -0
- data/lib/active_record/type/date_time.rb +9 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +71 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +21 -0
- data/lib/active_record/type/type_map.rb +62 -0
- data/lib/active_record/type/unsigned_integer.rb +17 -0
- data/lib/active_record/type.rb +78 -0
- data/lib/active_record/type_caster/connection.rb +34 -0
- data/lib/active_record/type_caster/map.rb +20 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +35 -18
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +68 -0
- data/lib/active_record/validations/uniqueness.rb +123 -77
- data/lib/active_record/validations.rb +54 -43
- data/lib/active_record/version.rb +7 -7
- data/lib/active_record.rb +97 -49
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +68 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +51 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +59 -9
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
- data/lib/rails/generators/active_record/migration.rb +41 -8
- data/lib/rails/generators/active_record/model/model_generator.rb +24 -22
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +1 -1
- data/lib/rails/generators/active_record.rb +10 -16
- metadata +285 -149
- data/examples/associations.png +0 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
- data/lib/active_record/associations/join_helper.rb +0 -55
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -15
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -188
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -426
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -579
- 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/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -203
- data/lib/active_record/session_store.rb +0 -358
- data/lib/active_record/test_case.rb +0 -73
- data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -34
- data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -12
- 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,75 +1,80 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/conversions"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
module Associations
|
5
|
-
# Keeps track of table aliases for ActiveRecord::Associations::
|
6
|
-
# ActiveRecord::Associations::ThroughAssociationScope
|
7
|
+
# Keeps track of table aliases for ActiveRecord::Associations::JoinDependency
|
7
8
|
class AliasTracker # :nodoc:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
def self.create(connection, initial_table, joins)
|
10
|
+
if joins.empty?
|
11
|
+
aliases = Hash.new(0)
|
12
|
+
else
|
13
|
+
aliases = Hash.new { |h, k|
|
14
|
+
h[k] = initial_count_for(connection, k, joins)
|
15
|
+
}
|
16
|
+
end
|
17
|
+
aliases[initial_table] = 1
|
18
|
+
new(connection, aliases)
|
15
19
|
end
|
16
20
|
|
17
|
-
def
|
18
|
-
|
21
|
+
def self.initial_count_for(connection, name, table_joins)
|
22
|
+
quoted_name = nil
|
19
23
|
|
20
|
-
|
21
|
-
Arel::
|
22
|
-
|
23
|
-
|
24
|
+
counts = table_joins.map do |join|
|
25
|
+
if join.is_a?(Arel::Nodes::StringJoin)
|
26
|
+
# quoted_name should be case ignored as some database adapters (Oracle) return quoted name in uppercase
|
27
|
+
quoted_name ||= connection.quote_table_name(name)
|
28
|
+
|
29
|
+
# Table names + table aliases
|
30
|
+
join.left.scan(
|
31
|
+
/JOIN(?:\s+\w+)?\s+(?:\S+\s+)?(?:#{quoted_name}|#{name})\sON/i
|
32
|
+
).size
|
33
|
+
elsif join.is_a?(Arel::Nodes::Join)
|
34
|
+
join.left.name == name ? 1 : 0
|
35
|
+
elsif join.is_a?(Hash)
|
36
|
+
join[name]
|
37
|
+
else
|
38
|
+
raise ArgumentError, "joins list should be initialized by list of Arel::Nodes::Join"
|
39
|
+
end
|
24
40
|
end
|
41
|
+
|
42
|
+
counts.sum
|
25
43
|
end
|
26
44
|
|
27
|
-
|
28
|
-
|
45
|
+
# table_joins is an array of arel joins which might conflict with the aliases we assign here
|
46
|
+
def initialize(connection, aliases)
|
47
|
+
@aliases = aliases
|
48
|
+
@connection = connection
|
49
|
+
end
|
29
50
|
|
51
|
+
def aliased_table_for(table_name, aliased_name, type_caster)
|
30
52
|
if aliases[table_name].zero?
|
31
53
|
# If it's zero, we can have our table_name
|
32
54
|
aliases[table_name] = 1
|
33
|
-
table_name
|
55
|
+
Arel::Table.new(table_name, type_caster: type_caster)
|
34
56
|
else
|
35
57
|
# Otherwise, we need to use an alias
|
36
|
-
aliased_name = connection.table_alias_for(aliased_name)
|
58
|
+
aliased_name = @connection.table_alias_for(aliased_name)
|
37
59
|
|
38
60
|
# Update the count
|
39
61
|
aliases[aliased_name] += 1
|
40
62
|
|
41
|
-
if aliases[aliased_name] > 1
|
63
|
+
table_alias = if aliases[aliased_name] > 1
|
42
64
|
"#{truncate(aliased_name)}_#{aliases[aliased_name]}"
|
43
65
|
else
|
44
66
|
aliased_name
|
45
67
|
end
|
68
|
+
Arel::Table.new(table_name, type_caster: type_caster).alias(table_alias)
|
46
69
|
end
|
47
70
|
end
|
48
71
|
|
49
|
-
|
50
|
-
|
51
|
-
def initial_count_for(name)
|
52
|
-
return 0 if Arel::Table === table_joins
|
53
|
-
|
54
|
-
# quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase
|
55
|
-
quoted_name = connection.quote_table_name(name).downcase
|
72
|
+
attr_reader :aliases
|
56
73
|
|
57
|
-
|
58
|
-
if join.is_a?(Arel::Nodes::StringJoin)
|
59
|
-
# Table names + table aliases
|
60
|
-
join.left.downcase.scan(
|
61
|
-
/join(?:\s+\w+)?\s+(\S+\s+)?#{quoted_name}\son/
|
62
|
-
).size
|
63
|
-
else
|
64
|
-
join.left.table_name == name ? 1 : 0
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
counts.sum
|
69
|
-
end
|
74
|
+
private
|
70
75
|
|
71
76
|
def truncate(name)
|
72
|
-
name.slice(0, connection.table_alias_length - 2)
|
77
|
+
name.slice(0, @connection.table_alias_length - 2)
|
73
78
|
end
|
74
79
|
end
|
75
80
|
end
|
@@ -1,5 +1,6 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/array/wrap"
|
3
4
|
|
4
5
|
module ActiveRecord
|
5
6
|
module Associations
|
@@ -9,47 +10,56 @@ module ActiveRecord
|
|
9
10
|
#
|
10
11
|
# Association
|
11
12
|
# SingularAssociation
|
12
|
-
# HasOneAssociation
|
13
|
+
# HasOneAssociation + ForeignAssociation
|
13
14
|
# HasOneThroughAssociation + ThroughAssociation
|
14
15
|
# BelongsToAssociation
|
15
16
|
# BelongsToPolymorphicAssociation
|
16
17
|
# CollectionAssociation
|
17
|
-
#
|
18
|
-
# HasManyAssociation
|
18
|
+
# HasManyAssociation + ForeignAssociation
|
19
19
|
# HasManyThroughAssociation + ThroughAssociation
|
20
|
+
#
|
21
|
+
# Associations in Active Record are middlemen between the object that
|
22
|
+
# holds the association, known as the <tt>owner</tt>, and the associated
|
23
|
+
# result set, known as the <tt>target</tt>. Association metadata is available in
|
24
|
+
# <tt>reflection</tt>, which is an instance of <tt>ActiveRecord::Reflection::AssociationReflection</tt>.
|
25
|
+
#
|
26
|
+
# For example, given
|
27
|
+
#
|
28
|
+
# class Blog < ActiveRecord::Base
|
29
|
+
# has_many :posts
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# blog = Blog.first
|
33
|
+
#
|
34
|
+
# The association of <tt>blog.posts</tt> has the object +blog+ as its
|
35
|
+
# <tt>owner</tt>, the collection of its posts as <tt>target</tt>, and
|
36
|
+
# the <tt>reflection</tt> object represents a <tt>:has_many</tt> macro.
|
20
37
|
class Association #:nodoc:
|
21
38
|
attr_reader :owner, :target, :reflection
|
22
39
|
|
23
|
-
delegate :options, :
|
40
|
+
delegate :options, to: :reflection
|
24
41
|
|
25
42
|
def initialize(owner, reflection)
|
26
43
|
reflection.check_validity!
|
27
44
|
|
28
|
-
@target = nil
|
29
45
|
@owner, @reflection = owner, reflection
|
30
|
-
@updated = false
|
31
46
|
|
32
47
|
reset
|
33
48
|
reset_scope
|
34
49
|
end
|
35
50
|
|
36
|
-
# Returns the name of the table of the related class:
|
37
|
-
#
|
38
|
-
# post.comments.aliased_table_name # => "comments"
|
39
|
-
#
|
40
|
-
def aliased_table_name
|
41
|
-
reflection.klass.table_name
|
42
|
-
end
|
43
|
-
|
44
51
|
# Resets the \loaded flag to +false+ and sets the \target to +nil+.
|
45
52
|
def reset
|
46
53
|
@loaded = false
|
47
|
-
IdentityMap.remove(target) if IdentityMap.enabled? && target
|
48
54
|
@target = nil
|
55
|
+
@stale_state = nil
|
56
|
+
@inversed = false
|
49
57
|
end
|
50
58
|
|
51
59
|
# Reloads the \target and returns +self+ on success.
|
52
|
-
|
60
|
+
# The QueryCache is cleared if +force+ is true.
|
61
|
+
def reload(force = false)
|
62
|
+
klass.connection.clear_query_cache if force && klass
|
53
63
|
reset
|
54
64
|
reset_scope
|
55
65
|
load_target
|
@@ -63,18 +73,19 @@ module ActiveRecord
|
|
63
73
|
|
64
74
|
# Asserts the \target has been loaded setting the \loaded flag to +true+.
|
65
75
|
def loaded!
|
66
|
-
@loaded
|
76
|
+
@loaded = true
|
67
77
|
@stale_state = stale_state
|
78
|
+
@inversed = false
|
68
79
|
end
|
69
80
|
|
70
81
|
# The target is stale if the target no longer points to the record(s) that the
|
71
82
|
# relevant foreign_key(s) refers to. If stale, the association accessor method
|
72
83
|
# on the owner will reload the target. It's up to subclasses to implement the
|
73
|
-
#
|
84
|
+
# stale_state method if relevant.
|
74
85
|
#
|
75
86
|
# Note that if the target has not been loaded, it is not considered stale.
|
76
87
|
def stale_target?
|
77
|
-
loaded? && @stale_state != stale_state
|
88
|
+
!@inversed && loaded? && @stale_state != stale_state
|
78
89
|
end
|
79
90
|
|
80
91
|
# Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
|
@@ -83,20 +94,8 @@ module ActiveRecord
|
|
83
94
|
loaded!
|
84
95
|
end
|
85
96
|
|
86
|
-
def
|
87
|
-
target_scope.merge(association_scope)
|
88
|
-
end
|
89
|
-
|
90
|
-
# The scope for this association.
|
91
|
-
#
|
92
|
-
# Note that the association_scope is merged into the target_scope only when the
|
93
|
-
# scoped method is called. This is because at that point the call may be surrounded
|
94
|
-
# by scope.scoping { ... } or with_scope { ... } etc, which affects the scope which
|
95
|
-
# actually gets built.
|
96
|
-
def association_scope
|
97
|
-
if klass
|
98
|
-
@association_scope ||= AssociationScope.new(self).scope
|
99
|
-
end
|
97
|
+
def scope
|
98
|
+
target_scope.merge!(association_scope)
|
100
99
|
end
|
101
100
|
|
102
101
|
def reset_scope
|
@@ -105,22 +104,46 @@ module ActiveRecord
|
|
105
104
|
|
106
105
|
# Set the inverse association, if possible
|
107
106
|
def set_inverse_instance(record)
|
108
|
-
if
|
109
|
-
inverse
|
110
|
-
inverse.target = owner
|
107
|
+
if inverse = inverse_association_for(record)
|
108
|
+
inverse.inversed_from(owner)
|
111
109
|
end
|
110
|
+
record
|
112
111
|
end
|
113
112
|
|
114
|
-
|
113
|
+
def set_inverse_instance_from_queries(record)
|
114
|
+
if inverse = inverse_association_for(record)
|
115
|
+
inverse.inversed_from_queries(owner)
|
116
|
+
end
|
117
|
+
record
|
118
|
+
end
|
119
|
+
|
120
|
+
# Remove the inverse association, if possible
|
121
|
+
def remove_inverse_instance(record)
|
122
|
+
if inverse = inverse_association_for(record)
|
123
|
+
inverse.inversed_from(nil)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def inversed_from(record)
|
128
|
+
self.target = record
|
129
|
+
@inversed = !!record
|
130
|
+
end
|
131
|
+
alias :inversed_from_queries :inversed_from
|
132
|
+
|
133
|
+
# Returns the class of the target. belongs_to polymorphic overrides this to look at the
|
115
134
|
# polymorphic_type field on the owner.
|
116
135
|
def klass
|
117
136
|
reflection.klass
|
118
137
|
end
|
119
138
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
139
|
+
def extensions
|
140
|
+
extensions = klass.default_extensions | reflection.extensions
|
141
|
+
|
142
|
+
if reflection.scope
|
143
|
+
extensions |= reflection.scope_for(klass.unscoped, owner).extensions
|
144
|
+
end
|
145
|
+
|
146
|
+
extensions
|
124
147
|
end
|
125
148
|
|
126
149
|
# Loads the \target if needed and returns it.
|
@@ -134,32 +157,80 @@ module ActiveRecord
|
|
134
157
|
# ActiveRecord::RecordNotFound is rescued within the method, and it is
|
135
158
|
# not reraised. The proxy is \reset and +nil+ is the return value.
|
136
159
|
def load_target
|
137
|
-
if find_target?
|
138
|
-
|
139
|
-
if IdentityMap.enabled? && association_class && association_class.respond_to?(:base_class)
|
140
|
-
@target = IdentityMap.get(association_class, owner[reflection.foreign_key])
|
141
|
-
end
|
142
|
-
rescue NameError
|
143
|
-
nil
|
144
|
-
ensure
|
145
|
-
@target ||= find_target
|
146
|
-
end
|
147
|
-
end
|
160
|
+
@target = find_target if (@stale_state && stale_target?) || find_target?
|
161
|
+
|
148
162
|
loaded! unless loaded?
|
149
163
|
target
|
150
164
|
rescue ActiveRecord::RecordNotFound
|
151
165
|
reset
|
152
166
|
end
|
153
167
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
168
|
+
# We can't dump @reflection and @through_reflection since it contains the scope proc
|
169
|
+
def marshal_dump
|
170
|
+
ivars = (instance_variables - [:@reflection, :@through_reflection]).map { |name| [name, instance_variable_get(name)] }
|
171
|
+
[@reflection.name, ivars]
|
172
|
+
end
|
173
|
+
|
174
|
+
def marshal_load(data)
|
175
|
+
reflection_name, ivars = data
|
176
|
+
ivars.each { |name, val| instance_variable_set(name, val) }
|
177
|
+
@reflection = @owner.class._reflect_on_association(reflection_name)
|
178
|
+
end
|
179
|
+
|
180
|
+
def initialize_attributes(record, except_from_scope_attributes = nil) #:nodoc:
|
181
|
+
except_from_scope_attributes ||= {}
|
182
|
+
skip_assign = [reflection.foreign_key, reflection.type].compact
|
183
|
+
assigned_keys = record.changed_attribute_names_to_save
|
184
|
+
assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
|
185
|
+
attributes = scope_for_create.except!(*(assigned_keys - skip_assign))
|
186
|
+
record.send(:_assign_attributes, attributes) if attributes.any?
|
187
|
+
set_inverse_instance(record)
|
188
|
+
end
|
189
|
+
|
190
|
+
def create(attributes = {}, &block)
|
191
|
+
_create_record(attributes, &block)
|
192
|
+
end
|
193
|
+
|
194
|
+
def create!(attributes = {}, &block)
|
195
|
+
_create_record(attributes, true, &block)
|
160
196
|
end
|
161
197
|
|
162
198
|
private
|
199
|
+
def find_target
|
200
|
+
scope = self.scope
|
201
|
+
return scope.to_a if skip_statement_cache?(scope)
|
202
|
+
|
203
|
+
conn = klass.connection
|
204
|
+
sc = reflection.association_scope_cache(conn, owner) do |params|
|
205
|
+
as = AssociationScope.create { params.bind }
|
206
|
+
target_scope.merge!(as.scope(self))
|
207
|
+
end
|
208
|
+
|
209
|
+
binds = AssociationScope.get_bind_values(owner, reflection.chain)
|
210
|
+
sc.execute(binds, conn) { |record| set_inverse_instance(record) } || []
|
211
|
+
end
|
212
|
+
|
213
|
+
# The scope for this association.
|
214
|
+
#
|
215
|
+
# Note that the association_scope is merged into the target_scope only when the
|
216
|
+
# scope method is called. This is because at that point the call may be surrounded
|
217
|
+
# by scope.scoping { ... } or unscoped { ... } etc, which affects the scope which
|
218
|
+
# actually gets built.
|
219
|
+
def association_scope
|
220
|
+
if klass
|
221
|
+
@association_scope ||= AssociationScope.scope(self)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
|
226
|
+
# through association's scope)
|
227
|
+
def target_scope
|
228
|
+
AssociationRelation.create(klass, self).merge!(klass.scope_for_association)
|
229
|
+
end
|
230
|
+
|
231
|
+
def scope_for_create
|
232
|
+
scope.scope_for_create
|
233
|
+
end
|
163
234
|
|
164
235
|
def find_target?
|
165
236
|
!loaded? && (!owner.new_record? || foreign_key_present?) && klass
|
@@ -168,11 +239,11 @@ module ActiveRecord
|
|
168
239
|
def creation_attributes
|
169
240
|
attributes = {}
|
170
241
|
|
171
|
-
if reflection.
|
242
|
+
if (reflection.has_one? || reflection.collection?) && !options[:through]
|
172
243
|
attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
|
173
244
|
|
174
|
-
if reflection.
|
175
|
-
attributes[reflection.type] = owner.class.
|
245
|
+
if reflection.type
|
246
|
+
attributes[reflection.type] = owner.class.polymorphic_name
|
176
247
|
end
|
177
248
|
end
|
178
249
|
|
@@ -184,13 +255,14 @@ module ActiveRecord
|
|
184
255
|
creation_attributes.each { |key, value| record[key] = value }
|
185
256
|
end
|
186
257
|
|
187
|
-
#
|
258
|
+
# Returns true if there is a foreign key present on the owner which
|
188
259
|
# references the target. This is used to determine whether we can load
|
189
260
|
# the target if the owner is currently a new record (and therefore
|
190
|
-
# without a key).
|
261
|
+
# without a key). If the owner is a new record then foreign_key must
|
262
|
+
# be present in order to load target.
|
191
263
|
#
|
192
264
|
# Currently implemented by belongs_to (vanilla and polymorphic) and
|
193
|
-
# has_one/has_many :through associations which go through a belongs_to
|
265
|
+
# has_one/has_many :through associations which go through a belongs_to.
|
194
266
|
def foreign_key_present?
|
195
267
|
false
|
196
268
|
end
|
@@ -198,10 +270,20 @@ module ActiveRecord
|
|
198
270
|
# Raises ActiveRecord::AssociationTypeMismatch unless +record+ is of
|
199
271
|
# the kind of the class of the associated objects. Meant to be used as
|
200
272
|
# a sanity check when you are about to assign an associated record.
|
201
|
-
def raise_on_type_mismatch(record)
|
202
|
-
unless record.is_a?(reflection.klass)
|
203
|
-
|
204
|
-
|
273
|
+
def raise_on_type_mismatch!(record)
|
274
|
+
unless record.is_a?(reflection.klass)
|
275
|
+
fresh_class = reflection.class_name.safe_constantize
|
276
|
+
unless fresh_class && record.is_a?(fresh_class)
|
277
|
+
message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, "\
|
278
|
+
"got #{record.inspect} which is an instance of #{record.class}(##{record.class.object_id})"
|
279
|
+
raise ActiveRecord::AssociationTypeMismatch, message
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def inverse_association_for(record)
|
285
|
+
if invertible_for?(record)
|
286
|
+
record.association(inverse_reflection_for(record).name)
|
205
287
|
end
|
206
288
|
end
|
207
289
|
|
@@ -212,28 +294,38 @@ module ActiveRecord
|
|
212
294
|
reflection.inverse_of
|
213
295
|
end
|
214
296
|
|
215
|
-
#
|
297
|
+
# Returns true if inverse association on the given record needs to be set.
|
298
|
+
# This method is redefined by subclasses.
|
216
299
|
def invertible_for?(record)
|
217
|
-
inverse_reflection_for(record)
|
300
|
+
foreign_key_for?(record) && inverse_reflection_for(record)
|
301
|
+
end
|
302
|
+
|
303
|
+
# Returns true if record contains the foreign_key
|
304
|
+
def foreign_key_for?(record)
|
305
|
+
record.has_attribute?(reflection.foreign_key)
|
218
306
|
end
|
219
307
|
|
220
308
|
# This should be implemented to return the values of the relevant key(s) on the owner,
|
221
|
-
# so that when
|
309
|
+
# so that when stale_state is different from the value stored on the last find_target,
|
222
310
|
# the target is stale.
|
223
311
|
#
|
224
|
-
# This is only relevant to certain associations, which is why it returns nil by default.
|
312
|
+
# This is only relevant to certain associations, which is why it returns +nil+ by default.
|
225
313
|
def stale_state
|
226
314
|
end
|
227
315
|
|
228
|
-
def
|
229
|
-
|
316
|
+
def build_record(attributes)
|
317
|
+
reflection.build_association(attributes) do |record|
|
318
|
+
initialize_attributes(record, attributes)
|
319
|
+
yield(record) if block_given?
|
320
|
+
end
|
230
321
|
end
|
231
322
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
323
|
+
# Returns true if statement cache should be skipped on the association reader.
|
324
|
+
def skip_statement_cache?(scope)
|
325
|
+
reflection.has_scope? ||
|
326
|
+
scope.eager_loading? ||
|
327
|
+
klass.scope_attributes? ||
|
328
|
+
reflection.source_reflection.active_record.default_scopes.any?
|
237
329
|
end
|
238
330
|
end
|
239
331
|
end
|