activerecord 2.3.18 → 3.2.22
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 +1014 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +222 -0
- data/examples/performance.rb +100 -126
- data/examples/simple.rb +14 -0
- data/lib/active_record/aggregations.rb +93 -99
- data/lib/active_record/associations/alias_tracker.rb +76 -0
- data/lib/active_record/associations/association.rb +247 -0
- data/lib/active_record/associations/association_scope.rb +134 -0
- data/lib/active_record/associations/belongs_to_association.rb +54 -61
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +17 -59
- data/lib/active_record/associations/builder/association.rb +55 -0
- data/lib/active_record/associations/builder/belongs_to.rb +88 -0
- data/lib/active_record/associations/builder/collection_association.rb +75 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -0
- data/lib/active_record/associations/builder/has_many.rb +71 -0
- data/lib/active_record/associations/builder/has_one.rb +62 -0
- data/lib/active_record/associations/builder/singular_association.rb +32 -0
- data/lib/active_record/associations/collection_association.rb +580 -0
- data/lib/active_record/associations/collection_proxy.rb +133 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +39 -119
- data/lib/active_record/associations/has_many_association.rb +60 -79
- data/lib/active_record/associations/has_many_through_association.rb +127 -206
- data/lib/active_record/associations/has_one_association.rb +55 -114
- data/lib/active_record/associations/has_one_through_association.rb +25 -26
- data/lib/active_record/associations/join_dependency/join_association.rb +159 -0
- data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
- data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
- data/lib/active_record/associations/join_dependency.rb +214 -0
- data/lib/active_record/associations/join_helper.rb +55 -0
- data/lib/active_record/associations/preloader/association.rb +125 -0
- data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
- data/lib/active_record/associations/preloader/collection_association.rb +24 -0
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
- data/lib/active_record/associations/preloader/has_many.rb +17 -0
- data/lib/active_record/associations/preloader/has_many_through.rb +15 -0
- data/lib/active_record/associations/preloader/has_one.rb +23 -0
- data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
- data/lib/active_record/associations/preloader/singular_association.rb +21 -0
- data/lib/active_record/associations/preloader/through_association.rb +67 -0
- data/lib/active_record/associations/preloader.rb +181 -0
- data/lib/active_record/associations/singular_association.rb +64 -0
- data/lib/active_record/associations/through_association.rb +87 -0
- data/lib/active_record/associations.rb +693 -1337
- data/lib/active_record/attribute_assignment.rb +221 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +31 -0
- data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +32 -0
- data/lib/active_record/attribute_methods/dirty.rb +111 -0
- data/lib/active_record/attribute_methods/primary_key.rb +114 -0
- data/lib/active_record/attribute_methods/query.rb +39 -0
- data/lib/active_record/attribute_methods/read.rb +136 -0
- data/lib/active_record/attribute_methods/serialization.rb +120 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +65 -0
- data/lib/active_record/attribute_methods/write.rb +70 -0
- data/lib/active_record/attribute_methods.rb +211 -339
- data/lib/active_record/autosave_association.rb +179 -149
- data/lib/active_record/base.rb +401 -2907
- data/lib/active_record/callbacks.rb +91 -176
- data/lib/active_record/coders/yaml_column.rb +41 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +236 -119
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +110 -58
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +12 -11
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +175 -74
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -35
- data/lib/active_record/connection_adapters/abstract/quoting.rb +71 -21
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +81 -311
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +194 -78
- data/lib/active_record/connection_adapters/abstract_adapter.rb +130 -83
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +676 -0
- data/lib/active_record/connection_adapters/column.rb +296 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +280 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +272 -493
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +650 -405
- data/lib/active_record/connection_adapters/schema_cache.rb +69 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +30 -9
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +276 -147
- data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
- data/lib/active_record/counter_cache.rb +123 -0
- data/lib/active_record/dynamic_finder_match.rb +41 -14
- data/lib/active_record/dynamic_matchers.rb +84 -0
- data/lib/active_record/dynamic_scope_match.rb +13 -15
- data/lib/active_record/errors.rb +195 -0
- data/lib/active_record/explain.rb +86 -0
- data/lib/active_record/explain_subscriber.rb +25 -0
- data/lib/active_record/fixtures/file.rb +65 -0
- data/lib/active_record/fixtures.rb +695 -770
- data/lib/active_record/identity_map.rb +162 -0
- data/lib/active_record/inheritance.rb +174 -0
- data/lib/active_record/integration.rb +60 -0
- data/lib/active_record/locale/en.yml +9 -27
- data/lib/active_record/locking/optimistic.rb +76 -73
- data/lib/active_record/locking/pessimistic.rb +32 -10
- data/lib/active_record/log_subscriber.rb +72 -0
- data/lib/active_record/migration/command_recorder.rb +105 -0
- data/lib/active_record/migration.rb +415 -205
- data/lib/active_record/model_schema.rb +368 -0
- data/lib/active_record/nested_attributes.rb +153 -63
- data/lib/active_record/observer.rb +27 -103
- data/lib/active_record/persistence.rb +376 -0
- data/lib/active_record/query_cache.rb +49 -8
- data/lib/active_record/querying.rb +58 -0
- data/lib/active_record/railtie.rb +131 -0
- data/lib/active_record/railties/console_sandbox.rb +6 -0
- data/lib/active_record/railties/controller_runtime.rb +49 -0
- data/lib/active_record/railties/databases.rake +659 -0
- data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
- data/lib/active_record/readonly_attributes.rb +26 -0
- data/lib/active_record/reflection.rb +269 -120
- data/lib/active_record/relation/batches.rb +90 -0
- data/lib/active_record/relation/calculations.rb +372 -0
- data/lib/active_record/relation/delegation.rb +49 -0
- data/lib/active_record/relation/finder_methods.rb +402 -0
- data/lib/active_record/relation/predicate_builder.rb +63 -0
- data/lib/active_record/relation/query_methods.rb +417 -0
- data/lib/active_record/relation/spawn_methods.rb +180 -0
- data/lib/active_record/relation.rb +537 -0
- data/lib/active_record/result.rb +40 -0
- data/lib/active_record/sanitization.rb +194 -0
- data/lib/active_record/schema.rb +9 -6
- data/lib/active_record/schema_dumper.rb +55 -32
- data/lib/active_record/scoping/default.rb +142 -0
- data/lib/active_record/scoping/named.rb +200 -0
- data/lib/active_record/scoping.rb +152 -0
- data/lib/active_record/serialization.rb +8 -91
- data/lib/active_record/serializers/xml_serializer.rb +43 -197
- data/lib/active_record/session_store.rb +129 -103
- data/lib/active_record/store.rb +52 -0
- data/lib/active_record/test_case.rb +30 -23
- data/lib/active_record/timestamp.rb +95 -52
- data/lib/active_record/transactions.rb +212 -66
- data/lib/active_record/translation.rb +22 -0
- data/lib/active_record/validations/associated.rb +43 -0
- data/lib/active_record/validations/uniqueness.rb +180 -0
- data/lib/active_record/validations.rb +43 -1106
- data/lib/active_record/version.rb +5 -4
- data/lib/active_record.rb +121 -48
- data/lib/rails/generators/active_record/migration/migration_generator.rb +25 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +34 -0
- data/lib/rails/generators/active_record/migration.rb +15 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +47 -0
- data/lib/rails/generators/active_record/model/templates/migration.rb +15 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +12 -0
- data/lib/rails/generators/active_record/model/templates/module.rb +7 -0
- data/lib/rails/generators/active_record/observer/observer_generator.rb +15 -0
- data/lib/rails/generators/active_record/observer/templates/observer.rb +4 -0
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +25 -0
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +12 -0
- data/lib/rails/generators/active_record.rb +25 -0
- metadata +187 -363
- data/CHANGELOG +0 -5904
- data/README +0 -351
- data/RUNNING_UNIT_TESTS +0 -36
- data/Rakefile +0 -268
- data/install.rb +0 -30
- data/lib/active_record/association_preload.rb +0 -406
- data/lib/active_record/associations/association_collection.rb +0 -533
- data/lib/active_record/associations/association_proxy.rb +0 -288
- data/lib/active_record/batches.rb +0 -85
- data/lib/active_record/calculations.rb +0 -321
- data/lib/active_record/dirty.rb +0 -183
- data/lib/active_record/named_scope.rb +0 -197
- data/lib/active_record/serializers/json_serializer.rb +0 -91
- data/lib/activerecord.rb +0 -2
- data/test/assets/example.log +0 -1
- data/test/assets/flowers.jpg +0 -0
- data/test/cases/aaa_create_tables_test.rb +0 -24
- data/test/cases/active_schema_test_mysql.rb +0 -122
- data/test/cases/active_schema_test_postgresql.rb +0 -24
- data/test/cases/adapter_test.rb +0 -144
- data/test/cases/aggregations_test.rb +0 -167
- data/test/cases/ar_schema_test.rb +0 -32
- data/test/cases/associations/belongs_to_associations_test.rb +0 -438
- data/test/cases/associations/callbacks_test.rb +0 -161
- data/test/cases/associations/cascaded_eager_loading_test.rb +0 -131
- data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +0 -36
- data/test/cases/associations/eager_load_nested_include_test.rb +0 -131
- data/test/cases/associations/eager_load_nested_polymorphic_include.rb +0 -19
- data/test/cases/associations/eager_singularization_test.rb +0 -145
- data/test/cases/associations/eager_test.rb +0 -852
- data/test/cases/associations/extension_test.rb +0 -62
- data/test/cases/associations/habtm_join_table_test.rb +0 -56
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +0 -827
- data/test/cases/associations/has_many_associations_test.rb +0 -1273
- data/test/cases/associations/has_many_through_associations_test.rb +0 -360
- data/test/cases/associations/has_one_associations_test.rb +0 -330
- data/test/cases/associations/has_one_through_associations_test.rb +0 -209
- data/test/cases/associations/inner_join_association_test.rb +0 -93
- data/test/cases/associations/inverse_associations_test.rb +0 -566
- data/test/cases/associations/join_model_test.rb +0 -712
- data/test/cases/associations_test.rb +0 -282
- data/test/cases/attribute_methods_test.rb +0 -305
- data/test/cases/autosave_association_test.rb +0 -1218
- data/test/cases/base_test.rb +0 -2166
- data/test/cases/batches_test.rb +0 -81
- data/test/cases/binary_test.rb +0 -30
- data/test/cases/calculations_test.rb +0 -360
- data/test/cases/callbacks_observers_test.rb +0 -38
- data/test/cases/callbacks_test.rb +0 -438
- data/test/cases/class_inheritable_attributes_test.rb +0 -32
- data/test/cases/column_alias_test.rb +0 -17
- data/test/cases/column_definition_test.rb +0 -70
- data/test/cases/connection_pool_test.rb +0 -25
- data/test/cases/connection_test_firebird.rb +0 -8
- data/test/cases/connection_test_mysql.rb +0 -65
- data/test/cases/copy_table_test_sqlite.rb +0 -80
- data/test/cases/counter_cache_test.rb +0 -84
- data/test/cases/database_statements_test.rb +0 -12
- data/test/cases/datatype_test_postgresql.rb +0 -204
- data/test/cases/date_time_test.rb +0 -37
- data/test/cases/default_test_firebird.rb +0 -16
- data/test/cases/defaults_test.rb +0 -111
- data/test/cases/deprecated_finder_test.rb +0 -30
- data/test/cases/dirty_test.rb +0 -316
- data/test/cases/finder_respond_to_test.rb +0 -76
- data/test/cases/finder_test.rb +0 -1098
- data/test/cases/fixtures_test.rb +0 -661
- data/test/cases/helper.rb +0 -68
- data/test/cases/i18n_test.rb +0 -46
- data/test/cases/inheritance_test.rb +0 -262
- data/test/cases/invalid_date_test.rb +0 -24
- data/test/cases/json_serialization_test.rb +0 -219
- data/test/cases/lifecycle_test.rb +0 -193
- data/test/cases/locking_test.rb +0 -350
- data/test/cases/method_scoping_test.rb +0 -704
- data/test/cases/migration_test.rb +0 -1649
- data/test/cases/migration_test_firebird.rb +0 -124
- data/test/cases/mixin_test.rb +0 -96
- data/test/cases/modules_test.rb +0 -109
- data/test/cases/multiple_db_test.rb +0 -85
- data/test/cases/named_scope_test.rb +0 -372
- data/test/cases/nested_attributes_test.rb +0 -840
- data/test/cases/pk_test.rb +0 -119
- data/test/cases/pooled_connections_test.rb +0 -103
- data/test/cases/query_cache_test.rb +0 -129
- data/test/cases/readonly_test.rb +0 -107
- data/test/cases/reflection_test.rb +0 -234
- data/test/cases/reload_models_test.rb +0 -22
- data/test/cases/repair_helper.rb +0 -50
- data/test/cases/reserved_word_test_mysql.rb +0 -176
- data/test/cases/sanitize_test.rb +0 -25
- data/test/cases/schema_authorization_test_postgresql.rb +0 -75
- data/test/cases/schema_dumper_test.rb +0 -211
- data/test/cases/schema_test_postgresql.rb +0 -178
- data/test/cases/serialization_test.rb +0 -47
- data/test/cases/sp_test_mysql.rb +0 -16
- data/test/cases/synonym_test_oracle.rb +0 -17
- data/test/cases/timestamp_test.rb +0 -75
- data/test/cases/transactions_test.rb +0 -543
- data/test/cases/unconnected_test.rb +0 -32
- data/test/cases/validations_i18n_test.rb +0 -925
- data/test/cases/validations_test.rb +0 -1684
- data/test/cases/xml_serialization_test.rb +0 -240
- data/test/cases/yaml_serialization_test.rb +0 -11
- data/test/config.rb +0 -5
- data/test/connections/jdbc_jdbcderby/connection.rb +0 -18
- data/test/connections/jdbc_jdbch2/connection.rb +0 -18
- data/test/connections/jdbc_jdbchsqldb/connection.rb +0 -18
- data/test/connections/jdbc_jdbcmysql/connection.rb +0 -26
- data/test/connections/jdbc_jdbcpostgresql/connection.rb +0 -26
- data/test/connections/jdbc_jdbcsqlite3/connection.rb +0 -25
- data/test/connections/native_db2/connection.rb +0 -25
- data/test/connections/native_firebird/connection.rb +0 -26
- data/test/connections/native_frontbase/connection.rb +0 -27
- data/test/connections/native_mysql/connection.rb +0 -25
- data/test/connections/native_openbase/connection.rb +0 -21
- data/test/connections/native_oracle/connection.rb +0 -27
- data/test/connections/native_postgresql/connection.rb +0 -21
- data/test/connections/native_sqlite/connection.rb +0 -25
- data/test/connections/native_sqlite3/connection.rb +0 -25
- data/test/connections/native_sqlite3/in_memory_connection.rb +0 -18
- data/test/connections/native_sybase/connection.rb +0 -23
- data/test/fixtures/accounts.yml +0 -29
- data/test/fixtures/all/developers.yml +0 -0
- data/test/fixtures/all/people.csv +0 -0
- data/test/fixtures/all/tasks.yml +0 -0
- data/test/fixtures/author_addresses.yml +0 -5
- data/test/fixtures/author_favorites.yml +0 -4
- data/test/fixtures/authors.yml +0 -9
- data/test/fixtures/binaries.yml +0 -132
- data/test/fixtures/books.yml +0 -7
- data/test/fixtures/categories/special_categories.yml +0 -9
- data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +0 -4
- data/test/fixtures/categories.yml +0 -14
- data/test/fixtures/categories_ordered.yml +0 -7
- data/test/fixtures/categories_posts.yml +0 -23
- data/test/fixtures/categorizations.yml +0 -17
- data/test/fixtures/clubs.yml +0 -6
- data/test/fixtures/comments.yml +0 -59
- data/test/fixtures/companies.yml +0 -56
- data/test/fixtures/computers.yml +0 -4
- data/test/fixtures/courses.yml +0 -7
- data/test/fixtures/customers.yml +0 -26
- data/test/fixtures/developers.yml +0 -21
- data/test/fixtures/developers_projects.yml +0 -17
- data/test/fixtures/edges.yml +0 -6
- data/test/fixtures/entrants.yml +0 -14
- data/test/fixtures/faces.yml +0 -11
- data/test/fixtures/fk_test_has_fk.yml +0 -3
- data/test/fixtures/fk_test_has_pk.yml +0 -2
- data/test/fixtures/funny_jokes.yml +0 -10
- data/test/fixtures/interests.yml +0 -33
- data/test/fixtures/items.yml +0 -4
- data/test/fixtures/jobs.yml +0 -7
- data/test/fixtures/legacy_things.yml +0 -3
- data/test/fixtures/mateys.yml +0 -4
- data/test/fixtures/member_types.yml +0 -6
- data/test/fixtures/members.yml +0 -6
- data/test/fixtures/memberships.yml +0 -20
- data/test/fixtures/men.yml +0 -5
- data/test/fixtures/minimalistics.yml +0 -2
- data/test/fixtures/mixed_case_monkeys.yml +0 -6
- data/test/fixtures/mixins.yml +0 -29
- data/test/fixtures/movies.yml +0 -7
- data/test/fixtures/naked/csv/accounts.csv +0 -1
- data/test/fixtures/naked/yml/accounts.yml +0 -1
- data/test/fixtures/naked/yml/companies.yml +0 -1
- data/test/fixtures/naked/yml/courses.yml +0 -1
- data/test/fixtures/organizations.yml +0 -5
- data/test/fixtures/owners.yml +0 -7
- data/test/fixtures/parrots.yml +0 -27
- data/test/fixtures/parrots_pirates.yml +0 -7
- data/test/fixtures/people.yml +0 -15
- data/test/fixtures/pets.yml +0 -14
- data/test/fixtures/pirates.yml +0 -9
- data/test/fixtures/polymorphic_designs.yml +0 -19
- data/test/fixtures/polymorphic_prices.yml +0 -19
- data/test/fixtures/posts.yml +0 -52
- data/test/fixtures/price_estimates.yml +0 -7
- data/test/fixtures/projects.yml +0 -7
- data/test/fixtures/readers.yml +0 -9
- data/test/fixtures/references.yml +0 -17
- data/test/fixtures/reserved_words/distinct.yml +0 -5
- data/test/fixtures/reserved_words/distincts_selects.yml +0 -11
- data/test/fixtures/reserved_words/group.yml +0 -14
- data/test/fixtures/reserved_words/select.yml +0 -8
- data/test/fixtures/reserved_words/values.yml +0 -7
- data/test/fixtures/ships.yml +0 -5
- data/test/fixtures/sponsors.yml +0 -9
- data/test/fixtures/subscribers.yml +0 -7
- data/test/fixtures/subscriptions.yml +0 -12
- data/test/fixtures/taggings.yml +0 -28
- data/test/fixtures/tags.yml +0 -7
- data/test/fixtures/tasks.yml +0 -7
- data/test/fixtures/tees.yml +0 -4
- data/test/fixtures/ties.yml +0 -4
- data/test/fixtures/topics.yml +0 -42
- data/test/fixtures/toys.yml +0 -4
- data/test/fixtures/treasures.yml +0 -10
- data/test/fixtures/vertices.yml +0 -4
- data/test/fixtures/warehouse-things.yml +0 -3
- data/test/fixtures/zines.yml +0 -5
- data/test/migrations/broken/100_migration_that_raises_exception.rb +0 -10
- data/test/migrations/decimal/1_give_me_big_numbers.rb +0 -15
- data/test/migrations/duplicate/1_people_have_last_names.rb +0 -9
- data/test/migrations/duplicate/2_we_need_reminders.rb +0 -12
- data/test/migrations/duplicate/3_foo.rb +0 -7
- data/test/migrations/duplicate/3_innocent_jointable.rb +0 -12
- data/test/migrations/duplicate_names/20080507052938_chunky.rb +0 -7
- data/test/migrations/duplicate_names/20080507053028_chunky.rb +0 -7
- data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +0 -12
- data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +0 -9
- data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +0 -12
- data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +0 -9
- data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +0 -8
- data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +0 -12
- data/test/migrations/missing/1000_people_have_middle_names.rb +0 -9
- data/test/migrations/missing/1_people_have_last_names.rb +0 -9
- data/test/migrations/missing/3_we_need_reminders.rb +0 -12
- data/test/migrations/missing/4_innocent_jointable.rb +0 -12
- data/test/migrations/valid/1_people_have_last_names.rb +0 -9
- data/test/migrations/valid/2_we_need_reminders.rb +0 -12
- data/test/migrations/valid/3_innocent_jointable.rb +0 -12
- data/test/models/author.rb +0 -151
- data/test/models/auto_id.rb +0 -4
- data/test/models/binary.rb +0 -2
- data/test/models/bird.rb +0 -9
- data/test/models/book.rb +0 -4
- data/test/models/categorization.rb +0 -5
- data/test/models/category.rb +0 -34
- data/test/models/citation.rb +0 -6
- data/test/models/club.rb +0 -13
- data/test/models/column_name.rb +0 -3
- data/test/models/comment.rb +0 -29
- data/test/models/company.rb +0 -173
- data/test/models/company_in_module.rb +0 -78
- data/test/models/computer.rb +0 -3
- data/test/models/contact.rb +0 -16
- data/test/models/contract.rb +0 -5
- data/test/models/course.rb +0 -3
- data/test/models/customer.rb +0 -73
- data/test/models/default.rb +0 -2
- data/test/models/developer.rb +0 -101
- data/test/models/edge.rb +0 -5
- data/test/models/entrant.rb +0 -3
- data/test/models/essay.rb +0 -3
- data/test/models/event.rb +0 -3
- data/test/models/event_author.rb +0 -8
- data/test/models/face.rb +0 -7
- data/test/models/guid.rb +0 -2
- data/test/models/interest.rb +0 -5
- data/test/models/invoice.rb +0 -4
- data/test/models/item.rb +0 -7
- data/test/models/job.rb +0 -5
- data/test/models/joke.rb +0 -3
- data/test/models/keyboard.rb +0 -3
- data/test/models/legacy_thing.rb +0 -3
- data/test/models/line_item.rb +0 -3
- data/test/models/man.rb +0 -9
- data/test/models/matey.rb +0 -4
- data/test/models/member.rb +0 -12
- data/test/models/member_detail.rb +0 -5
- data/test/models/member_type.rb +0 -3
- data/test/models/membership.rb +0 -9
- data/test/models/minimalistic.rb +0 -2
- data/test/models/mixed_case_monkey.rb +0 -3
- data/test/models/movie.rb +0 -5
- data/test/models/order.rb +0 -4
- data/test/models/organization.rb +0 -6
- data/test/models/owner.rb +0 -5
- data/test/models/parrot.rb +0 -22
- data/test/models/person.rb +0 -16
- data/test/models/pet.rb +0 -5
- data/test/models/pirate.rb +0 -80
- data/test/models/polymorphic_design.rb +0 -3
- data/test/models/polymorphic_price.rb +0 -3
- data/test/models/post.rb +0 -102
- data/test/models/price_estimate.rb +0 -3
- data/test/models/project.rb +0 -30
- data/test/models/reader.rb +0 -4
- data/test/models/reference.rb +0 -4
- data/test/models/reply.rb +0 -46
- data/test/models/ship.rb +0 -19
- data/test/models/ship_part.rb +0 -7
- data/test/models/sponsor.rb +0 -4
- data/test/models/subject.rb +0 -4
- data/test/models/subscriber.rb +0 -8
- data/test/models/subscription.rb +0 -4
- data/test/models/tag.rb +0 -7
- data/test/models/tagging.rb +0 -10
- data/test/models/task.rb +0 -3
- data/test/models/tee.rb +0 -4
- data/test/models/tie.rb +0 -4
- data/test/models/topic.rb +0 -80
- data/test/models/toy.rb +0 -6
- data/test/models/treasure.rb +0 -8
- data/test/models/vertex.rb +0 -9
- data/test/models/warehouse_thing.rb +0 -5
- data/test/models/zine.rb +0 -3
- data/test/schema/mysql_specific_schema.rb +0 -31
- data/test/schema/postgresql_specific_schema.rb +0 -114
- data/test/schema/schema.rb +0 -550
- data/test/schema/schema2.rb +0 -6
- data/test/schema/sqlite_specific_schema.rb +0 -25
@@ -1,13 +1,16 @@
|
|
1
|
+
require 'active_support/core_ext/array/wrap'
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
4
|
+
# = Active Record Autosave Association
|
5
|
+
#
|
6
|
+
# +AutosaveAssociation+ is a module that takes care of automatically saving
|
7
|
+
# associated records when their parent is saved. In addition to saving, it
|
8
|
+
# also destroys any associated records that were marked for destruction.
|
9
|
+
# (See +mark_for_destruction+ and <tt>marked_for_destruction?</tt>).
|
6
10
|
#
|
7
11
|
# Saving of the parent, its associations, and the destruction of marked
|
8
|
-
# associations, all happen inside
|
9
|
-
# database in an inconsistent state
|
10
|
-
# attributes and saving them.
|
12
|
+
# associations, all happen inside a transaction. This should never leave the
|
13
|
+
# database in an inconsistent state.
|
11
14
|
#
|
12
15
|
# If validations for any of the associations fail, their error messages will
|
13
16
|
# be applied to the parent.
|
@@ -15,9 +18,25 @@ module ActiveRecord
|
|
15
18
|
# Note that it also means that associations marked for destruction won't
|
16
19
|
# be destroyed directly. They will however still be marked for destruction.
|
17
20
|
#
|
18
|
-
#
|
21
|
+
# Note that <tt>:autosave => false</tt> is not same as not declaring <tt>:autosave</tt>.
|
22
|
+
# When the <tt>:autosave</tt> option is not present new associations are saved.
|
23
|
+
#
|
24
|
+
# == Validation
|
25
|
+
#
|
26
|
+
# Children records are validated unless <tt>:validate</tt> is +false+.
|
19
27
|
#
|
20
|
-
#
|
28
|
+
# == Callbacks
|
29
|
+
#
|
30
|
+
# Association with autosave option defines several callbacks on your
|
31
|
+
# model (before_save, after_create, after_update). Please note that
|
32
|
+
# callbacks are executed in the order they were defined in
|
33
|
+
# model. You should avoid modyfing the association content, before
|
34
|
+
# autosave callbacks are executed. Placing your callbacks after
|
35
|
+
# associations is usually a good practice.
|
36
|
+
#
|
37
|
+
# == Examples
|
38
|
+
#
|
39
|
+
# === One-to-one Example
|
21
40
|
#
|
22
41
|
# class Post
|
23
42
|
# has_one :author, :autosave => true
|
@@ -27,7 +46,7 @@ module ActiveRecord
|
|
27
46
|
# automatically _and_ atomically:
|
28
47
|
#
|
29
48
|
# post = Post.find(1)
|
30
|
-
# post.title
|
49
|
+
# post.title # => "The current global position of migrating ducks"
|
31
50
|
# post.author.name # => "alloy"
|
32
51
|
#
|
33
52
|
# post.title = "On the migration of ducks"
|
@@ -35,7 +54,7 @@ module ActiveRecord
|
|
35
54
|
#
|
36
55
|
# post.save
|
37
56
|
# post.reload
|
38
|
-
# post.title
|
57
|
+
# post.title # => "On the migration of ducks"
|
39
58
|
# post.author.name # => "Eloy Duran"
|
40
59
|
#
|
41
60
|
# Destroying an associated model, as part of the parent's save action, is as
|
@@ -45,6 +64,7 @@ module ActiveRecord
|
|
45
64
|
# post.author.marked_for_destruction? # => true
|
46
65
|
#
|
47
66
|
# Note that the model is _not_ yet removed from the database:
|
67
|
+
#
|
48
68
|
# id = post.author.id
|
49
69
|
# Author.find_by_id(id).nil? # => false
|
50
70
|
#
|
@@ -52,40 +72,49 @@ module ActiveRecord
|
|
52
72
|
# post.reload.author # => nil
|
53
73
|
#
|
54
74
|
# Now it _is_ removed from the database:
|
75
|
+
#
|
55
76
|
# Author.find_by_id(id).nil? # => true
|
56
77
|
#
|
57
78
|
# === One-to-many Example
|
58
79
|
#
|
59
|
-
#
|
80
|
+
# When <tt>:autosave</tt> is not declared new children are saved when their parent is saved:
|
60
81
|
#
|
61
82
|
# class Post
|
62
|
-
# has_many :comments
|
83
|
+
# has_many :comments # :autosave option is no declared
|
63
84
|
# end
|
64
85
|
#
|
65
|
-
#
|
66
|
-
#
|
86
|
+
# post = Post.new(:title => 'ruby rocks')
|
87
|
+
# post.comments.build(:body => 'hello world')
|
88
|
+
# post.save # => saves both post and comment
|
67
89
|
#
|
68
|
-
# post = Post.
|
69
|
-
# post.
|
70
|
-
# post.
|
71
|
-
# post.comments.last.body # => "Actually, your article should be named differently."
|
90
|
+
# post = Post.create(:title => 'ruby rocks')
|
91
|
+
# post.comments.build(:body => 'hello world')
|
92
|
+
# post.save # => saves both post and comment
|
72
93
|
#
|
73
|
-
# post
|
74
|
-
# post.comments.
|
94
|
+
# post = Post.create(:title => 'ruby rocks')
|
95
|
+
# post.comments.create(:body => 'hello world')
|
96
|
+
# post.save # => saves both post and comment
|
75
97
|
#
|
76
|
-
#
|
77
|
-
# post.reload
|
78
|
-
# post.title # => "On the migration of ducks"
|
79
|
-
# post.comments.last.body # => "Actually, your article should be named differently. [UPDATED]: You are right, thanks."
|
98
|
+
# When <tt>:autosave</tt> is true all children is saved, no matter whether they are new records:
|
80
99
|
#
|
81
|
-
#
|
82
|
-
#
|
100
|
+
# class Post
|
101
|
+
# has_many :comments, :autosave => true
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# post = Post.create(:title => 'ruby rocks')
|
105
|
+
# post.comments.create(:body => 'hello world')
|
106
|
+
# post.comments[0].body = 'hi everyone'
|
107
|
+
# post.save # => saves both post and comment, with 'hi everyone' as body
|
108
|
+
#
|
109
|
+
# Destroying one of the associated models as part of the parent's save action
|
110
|
+
# is as simple as marking it for destruction:
|
83
111
|
#
|
84
112
|
# post.comments.last.mark_for_destruction
|
85
113
|
# post.comments.last.marked_for_destruction? # => true
|
86
114
|
# post.comments.length # => 2
|
87
115
|
#
|
88
116
|
# Note that the model is _not_ yet removed from the database:
|
117
|
+
#
|
89
118
|
# id = post.comments.last.id
|
90
119
|
# Comment.find_by_id(id).nil? # => false
|
91
120
|
#
|
@@ -93,72 +122,58 @@ module ActiveRecord
|
|
93
122
|
# post.reload.comments.length # => 1
|
94
123
|
#
|
95
124
|
# Now it _is_ removed from the database:
|
96
|
-
# Comment.find_by_id(id).nil? # => true
|
97
|
-
#
|
98
|
-
# === Validation
|
99
|
-
#
|
100
|
-
# Validation is performed on the parent as usual, but also on all autosave
|
101
|
-
# enabled associations. If any of the associations fail validation, its
|
102
|
-
# error messages will be applied on the parents errors object and validation
|
103
|
-
# of the parent will fail.
|
104
|
-
#
|
105
|
-
# Consider a Post model with Author which validates the presence of its name
|
106
|
-
# attribute:
|
107
|
-
#
|
108
|
-
# class Post
|
109
|
-
# has_one :author, :autosave => true
|
110
|
-
# end
|
111
|
-
#
|
112
|
-
# class Author
|
113
|
-
# validates_presence_of :name
|
114
|
-
# end
|
115
|
-
#
|
116
|
-
# post = Post.find(1)
|
117
|
-
# post.author.name = ''
|
118
|
-
# post.save # => false
|
119
|
-
# post.errors # => #<ActiveRecord::Errors:0x174498c @errors={"author_name"=>["can't be blank"]}, @base=#<Post ...>>
|
120
|
-
#
|
121
|
-
# No validations will be performed on the associated models when validations
|
122
|
-
# are skipped for the parent:
|
123
125
|
#
|
124
|
-
#
|
125
|
-
|
126
|
-
# post.save(false) # => true
|
126
|
+
# Comment.find_by_id(id).nil? # => true
|
127
|
+
|
127
128
|
module AutosaveAssociation
|
128
|
-
|
129
|
+
extend ActiveSupport::Concern
|
129
130
|
|
130
|
-
|
131
|
-
base.class_eval do
|
132
|
-
base.extend(ClassMethods)
|
133
|
-
alias_method_chain :reload, :autosave_associations
|
131
|
+
ASSOCIATION_TYPES = %w{ HasOne HasMany BelongsTo HasAndBelongsToMany }
|
134
132
|
|
135
|
-
|
136
|
-
|
137
|
-
|
133
|
+
module AssociationBuilderExtension #:nodoc:
|
134
|
+
def self.included(base)
|
135
|
+
base.valid_options << :autosave
|
136
|
+
end
|
137
|
+
|
138
|
+
def build
|
139
|
+
reflection = super
|
140
|
+
model.send(:add_autosave_association_callbacks, reflection)
|
141
|
+
reflection
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
included do
|
146
|
+
ASSOCIATION_TYPES.each do |type|
|
147
|
+
Associations::Builder.const_get(type).send(:include, AssociationBuilderExtension)
|
138
148
|
end
|
139
149
|
end
|
140
150
|
|
141
151
|
module ClassMethods
|
142
152
|
private
|
143
153
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
154
|
+
def define_non_cyclic_method(name, reflection, &block)
|
155
|
+
define_method(name) do |*args|
|
156
|
+
result = true; @_already_called ||= {}
|
157
|
+
# Loop prevention for validation of associations
|
158
|
+
unless @_already_called[[name, reflection.name]]
|
159
|
+
begin
|
160
|
+
@_already_called[[name, reflection.name]]=true
|
161
|
+
result = instance_eval(&block)
|
162
|
+
ensure
|
163
|
+
@_already_called[[name, reflection.name]]=false
|
164
|
+
end
|
153
165
|
end
|
154
|
-
|
166
|
+
|
167
|
+
result
|
168
|
+
end
|
155
169
|
end
|
156
170
|
|
157
|
-
# Adds
|
171
|
+
# Adds validation and save callbacks for the association as specified by
|
158
172
|
# the +reflection+.
|
159
173
|
#
|
160
|
-
# For performance reasons, we don't check whether to validate at runtime
|
161
|
-
#
|
174
|
+
# For performance reasons, we don't check whether to validate at runtime.
|
175
|
+
# However the validation and callback methods are lazy and those methods
|
176
|
+
# get created when they are invoked for the very first time. However,
|
162
177
|
# this can change, for instance, when using nested attributes, which is
|
163
178
|
# called _after_ the association has been defined. Since we don't want
|
164
179
|
# the callbacks to get defined multiple times, there are guards that
|
@@ -173,16 +188,25 @@ module ActiveRecord
|
|
173
188
|
if collection
|
174
189
|
before_save :before_save_collection_association
|
175
190
|
|
176
|
-
|
191
|
+
define_non_cyclic_method(save_method, reflection) { save_collection_association(reflection) }
|
177
192
|
# Doesn't use after_save as that would save associations added in after_create/after_update twice
|
178
193
|
after_create save_method
|
179
194
|
after_update save_method
|
180
195
|
else
|
181
196
|
if reflection.macro == :has_one
|
182
197
|
define_method(save_method) { save_has_one_association(reflection) }
|
183
|
-
after_save
|
198
|
+
# Configures two callbacks instead of a single after_save so that
|
199
|
+
# the model may rely on their execution order relative to its
|
200
|
+
# own callbacks.
|
201
|
+
#
|
202
|
+
# For example, given that after_creates run before after_saves, if
|
203
|
+
# we configured instead an after_save there would be no way to fire
|
204
|
+
# a custom after_create callback after the child association gets
|
205
|
+
# created.
|
206
|
+
after_create save_method
|
207
|
+
after_update save_method
|
184
208
|
else
|
185
|
-
|
209
|
+
define_non_cyclic_method(save_method, reflection) { save_belongs_to_association(reflection) }
|
186
210
|
before_save save_method
|
187
211
|
end
|
188
212
|
end
|
@@ -190,20 +214,21 @@ module ActiveRecord
|
|
190
214
|
|
191
215
|
if reflection.validate? && !method_defined?(validation_method)
|
192
216
|
method = (collection ? :validate_collection_association : :validate_single_association)
|
193
|
-
|
217
|
+
define_non_cyclic_method(validation_method, reflection) { send(method, reflection) }
|
194
218
|
validate validation_method
|
195
219
|
end
|
196
220
|
end
|
197
221
|
end
|
198
222
|
|
199
|
-
# Reloads the attributes of the object as usual and
|
200
|
-
def
|
223
|
+
# Reloads the attributes of the object as usual and clears <tt>marked_for_destruction</tt> flag.
|
224
|
+
def reload(options = nil)
|
201
225
|
@marked_for_destruction = false
|
202
|
-
|
226
|
+
super
|
203
227
|
end
|
204
228
|
|
205
229
|
# Marks this record to be destroyed as part of the parents save transaction.
|
206
|
-
# This does _not_ actually destroy the record
|
230
|
+
# This does _not_ actually destroy the record instantly, rather child record will be destroyed
|
231
|
+
# when <tt>parent.save</tt> is called.
|
207
232
|
#
|
208
233
|
# Only useful if the <tt>:autosave</tt> option on the parent is enabled for this associated model.
|
209
234
|
def mark_for_destruction
|
@@ -222,7 +247,7 @@ module ActiveRecord
|
|
222
247
|
def changed_for_autosave?
|
223
248
|
new_record? || changed? || marked_for_destruction? || nested_records_changed_for_autosave?
|
224
249
|
end
|
225
|
-
|
250
|
+
|
226
251
|
private
|
227
252
|
|
228
253
|
# Returns the record for an association collection that should be validated
|
@@ -230,35 +255,29 @@ module ActiveRecord
|
|
230
255
|
# unless the parent is/was a new record itself.
|
231
256
|
def associated_records_to_validate_or_save(association, new_record, autosave)
|
232
257
|
if new_record
|
233
|
-
association
|
258
|
+
association && association.target
|
234
259
|
elsif autosave
|
235
|
-
association.target.
|
260
|
+
association.target.find_all { |record| record.changed_for_autosave? }
|
236
261
|
else
|
237
|
-
association.target.
|
262
|
+
association.target.find_all { |record| record.new_record? }
|
238
263
|
end
|
239
264
|
end
|
240
|
-
|
265
|
+
|
241
266
|
# go through nested autosave associations that are loaded in memory (without loading
|
242
267
|
# any new ones), and return true if is changed for autosave
|
243
268
|
def nested_records_changed_for_autosave?
|
244
|
-
self.class.reflect_on_all_autosave_associations.
|
245
|
-
|
246
|
-
|
247
|
-
return true if association.target && association.target.changed_for_autosave?
|
248
|
-
else
|
249
|
-
association.target.each {|record| return true if record.changed_for_autosave? }
|
250
|
-
end
|
251
|
-
end
|
269
|
+
self.class.reflect_on_all_autosave_associations.any? do |reflection|
|
270
|
+
association = association_instance_get(reflection.name)
|
271
|
+
association && Array.wrap(association.target).any? { |a| a.changed_for_autosave? }
|
252
272
|
end
|
253
|
-
false
|
254
273
|
end
|
255
|
-
|
274
|
+
|
256
275
|
# Validate the association if <tt>:validate</tt> or <tt>:autosave</tt> is
|
257
|
-
# turned on for the association
|
276
|
+
# turned on for the association.
|
258
277
|
def validate_single_association(reflection)
|
259
|
-
|
260
|
-
|
261
|
-
|
278
|
+
association = association_instance_get(reflection.name)
|
279
|
+
record = association && association.reader
|
280
|
+
association_valid?(reflection, record) if record
|
262
281
|
end
|
263
282
|
|
264
283
|
# Validate the associated records if <tt>:validate</tt> or
|
@@ -275,14 +294,15 @@ module ActiveRecord
|
|
275
294
|
# Returns whether or not the association is valid and applies any errors to
|
276
295
|
# the parent, <tt>self</tt>, if it wasn't. Skips any <tt>:autosave</tt>
|
277
296
|
# enabled records if they're marked_for_destruction? or destroyed.
|
278
|
-
def association_valid?(reflection,
|
279
|
-
return true if
|
297
|
+
def association_valid?(reflection, record)
|
298
|
+
return true if record.destroyed? || record.marked_for_destruction?
|
280
299
|
|
281
|
-
unless valid =
|
300
|
+
unless valid = record.valid?
|
282
301
|
if reflection.options[:autosave]
|
283
|
-
|
302
|
+
record.errors.each do |attribute, message|
|
284
303
|
attribute = "#{reflection.name}.#{attribute}"
|
285
|
-
errors
|
304
|
+
errors[attribute] << message
|
305
|
+
errors[attribute].uniq!
|
286
306
|
end
|
287
307
|
else
|
288
308
|
errors.add(reflection.name)
|
@@ -311,27 +331,38 @@ module ActiveRecord
|
|
311
331
|
autosave = reflection.options[:autosave]
|
312
332
|
|
313
333
|
if records = associated_records_to_validate_or_save(association, @new_record_before_save, autosave)
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
elsif autosave != false && (@new_record_before_save || record.new_record?)
|
320
|
-
if autosave
|
321
|
-
saved = association.send(:insert_record, record, false, false)
|
322
|
-
else
|
323
|
-
association.send(:insert_record, record)
|
324
|
-
end
|
325
|
-
elsif autosave
|
326
|
-
saved = record.save(false)
|
334
|
+
begin
|
335
|
+
if autosave
|
336
|
+
records_to_destroy = records.select(&:marked_for_destruction?)
|
337
|
+
records_to_destroy.each { |record| association.proxy.destroy(record) }
|
338
|
+
records -= records_to_destroy
|
327
339
|
end
|
328
340
|
|
329
|
-
|
341
|
+
records.each do |record|
|
342
|
+
next if record.destroyed?
|
343
|
+
|
344
|
+
saved = true
|
345
|
+
|
346
|
+
if autosave != false && (@new_record_before_save || record.new_record?)
|
347
|
+
if autosave
|
348
|
+
saved = association.insert_record(record, false)
|
349
|
+
else
|
350
|
+
association.insert_record(record) unless reflection.nested?
|
351
|
+
end
|
352
|
+
elsif autosave
|
353
|
+
saved = record.save(:validate => false)
|
354
|
+
end
|
355
|
+
|
356
|
+
raise ActiveRecord::Rollback unless saved
|
357
|
+
end
|
358
|
+
rescue
|
359
|
+
records.each {|x| IdentityMap.remove(x) } if IdentityMap.enabled?
|
360
|
+
raise
|
330
361
|
end
|
331
362
|
end
|
332
363
|
|
333
|
-
# reconstruct the
|
334
|
-
association.
|
364
|
+
# reconstruct the scope now that we know the owner's id
|
365
|
+
association.reset_scope if association.respond_to?(:reset_scope)
|
335
366
|
end
|
336
367
|
end
|
337
368
|
|
@@ -344,16 +375,21 @@ module ActiveRecord
|
|
344
375
|
# This all happens inside a transaction, _if_ the Transactions module is included into
|
345
376
|
# ActiveRecord::Base after the AutosaveAssociation module, which it does by default.
|
346
377
|
def save_has_one_association(reflection)
|
347
|
-
|
378
|
+
association = association_instance_get(reflection.name)
|
379
|
+
record = association && association.load_target
|
380
|
+
if record && !record.destroyed?
|
348
381
|
autosave = reflection.options[:autosave]
|
349
382
|
|
350
|
-
if autosave &&
|
351
|
-
|
383
|
+
if autosave && record.marked_for_destruction?
|
384
|
+
record.destroy
|
352
385
|
else
|
353
386
|
key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id
|
354
|
-
if autosave != false && (new_record? ||
|
355
|
-
|
356
|
-
|
387
|
+
if autosave != false && (new_record? || record.new_record? || record[reflection.foreign_key] != key || autosave)
|
388
|
+
unless reflection.through_reflection
|
389
|
+
record[reflection.foreign_key] = key
|
390
|
+
end
|
391
|
+
|
392
|
+
saved = record.save(:validate => !autosave)
|
357
393
|
raise ActiveRecord::Rollback if !saved && autosave
|
358
394
|
saved
|
359
395
|
end
|
@@ -361,30 +397,24 @@ module ActiveRecord
|
|
361
397
|
end
|
362
398
|
end
|
363
399
|
|
364
|
-
# Saves the associated record if it's new or <tt>:autosave</tt> is enabled
|
365
|
-
# on the association.
|
400
|
+
# Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
|
366
401
|
#
|
367
|
-
# In addition, it will destroy the association if it was marked for
|
368
|
-
# destruction with mark_for_destruction.
|
369
|
-
#
|
370
|
-
# This all happens inside a transaction, _if_ the Transactions module is included into
|
371
|
-
# ActiveRecord::Base after the AutosaveAssociation module, which it does by default.
|
402
|
+
# In addition, it will destroy the association if it was marked for destruction.
|
372
403
|
def save_belongs_to_association(reflection)
|
373
|
-
|
404
|
+
association = association_instance_get(reflection.name)
|
405
|
+
record = association && association.load_target
|
406
|
+
if record && !record.destroyed?
|
374
407
|
autosave = reflection.options[:autosave]
|
375
408
|
|
376
|
-
if autosave &&
|
377
|
-
|
409
|
+
if autosave && record.marked_for_destruction?
|
410
|
+
record.destroy
|
378
411
|
elsif autosave != false
|
379
|
-
saved =
|
412
|
+
saved = record.save(:validate => !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
|
380
413
|
|
381
414
|
if association.updated?
|
382
|
-
association_id =
|
383
|
-
self[reflection.
|
384
|
-
|
385
|
-
if reflection.options[:polymorphic]
|
386
|
-
self[reflection.options[:foreign_type]] = association.class.base_class.name.to_s
|
387
|
-
end
|
415
|
+
association_id = record.send(reflection.options[:primary_key] || :id)
|
416
|
+
self[reflection.foreign_key] = association_id
|
417
|
+
association.loaded!
|
388
418
|
end
|
389
419
|
|
390
420
|
saved if autosave
|