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
@@ -3,16 +3,17 @@ module ActiveRecord
|
|
3
3
|
# == What is Optimistic Locking
|
4
4
|
#
|
5
5
|
# Optimistic locking allows multiple users to access the same record for edits, and assumes a minimum of
|
6
|
-
# conflicts with the data.
|
7
|
-
# it was opened, an ActiveRecord::StaleObjectError is thrown if that has occurred
|
6
|
+
# conflicts with the data. It does this by checking whether another process has made changes to a record since
|
7
|
+
# it was opened, an <tt>ActiveRecord::StaleObjectError</tt> exception is thrown if that has occurred
|
8
|
+
# and the update is ignored.
|
8
9
|
#
|
9
|
-
# Check out ActiveRecord::Locking::Pessimistic for an alternative.
|
10
|
+
# Check out <tt>ActiveRecord::Locking::Pessimistic</tt> for an alternative.
|
10
11
|
#
|
11
12
|
# == Usage
|
12
13
|
#
|
13
|
-
# Active Records support optimistic locking if the field
|
14
|
-
# record increments the lock_version column and the locking facilities ensure that records instantiated twice
|
15
|
-
# will let the last one saved raise a StaleObjectError if the first was also updated. Example:
|
14
|
+
# Active Records support optimistic locking if the field +lock_version+ is present. Each update to the
|
15
|
+
# record increments the +lock_version+ column and the locking facilities ensure that records instantiated twice
|
16
|
+
# will let the last one saved raise a +StaleObjectError+ if the first was also updated. Example:
|
16
17
|
#
|
17
18
|
# p1 = Person.find(1)
|
18
19
|
# p2 = Person.find(1)
|
@@ -23,7 +24,7 @@ module ActiveRecord
|
|
23
24
|
# p2.first_name = "should fail"
|
24
25
|
# p2.save # Raises a ActiveRecord::StaleObjectError
|
25
26
|
#
|
26
|
-
# Optimistic locking will also check for stale data when objects are destroyed.
|
27
|
+
# Optimistic locking will also check for stale data when objects are destroyed. Example:
|
27
28
|
#
|
28
29
|
# p1 = Person.find(1)
|
29
30
|
# p2 = Person.find(1)
|
@@ -36,25 +37,20 @@ module ActiveRecord
|
|
36
37
|
# You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging,
|
37
38
|
# or otherwise apply the business logic needed to resolve the conflict.
|
38
39
|
#
|
39
|
-
#
|
40
|
+
# This locking mechanism will function inside a single Ruby process. To make it work across all
|
41
|
+
# web requests, the recommended approach is to add +lock_version+ as a hidden field to your form.
|
42
|
+
#
|
43
|
+
# You must ensure that your database schema defaults the +lock_version+ column to 0.
|
40
44
|
#
|
41
45
|
# This behavior can be turned off by setting <tt>ActiveRecord::Base.lock_optimistically = false</tt>.
|
42
|
-
# To override the name of the lock_version column, invoke the <tt>set_locking_column</tt> method.
|
46
|
+
# To override the name of the +lock_version+ column, invoke the <tt>set_locking_column</tt> method.
|
43
47
|
# This method uses the same syntax as <tt>set_table_name</tt>
|
44
48
|
module Optimistic
|
45
|
-
|
46
|
-
base.extend ClassMethods
|
47
|
-
|
48
|
-
base.cattr_accessor :lock_optimistically, :instance_writer => false
|
49
|
-
base.lock_optimistically = true
|
50
|
-
|
51
|
-
base.alias_method_chain :update, :lock
|
52
|
-
base.alias_method_chain :destroy, :lock
|
53
|
-
base.alias_method_chain :attributes_from_column_definition, :lock
|
49
|
+
extend ActiveSupport::Concern
|
54
50
|
|
55
|
-
|
56
|
-
|
57
|
-
|
51
|
+
included do
|
52
|
+
cattr_accessor :lock_optimistically, :instance_writer => false
|
53
|
+
self.lock_optimistically = true
|
58
54
|
end
|
59
55
|
|
60
56
|
def locking_enabled? #:nodoc:
|
@@ -62,69 +58,62 @@ module ActiveRecord
|
|
62
58
|
end
|
63
59
|
|
64
60
|
private
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
# start the lock version at zero. Note we can't use
|
70
|
-
# locking_enabled? at this point as @attributes may
|
71
|
-
# not have been initialized yet
|
72
|
-
|
73
|
-
if lock_optimistically && result.include?(self.class.locking_column)
|
74
|
-
result[self.class.locking_column] ||= 0
|
75
|
-
end
|
76
|
-
|
77
|
-
return result
|
61
|
+
def increment_lock
|
62
|
+
lock_col = self.class.locking_column
|
63
|
+
previous_lock_value = send(lock_col).to_i
|
64
|
+
send(lock_col + '=', previous_lock_value + 1)
|
78
65
|
end
|
79
66
|
|
80
|
-
def
|
81
|
-
return
|
67
|
+
def update(attribute_names = @attributes.keys) #:nodoc:
|
68
|
+
return super unless locking_enabled?
|
82
69
|
return 0 if attribute_names.empty?
|
83
70
|
|
84
71
|
lock_col = self.class.locking_column
|
85
|
-
|
86
|
-
|
72
|
+
previous_lock_value = send(lock_col).to_i
|
73
|
+
increment_lock
|
87
74
|
|
88
75
|
attribute_names += [lock_col]
|
89
76
|
attribute_names.uniq!
|
90
77
|
|
91
78
|
begin
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
79
|
+
relation = self.class.unscoped
|
80
|
+
|
81
|
+
stmt = relation.where(
|
82
|
+
relation.table[self.class.primary_key].eq(id).and(
|
83
|
+
relation.table[lock_col].eq(quote_value(previous_lock_value, self.class.columns_hash[lock_col]))
|
84
|
+
)
|
85
|
+
).arel.compile_update(arel_attributes_values(false, false, attribute_names))
|
86
|
+
|
87
|
+
affected_rows = connection.update stmt
|
98
88
|
|
99
89
|
unless affected_rows == 1
|
100
|
-
raise ActiveRecord::StaleObjectError, "
|
90
|
+
raise ActiveRecord::StaleObjectError.new(self, "update")
|
101
91
|
end
|
102
92
|
|
103
93
|
affected_rows
|
104
94
|
|
105
95
|
# If something went wrong, revert the version.
|
106
96
|
rescue Exception
|
107
|
-
send(lock_col + '=',
|
97
|
+
send(lock_col + '=', previous_lock_value)
|
108
98
|
raise
|
109
99
|
end
|
110
100
|
end
|
111
101
|
|
112
|
-
def
|
113
|
-
return
|
102
|
+
def destroy #:nodoc:
|
103
|
+
return super unless locking_enabled?
|
104
|
+
|
105
|
+
destroy_associations
|
114
106
|
|
115
|
-
|
107
|
+
if persisted?
|
108
|
+
table = self.class.arel_table
|
116
109
|
lock_col = self.class.locking_column
|
117
|
-
|
110
|
+
predicate = table[self.class.primary_key].eq(id).
|
111
|
+
and(table[lock_col].eq(send(lock_col).to_i))
|
118
112
|
|
119
|
-
affected_rows =
|
120
|
-
"DELETE FROM #{self.class.quoted_table_name} " +
|
121
|
-
"WHERE #{connection.quote_column_name(self.class.primary_key)} = #{quoted_id} " +
|
122
|
-
"AND #{self.class.quoted_locking_column} = #{quote_value(previous_value)}",
|
123
|
-
"#{self.class.name} Destroy"
|
124
|
-
)
|
113
|
+
affected_rows = self.class.unscoped.where(predicate).delete_all
|
125
114
|
|
126
115
|
unless affected_rows == 1
|
127
|
-
raise ActiveRecord::StaleObjectError, "
|
116
|
+
raise ActiveRecord::StaleObjectError.new(self, "destroy")
|
128
117
|
end
|
129
118
|
end
|
130
119
|
|
@@ -135,29 +124,31 @@ module ActiveRecord
|
|
135
124
|
module ClassMethods
|
136
125
|
DEFAULT_LOCKING_COLUMN = 'lock_version'
|
137
126
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
# Is optimistic locking enabled for this table? Returns true if the
|
145
|
-
# +lock_optimistically+ flag is set to true (which it is, by default)
|
146
|
-
# and the table includes the +locking_column+ column (defaults to
|
147
|
-
# +lock_version+).
|
127
|
+
# Returns true if the +lock_optimistically+ flag is set to true
|
128
|
+
# (which it is, by default) and the table includes the
|
129
|
+
# +locking_column+ column (defaults to +lock_version+).
|
148
130
|
def locking_enabled?
|
149
131
|
lock_optimistically && columns_hash[locking_column]
|
150
132
|
end
|
151
133
|
|
134
|
+
def locking_column=(value)
|
135
|
+
@original_locking_column = @locking_column if defined?(@locking_column)
|
136
|
+
@locking_column = value.to_s
|
137
|
+
end
|
138
|
+
|
152
139
|
# Set the column to use for optimistic locking. Defaults to +lock_version+.
|
153
140
|
def set_locking_column(value = nil, &block)
|
154
|
-
|
155
|
-
value
|
141
|
+
deprecated_property_setter :locking_column, value, block
|
156
142
|
end
|
157
143
|
|
158
144
|
# The version column used for optimistic locking. Defaults to +lock_version+.
|
159
145
|
def locking_column
|
160
|
-
reset_locking_column
|
146
|
+
reset_locking_column unless defined?(@locking_column)
|
147
|
+
@locking_column
|
148
|
+
end
|
149
|
+
|
150
|
+
def original_locking_column #:nodoc:
|
151
|
+
deprecated_original_property_getter :locking_column
|
161
152
|
end
|
162
153
|
|
163
154
|
# Quote the column name used for optimistic locking.
|
@@ -167,14 +158,26 @@ module ActiveRecord
|
|
167
158
|
|
168
159
|
# Reset the column used for optimistic locking back to the +lock_version+ default.
|
169
160
|
def reset_locking_column
|
170
|
-
|
161
|
+
self.locking_column = DEFAULT_LOCKING_COLUMN
|
171
162
|
end
|
172
163
|
|
173
164
|
# Make sure the lock version column gets updated when counters are
|
174
165
|
# updated.
|
175
|
-
def
|
166
|
+
def update_counters(id, counters)
|
176
167
|
counters = counters.merge(locking_column => 1) if locking_enabled?
|
177
|
-
|
168
|
+
super
|
169
|
+
end
|
170
|
+
|
171
|
+
# If the locking column has no default value set,
|
172
|
+
# start the lock version at zero. Note we can't use
|
173
|
+
# <tt>locking_enabled?</tt> at this point as
|
174
|
+
# <tt>@attributes</tt> may not have been initialized yet.
|
175
|
+
def initialize_attributes(attributes, options = {}) #:nodoc:
|
176
|
+
if attributes.key?(locking_column) && lock_optimistically
|
177
|
+
attributes[locking_column] ||= 0
|
178
|
+
end
|
179
|
+
|
180
|
+
attributes
|
178
181
|
end
|
179
182
|
end
|
180
183
|
end
|
@@ -3,30 +3,30 @@ module ActiveRecord
|
|
3
3
|
# Locking::Pessimistic provides support for row-level locking using
|
4
4
|
# SELECT ... FOR UPDATE and other lock types.
|
5
5
|
#
|
6
|
-
# Pass <tt>:lock => true</tt> to ActiveRecord::Base.find to obtain an exclusive
|
6
|
+
# Pass <tt>:lock => true</tt> to <tt>ActiveRecord::Base.find</tt> to obtain an exclusive
|
7
7
|
# lock on the selected rows:
|
8
8
|
# # select * from accounts where id=1 for update
|
9
9
|
# Account.find(1, :lock => true)
|
10
10
|
#
|
11
11
|
# Pass <tt>:lock => 'some locking clause'</tt> to give a database-specific locking clause
|
12
|
-
# of your own such as 'LOCK IN SHARE MODE' or 'FOR UPDATE NOWAIT'.
|
12
|
+
# of your own such as 'LOCK IN SHARE MODE' or 'FOR UPDATE NOWAIT'. Example:
|
13
13
|
#
|
14
|
-
# Example:
|
15
14
|
# Account.transaction do
|
16
15
|
# # select * from accounts where name = 'shugo' limit 1 for update
|
17
|
-
# shugo = Account.
|
18
|
-
# yuko = Account.
|
16
|
+
# shugo = Account.where("name = 'shugo'").lock(true).first
|
17
|
+
# yuko = Account.where("name = 'yuko'").lock(true).first
|
19
18
|
# shugo.balance -= 100
|
20
19
|
# shugo.save!
|
21
20
|
# yuko.balance += 100
|
22
21
|
# yuko.save!
|
23
22
|
# end
|
24
23
|
#
|
25
|
-
# You can also use ActiveRecord::Base#lock
|
24
|
+
# You can also use <tt>ActiveRecord::Base#lock!</tt> method to lock one record by id.
|
26
25
|
# This may be better if you don't need to lock every row. Example:
|
26
|
+
#
|
27
27
|
# Account.transaction do
|
28
28
|
# # select * from accounts where ...
|
29
|
-
# accounts = Account.
|
29
|
+
# accounts = Account.where(...).all
|
30
30
|
# account1 = accounts.detect { |account| ... }
|
31
31
|
# account2 = accounts.detect { |account| ... }
|
32
32
|
# # select * from accounts where id=? for update
|
@@ -38,18 +38,40 @@ module ActiveRecord
|
|
38
38
|
# account2.save!
|
39
39
|
# end
|
40
40
|
#
|
41
|
+
# You can start a transaction and acquire the lock in one go by calling
|
42
|
+
# <tt>with_lock</tt> with a block. The block is called from within
|
43
|
+
# a transaction, the object is already locked. Example:
|
44
|
+
#
|
45
|
+
# account = Account.first
|
46
|
+
# account.with_lock do
|
47
|
+
# # This block is called within a transaction,
|
48
|
+
# # account is already locked.
|
49
|
+
# account.balance -= 100
|
50
|
+
# account.save!
|
51
|
+
# end
|
52
|
+
#
|
41
53
|
# Database-specific information on row locking:
|
42
54
|
# MySQL: http://dev.mysql.com/doc/refman/5.1/en/innodb-locking-reads.html
|
43
|
-
# PostgreSQL: http://www.postgresql.org/docs/
|
55
|
+
# PostgreSQL: http://www.postgresql.org/docs/current/interactive/sql-select.html#SQL-FOR-UPDATE-SHARE
|
44
56
|
module Pessimistic
|
45
57
|
# Obtain a row lock on this record. Reloads the record to obtain the requested
|
46
58
|
# lock. Pass an SQL locking clause to append the end of the SELECT statement
|
47
|
-
# or pass true for "FOR UPDATE" (the default, an exclusive row lock).
|
59
|
+
# or pass true for "FOR UPDATE" (the default, an exclusive row lock). Returns
|
48
60
|
# the locked record.
|
49
61
|
def lock!(lock = true)
|
50
|
-
reload(:lock => lock)
|
62
|
+
reload(:lock => lock) if persisted?
|
51
63
|
self
|
52
64
|
end
|
65
|
+
|
66
|
+
# Wraps the passed block in a transaction, locking the object
|
67
|
+
# before yielding. You pass can the SQL locking clause
|
68
|
+
# as argument (see <tt>lock!</tt>).
|
69
|
+
def with_lock(lock = true)
|
70
|
+
transaction do
|
71
|
+
lock!(lock)
|
72
|
+
yield
|
73
|
+
end
|
74
|
+
end
|
53
75
|
end
|
54
76
|
end
|
55
77
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class LogSubscriber < ActiveSupport::LogSubscriber
|
3
|
+
def self.runtime=(value)
|
4
|
+
Thread.current["active_record_sql_runtime"] = value
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.runtime
|
8
|
+
Thread.current["active_record_sql_runtime"] ||= 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.reset_runtime
|
12
|
+
rt, self.runtime = runtime, 0
|
13
|
+
rt
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
super
|
18
|
+
@odd_or_even = false
|
19
|
+
end
|
20
|
+
|
21
|
+
def sql(event)
|
22
|
+
self.class.runtime += event.duration
|
23
|
+
return unless logger.debug?
|
24
|
+
|
25
|
+
payload = event.payload
|
26
|
+
|
27
|
+
return if 'SCHEMA' == payload[:name]
|
28
|
+
|
29
|
+
name = '%s (%.1fms)' % [payload[:name], event.duration]
|
30
|
+
sql = payload[:sql].squeeze(' ')
|
31
|
+
binds = nil
|
32
|
+
|
33
|
+
unless (payload[:binds] || []).empty?
|
34
|
+
binds = " " + payload[:binds].map { |col,v|
|
35
|
+
if col
|
36
|
+
[col.name, v]
|
37
|
+
else
|
38
|
+
[nil, v]
|
39
|
+
end
|
40
|
+
}.inspect
|
41
|
+
end
|
42
|
+
|
43
|
+
if odd?
|
44
|
+
name = color(name, CYAN, true)
|
45
|
+
sql = color(sql, nil, true)
|
46
|
+
else
|
47
|
+
name = color(name, MAGENTA, true)
|
48
|
+
end
|
49
|
+
|
50
|
+
debug " #{name} #{sql}#{binds}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def identity(event)
|
54
|
+
return unless logger.debug?
|
55
|
+
|
56
|
+
name = color(event.payload[:name], odd? ? CYAN : MAGENTA, true)
|
57
|
+
line = odd? ? color(event.payload[:line], nil, true) : event.payload[:line]
|
58
|
+
|
59
|
+
debug " #{name} #{line}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def odd?
|
63
|
+
@odd_or_even = !@odd_or_even
|
64
|
+
end
|
65
|
+
|
66
|
+
def logger
|
67
|
+
ActiveRecord::Base.logger
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
ActiveRecord::LogSubscriber.attach_to :active_record
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Migration
|
3
|
+
# <tt>ActiveRecord::Migration::CommandRecorder</tt> records commands done during
|
4
|
+
# a migration and knows how to reverse those commands. The CommandRecorder
|
5
|
+
# knows how to invert the following commands:
|
6
|
+
#
|
7
|
+
# * add_column
|
8
|
+
# * add_index
|
9
|
+
# * add_timestamps
|
10
|
+
# * create_table
|
11
|
+
# * remove_timestamps
|
12
|
+
# * rename_column
|
13
|
+
# * rename_index
|
14
|
+
# * rename_table
|
15
|
+
class CommandRecorder
|
16
|
+
attr_accessor :commands, :delegate
|
17
|
+
|
18
|
+
def initialize(delegate = nil)
|
19
|
+
@commands = []
|
20
|
+
@delegate = delegate
|
21
|
+
end
|
22
|
+
|
23
|
+
# record +command+. +command+ should be a method name and arguments.
|
24
|
+
# For example:
|
25
|
+
#
|
26
|
+
# recorder.record(:method_name, [:arg1, :arg2])
|
27
|
+
def record(*command)
|
28
|
+
@commands << command
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns a list that represents commands that are the inverse of the
|
32
|
+
# commands stored in +commands+. For example:
|
33
|
+
#
|
34
|
+
# recorder.record(:rename_table, [:old, :new])
|
35
|
+
# recorder.inverse # => [:rename_table, [:new, :old]]
|
36
|
+
#
|
37
|
+
# This method will raise an +IrreversibleMigration+ exception if it cannot
|
38
|
+
# invert the +commands+.
|
39
|
+
def inverse
|
40
|
+
@commands.reverse.map { |name, args|
|
41
|
+
method = :"invert_#{name}"
|
42
|
+
raise IrreversibleMigration unless respond_to?(method, true)
|
43
|
+
send(method, args)
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def respond_to?(*args) # :nodoc:
|
48
|
+
super || delegate.respond_to?(*args)
|
49
|
+
end
|
50
|
+
|
51
|
+
[:create_table, :change_table, :rename_table, :add_column, :remove_column, :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps, :change_column, :change_column_default].each do |method|
|
52
|
+
class_eval <<-EOV, __FILE__, __LINE__ + 1
|
53
|
+
def #{method}(*args) # def create_table(*args)
|
54
|
+
record(:"#{method}", args) # record(:create_table, args)
|
55
|
+
end # end
|
56
|
+
EOV
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def invert_create_table(args)
|
62
|
+
[:drop_table, [args.first]]
|
63
|
+
end
|
64
|
+
|
65
|
+
def invert_rename_table(args)
|
66
|
+
[:rename_table, args.reverse]
|
67
|
+
end
|
68
|
+
|
69
|
+
def invert_add_column(args)
|
70
|
+
[:remove_column, args.first(2)]
|
71
|
+
end
|
72
|
+
|
73
|
+
def invert_rename_index(args)
|
74
|
+
[:rename_index, [args.first] + args.last(2).reverse]
|
75
|
+
end
|
76
|
+
|
77
|
+
def invert_rename_column(args)
|
78
|
+
[:rename_column, [args.first] + args.last(2).reverse]
|
79
|
+
end
|
80
|
+
|
81
|
+
def invert_add_index(args)
|
82
|
+
table, columns, options = *args
|
83
|
+
index_name = options.try(:[], :name)
|
84
|
+
options_hash = index_name ? {:name => index_name} : {:column => columns}
|
85
|
+
[:remove_index, [table, options_hash]]
|
86
|
+
end
|
87
|
+
|
88
|
+
def invert_remove_timestamps(args)
|
89
|
+
[:add_timestamps, args]
|
90
|
+
end
|
91
|
+
|
92
|
+
def invert_add_timestamps(args)
|
93
|
+
[:remove_timestamps, args]
|
94
|
+
end
|
95
|
+
|
96
|
+
# Forwards any missing method call to the \target.
|
97
|
+
def method_missing(method, *args, &block)
|
98
|
+
@delegate.send(method, *args, &block)
|
99
|
+
rescue NoMethodError => e
|
100
|
+
raise e, e.message.sub(/ for #<.*$/, " via proxy for #{@delegate}")
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|