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
@@ -0,0 +1,194 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Sanitization
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def quote_value(value, column = nil) #:nodoc:
|
9
|
+
connection.quote(value,column)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Used to sanitize objects before they're used in an SQL SELECT statement. Delegates to <tt>connection.quote</tt>.
|
13
|
+
def sanitize(object) #:nodoc:
|
14
|
+
connection.quote(object)
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
# Accepts an array, hash, or string of SQL conditions and sanitizes
|
20
|
+
# them into a valid SQL fragment for a WHERE clause.
|
21
|
+
# ["name='%s' and group_id='%s'", "foo'bar", 4] returns "name='foo''bar' and group_id='4'"
|
22
|
+
# { :name => "foo'bar", :group_id => 4 } returns "name='foo''bar' and group_id='4'"
|
23
|
+
# "name='foo''bar' and group_id='4'" returns "name='foo''bar' and group_id='4'"
|
24
|
+
def sanitize_sql_for_conditions(condition, table_name = self.table_name)
|
25
|
+
return nil if condition.blank?
|
26
|
+
|
27
|
+
case condition
|
28
|
+
when Array; sanitize_sql_array(condition)
|
29
|
+
when Hash; sanitize_sql_hash_for_conditions(condition, table_name)
|
30
|
+
else condition
|
31
|
+
end
|
32
|
+
end
|
33
|
+
alias_method :sanitize_sql, :sanitize_sql_for_conditions
|
34
|
+
|
35
|
+
# Accepts an array, hash, or string of SQL conditions and sanitizes
|
36
|
+
# them into a valid SQL fragment for a SET clause.
|
37
|
+
# { :name => nil, :group_id => 4 } returns "name = NULL , group_id='4'"
|
38
|
+
def sanitize_sql_for_assignment(assignments)
|
39
|
+
case assignments
|
40
|
+
when Array; sanitize_sql_array(assignments)
|
41
|
+
when Hash; sanitize_sql_hash_for_assignment(assignments)
|
42
|
+
else assignments
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Accepts a hash of SQL conditions and replaces those attributes
|
47
|
+
# that correspond to a +composed_of+ relationship with their expanded
|
48
|
+
# aggregate attribute values.
|
49
|
+
# Given:
|
50
|
+
# class Person < ActiveRecord::Base
|
51
|
+
# composed_of :address, :class_name => "Address",
|
52
|
+
# :mapping => [%w(address_street street), %w(address_city city)]
|
53
|
+
# end
|
54
|
+
# Then:
|
55
|
+
# { :address => Address.new("813 abc st.", "chicago") }
|
56
|
+
# # => { :address_street => "813 abc st.", :address_city => "chicago" }
|
57
|
+
def expand_hash_conditions_for_aggregates(attrs)
|
58
|
+
expanded_attrs = {}
|
59
|
+
attrs.each do |attr, value|
|
60
|
+
unless (aggregation = reflect_on_aggregation(attr.to_sym)).nil?
|
61
|
+
mapping = aggregate_mapping(aggregation)
|
62
|
+
mapping.each do |field_attr, aggregate_attr|
|
63
|
+
if mapping.size == 1 && !value.respond_to?(aggregate_attr)
|
64
|
+
expanded_attrs[field_attr] = value
|
65
|
+
else
|
66
|
+
expanded_attrs[field_attr] = value.send(aggregate_attr)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
else
|
70
|
+
expanded_attrs[attr] = value
|
71
|
+
end
|
72
|
+
end
|
73
|
+
expanded_attrs
|
74
|
+
end
|
75
|
+
|
76
|
+
# Sanitizes a hash of attribute/value pairs into SQL conditions for a WHERE clause.
|
77
|
+
# { :name => "foo'bar", :group_id => 4 }
|
78
|
+
# # => "name='foo''bar' and group_id= 4"
|
79
|
+
# { :status => nil, :group_id => [1,2,3] }
|
80
|
+
# # => "status IS NULL and group_id IN (1,2,3)"
|
81
|
+
# { :age => 13..18 }
|
82
|
+
# # => "age BETWEEN 13 AND 18"
|
83
|
+
# { 'other_records.id' => 7 }
|
84
|
+
# # => "`other_records`.`id` = 7"
|
85
|
+
# { :other_records => { :id => 7 } }
|
86
|
+
# # => "`other_records`.`id` = 7"
|
87
|
+
# And for value objects on a composed_of relationship:
|
88
|
+
# { :address => Address.new("123 abc st.", "chicago") }
|
89
|
+
# # => "address_street='123 abc st.' and address_city='chicago'"
|
90
|
+
def sanitize_sql_hash_for_conditions(attrs, default_table_name = self.table_name)
|
91
|
+
attrs = expand_hash_conditions_for_aggregates(attrs)
|
92
|
+
|
93
|
+
table = Arel::Table.new(table_name).alias(default_table_name)
|
94
|
+
PredicateBuilder.build_from_hash(arel_engine, attrs, table).map { |b|
|
95
|
+
connection.visitor.accept b
|
96
|
+
}.join(' AND ')
|
97
|
+
end
|
98
|
+
alias_method :sanitize_sql_hash, :sanitize_sql_hash_for_conditions
|
99
|
+
|
100
|
+
# Sanitizes a hash of attribute/value pairs into SQL conditions for a SET clause.
|
101
|
+
# { :status => nil, :group_id => 1 }
|
102
|
+
# # => "status = NULL , group_id = 1"
|
103
|
+
def sanitize_sql_hash_for_assignment(attrs)
|
104
|
+
attrs.map do |attr, value|
|
105
|
+
"#{connection.quote_column_name(attr)} = #{quote_bound_value(value)}"
|
106
|
+
end.join(', ')
|
107
|
+
end
|
108
|
+
|
109
|
+
# Accepts an array of conditions. The array has each value
|
110
|
+
# sanitized and interpolated into the SQL statement.
|
111
|
+
# ["name='%s' and group_id='%s'", "foo'bar", 4] returns "name='foo''bar' and group_id='4'"
|
112
|
+
def sanitize_sql_array(ary)
|
113
|
+
statement, *values = ary
|
114
|
+
if values.first.is_a?(Hash) && statement =~ /:\w+/
|
115
|
+
replace_named_bind_variables(statement, values.first)
|
116
|
+
elsif statement.include?('?')
|
117
|
+
replace_bind_variables(statement, values)
|
118
|
+
elsif statement.blank?
|
119
|
+
statement
|
120
|
+
else
|
121
|
+
statement % values.collect { |value| connection.quote_string(value.to_s) }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
alias_method :sanitize_conditions, :sanitize_sql
|
126
|
+
|
127
|
+
def replace_bind_variables(statement, values) #:nodoc:
|
128
|
+
raise_if_bind_arity_mismatch(statement, statement.count('?'), values.size)
|
129
|
+
bound = values.dup
|
130
|
+
c = connection
|
131
|
+
statement.gsub('?') { quote_bound_value(bound.shift, c) }
|
132
|
+
end
|
133
|
+
|
134
|
+
def replace_named_bind_variables(statement, bind_vars) #:nodoc:
|
135
|
+
statement.gsub(/(:?):([a-zA-Z]\w*)/) do
|
136
|
+
if $1 == ':' # skip postgresql casts
|
137
|
+
$& # return the whole match
|
138
|
+
elsif bind_vars.include?(match = $2.to_sym)
|
139
|
+
quote_bound_value(bind_vars[match])
|
140
|
+
else
|
141
|
+
raise PreparedStatementInvalid, "missing value for :#{match} in #{statement}"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def expand_range_bind_variables(bind_vars) #:nodoc:
|
147
|
+
expanded = []
|
148
|
+
|
149
|
+
bind_vars.each do |var|
|
150
|
+
next if var.is_a?(Hash)
|
151
|
+
|
152
|
+
if var.is_a?(Range)
|
153
|
+
expanded << var.first
|
154
|
+
expanded << var.last
|
155
|
+
else
|
156
|
+
expanded << var
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
expanded
|
161
|
+
end
|
162
|
+
|
163
|
+
def quote_bound_value(value, c = connection) #:nodoc:
|
164
|
+
if value.respond_to?(:map) && !value.acts_like?(:string)
|
165
|
+
if value.respond_to?(:empty?) && value.empty?
|
166
|
+
c.quote(nil)
|
167
|
+
else
|
168
|
+
value.map { |v| c.quote(v) }.join(',')
|
169
|
+
end
|
170
|
+
else
|
171
|
+
c.quote(value)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def raise_if_bind_arity_mismatch(statement, expected, provided) #:nodoc:
|
176
|
+
unless expected == provided
|
177
|
+
raise PreparedStatementInvalid, "wrong number of bind variables (#{provided} for #{expected}) in: #{statement}"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# TODO: Deprecate this
|
183
|
+
def quoted_id #:nodoc:
|
184
|
+
quote_value(id, column_for_attribute(self.class.primary_key))
|
185
|
+
end
|
186
|
+
|
187
|
+
private
|
188
|
+
|
189
|
+
# Quote strings appropriately for SQL statements.
|
190
|
+
def quote_value(value, column = nil)
|
191
|
+
self.class.connection.quote(value, column)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
data/lib/active_record/schema.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
+
require 'active_support/core_ext/object/blank'
|
2
|
+
|
1
3
|
module ActiveRecord
|
4
|
+
# = Active Record Schema
|
5
|
+
#
|
2
6
|
# Allows programmers to programmatically define a schema in a portable
|
3
7
|
# DSL. This means you can define tables, indexes, etc. without using SQL
|
4
8
|
# directly, so your applications can more easily support multiple
|
@@ -26,10 +30,8 @@ module ActiveRecord
|
|
26
30
|
# ActiveRecord::Schema is only supported by database adapters that also
|
27
31
|
# support migrations, the two features being very similar.
|
28
32
|
class Schema < Migration
|
29
|
-
|
30
|
-
|
31
|
-
def self.migrations_path
|
32
|
-
ActiveRecord::Migrator.migrations_path
|
33
|
+
def migrations_paths
|
34
|
+
ActiveRecord::Migrator.migrations_paths
|
33
35
|
end
|
34
36
|
|
35
37
|
# Eval the given block. All methods available to the current connection
|
@@ -44,11 +46,12 @@ module ActiveRecord
|
|
44
46
|
# ...
|
45
47
|
# end
|
46
48
|
def self.define(info={}, &block)
|
47
|
-
|
49
|
+
schema = new
|
50
|
+
schema.instance_eval(&block)
|
48
51
|
|
49
52
|
unless info[:version].blank?
|
50
53
|
initialize_schema_migrations_table
|
51
|
-
assume_migrated_upto_version(info[:version],
|
54
|
+
assume_migrated_upto_version(info[:version], schema.migrations_paths)
|
52
55
|
end
|
53
56
|
end
|
54
57
|
end
|
@@ -1,18 +1,20 @@
|
|
1
1
|
require 'stringio'
|
2
|
-
require '
|
2
|
+
require 'active_support/core_ext/big_decimal'
|
3
3
|
|
4
4
|
module ActiveRecord
|
5
|
+
# = Active Record Schema Dumper
|
6
|
+
#
|
5
7
|
# This class is used to dump the database schema for some connection to some
|
6
8
|
# output format (i.e., ActiveRecord::Schema).
|
7
9
|
class SchemaDumper #:nodoc:
|
8
10
|
private_class_method :new
|
9
|
-
|
11
|
+
|
10
12
|
##
|
11
13
|
# :singleton-method:
|
12
|
-
# A list of tables which should not be dumped to the schema.
|
14
|
+
# A list of tables which should not be dumped to the schema.
|
13
15
|
# Acceptable values are strings as well as regexp.
|
14
16
|
# This setting is only used if ActiveRecord::Base.schema_format == :ruby
|
15
|
-
cattr_accessor :ignore_tables
|
17
|
+
cattr_accessor :ignore_tables
|
16
18
|
@@ignore_tables = []
|
17
19
|
|
18
20
|
def self.dump(connection=ActiveRecord::Base.connection, stream=STDOUT)
|
@@ -38,14 +40,19 @@ module ActiveRecord
|
|
38
40
|
def header(stream)
|
39
41
|
define_params = @version ? ":version => #{@version}" : ""
|
40
42
|
|
43
|
+
if stream.respond_to?(:external_encoding) && stream.external_encoding
|
44
|
+
stream.puts "# encoding: #{stream.external_encoding.name}"
|
45
|
+
end
|
46
|
+
|
41
47
|
stream.puts <<HEADER
|
42
|
-
# This file is auto-generated from the current state of the database. Instead
|
43
|
-
# please use the migrations feature of Active Record to
|
44
|
-
# then regenerate this schema definition.
|
48
|
+
# This file is auto-generated from the current state of the database. Instead
|
49
|
+
# of editing this file, please use the migrations feature of Active Record to
|
50
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
45
51
|
#
|
46
|
-
# Note that this schema.rb definition is the authoritative source for your
|
47
|
-
# to create the application database on another
|
48
|
-
#
|
52
|
+
# Note that this schema.rb definition is the authoritative source for your
|
53
|
+
# database schema. If you need to create the application database on another
|
54
|
+
# system, you should be using db:schema:load, not running all the migrations
|
55
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
49
56
|
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
50
57
|
#
|
51
58
|
# It's strongly recommended to check this file into your version control system.
|
@@ -63,12 +70,12 @@ HEADER
|
|
63
70
|
@connection.tables.sort.each do |tbl|
|
64
71
|
next if ['schema_migrations', ignore_tables].flatten.any? do |ignored|
|
65
72
|
case ignored
|
66
|
-
when String; tbl == ignored
|
67
|
-
when Regexp; tbl =~ ignored
|
73
|
+
when String; remove_prefix_and_suffix(tbl) == ignored
|
74
|
+
when Regexp; remove_prefix_and_suffix(tbl) =~ ignored
|
68
75
|
else
|
69
76
|
raise StandardError, 'ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.'
|
70
77
|
end
|
71
|
-
end
|
78
|
+
end
|
72
79
|
table(tbl, stream)
|
73
80
|
end
|
74
81
|
end
|
@@ -80,12 +87,12 @@ HEADER
|
|
80
87
|
|
81
88
|
# first dump primary key column
|
82
89
|
if @connection.respond_to?(:pk_and_sequence_for)
|
83
|
-
pk,
|
90
|
+
pk, _ = @connection.pk_and_sequence_for(table)
|
84
91
|
elsif @connection.respond_to?(:primary_key)
|
85
92
|
pk = @connection.primary_key(table)
|
86
93
|
end
|
87
|
-
|
88
|
-
tbl.print " create_table #{table.inspect}"
|
94
|
+
|
95
|
+
tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}"
|
89
96
|
if columns.detect { |c| c.name == pk }
|
90
97
|
if pk != 'id'
|
91
98
|
tbl.print %Q(, :primary_key => "#{pk}")
|
@@ -102,18 +109,25 @@ HEADER
|
|
102
109
|
next if column.name == pk
|
103
110
|
spec = {}
|
104
111
|
spec[:name] = column.name.inspect
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
spec[:
|
109
|
-
|
112
|
+
|
113
|
+
# AR has an optimization which handles zero-scale decimals as integers. This
|
114
|
+
# code ensures that the dumper still dumps the column as a decimal.
|
115
|
+
spec[:type] = if column.type == :integer && [/^numeric/, /^decimal/].any? { |e| e.match(column.sql_type) }
|
116
|
+
'decimal'
|
117
|
+
else
|
118
|
+
column.type.to_s
|
119
|
+
end
|
120
|
+
spec[:limit] = column.limit.inspect if column.limit != @types[column.type][:limit] && spec[:type] != 'decimal'
|
121
|
+
spec[:precision] = column.precision.inspect if column.precision
|
122
|
+
spec[:scale] = column.scale.inspect if column.scale
|
123
|
+
spec[:null] = 'false' unless column.null
|
110
124
|
spec[:default] = default_string(column.default) if column.has_default?
|
111
125
|
(spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.inspect} => ")}
|
112
126
|
spec
|
113
127
|
end.compact
|
114
128
|
|
115
129
|
# find all migration keys used in this table
|
116
|
-
keys = [:name, :limit, :precision, :scale, :default, :null] & column_specs.map
|
130
|
+
keys = [:name, :limit, :precision, :scale, :default, :null] & column_specs.map{ |k| k.keys }.flatten
|
117
131
|
|
118
132
|
# figure out the lengths for each column based on above keys
|
119
133
|
lengths = keys.map{ |key| column_specs.map{ |spec| spec[key] ? spec[key].length + 2 : 0 }.max }
|
@@ -138,7 +152,7 @@ HEADER
|
|
138
152
|
|
139
153
|
tbl.puts " end"
|
140
154
|
tbl.puts
|
141
|
-
|
155
|
+
|
142
156
|
indexes(table, tbl)
|
143
157
|
|
144
158
|
tbl.rewind
|
@@ -148,7 +162,7 @@ HEADER
|
|
148
162
|
stream.puts "# #{e.message}"
|
149
163
|
stream.puts
|
150
164
|
end
|
151
|
-
|
165
|
+
|
152
166
|
stream
|
153
167
|
end
|
154
168
|
|
@@ -162,24 +176,33 @@ HEADER
|
|
162
176
|
value.inspect
|
163
177
|
end
|
164
178
|
end
|
165
|
-
|
179
|
+
|
166
180
|
def indexes(table, stream)
|
167
181
|
if (indexes = @connection.indexes(table)).any?
|
168
182
|
add_index_statements = indexes.map do |index|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
183
|
+
statement_parts = [
|
184
|
+
('add_index ' + remove_prefix_and_suffix(index.table).inspect),
|
185
|
+
index.columns.inspect,
|
186
|
+
(':name => ' + index.name.inspect),
|
187
|
+
]
|
188
|
+
statement_parts << ':unique => true' if index.unique
|
173
189
|
|
174
|
-
index_lengths = index.lengths
|
175
|
-
|
190
|
+
index_lengths = (index.lengths || []).compact
|
191
|
+
statement_parts << (':length => ' + Hash[index.columns.zip(index.lengths)].inspect) unless index_lengths.empty?
|
176
192
|
|
177
|
-
|
193
|
+
index_orders = (index.orders || {})
|
194
|
+
statement_parts << (':order => ' + index.orders.inspect) unless index_orders.empty?
|
195
|
+
|
196
|
+
' ' + statement_parts.join(', ')
|
178
197
|
end
|
179
198
|
|
180
199
|
stream.puts add_index_statements.sort.join("\n")
|
181
200
|
stream.puts
|
182
201
|
end
|
183
202
|
end
|
203
|
+
|
204
|
+
def remove_prefix_and_suffix(table)
|
205
|
+
table.gsub(/^(#{ActiveRecord::Base.table_name_prefix})(.+)(#{ActiveRecord::Base.table_name_suffix})$/, "\\2")
|
206
|
+
end
|
184
207
|
end
|
185
208
|
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Scoping
|
5
|
+
module Default
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
# Stores the default scope for the class
|
10
|
+
class_attribute :default_scopes, :instance_writer => false
|
11
|
+
self.default_scopes = []
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
# Returns a scope for the model without the default_scope.
|
16
|
+
#
|
17
|
+
# class Post < ActiveRecord::Base
|
18
|
+
# def self.default_scope
|
19
|
+
# where :published => true
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# Post.all # Fires "SELECT * FROM posts WHERE published = true"
|
24
|
+
# Post.unscoped.all # Fires "SELECT * FROM posts"
|
25
|
+
#
|
26
|
+
# This method also accepts a block. All queries inside the block will
|
27
|
+
# not use the default_scope:
|
28
|
+
#
|
29
|
+
# Post.unscoped {
|
30
|
+
# Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
|
31
|
+
# }
|
32
|
+
#
|
33
|
+
# It is recommended to use the block form of unscoped because chaining
|
34
|
+
# unscoped with <tt>scope</tt> does not work. Assuming that
|
35
|
+
# <tt>published</tt> is a <tt>scope</tt>, the following two statements
|
36
|
+
# are equal: the default_scope is applied on both.
|
37
|
+
#
|
38
|
+
# Post.unscoped.published
|
39
|
+
# Post.published
|
40
|
+
def unscoped #:nodoc:
|
41
|
+
block_given? ? relation.scoping { yield } : relation
|
42
|
+
end
|
43
|
+
|
44
|
+
def before_remove_const #:nodoc:
|
45
|
+
self.current_scope = nil
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
# Use this macro in your model to set a default scope for all operations on
|
51
|
+
# the model.
|
52
|
+
#
|
53
|
+
# class Article < ActiveRecord::Base
|
54
|
+
# default_scope where(:published => true)
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# Article.all # => SELECT * FROM articles WHERE published = true
|
58
|
+
#
|
59
|
+
# The <tt>default_scope</tt> is also applied while creating/building a record. It is not
|
60
|
+
# applied while updating a record.
|
61
|
+
#
|
62
|
+
# Article.new.published # => true
|
63
|
+
# Article.create.published # => true
|
64
|
+
#
|
65
|
+
# You can also use <tt>default_scope</tt> with a block, in order to have it lazily evaluated:
|
66
|
+
#
|
67
|
+
# class Article < ActiveRecord::Base
|
68
|
+
# default_scope { where(:published_at => Time.now - 1.week) }
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# (You can also pass any object which responds to <tt>call</tt> to the <tt>default_scope</tt>
|
72
|
+
# macro, and it will be called when building the default scope.)
|
73
|
+
#
|
74
|
+
# If you use multiple <tt>default_scope</tt> declarations in your model then they will
|
75
|
+
# be merged together:
|
76
|
+
#
|
77
|
+
# class Article < ActiveRecord::Base
|
78
|
+
# default_scope where(:published => true)
|
79
|
+
# default_scope where(:rating => 'G')
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G'
|
83
|
+
#
|
84
|
+
# This is also the case with inheritance and module includes where the parent or module
|
85
|
+
# defines a <tt>default_scope</tt> and the child or including class defines a second one.
|
86
|
+
#
|
87
|
+
# If you need to do more complex things with a default scope, you can alternatively
|
88
|
+
# define it as a class method:
|
89
|
+
#
|
90
|
+
# class Article < ActiveRecord::Base
|
91
|
+
# def self.default_scope
|
92
|
+
# # Should return a scope, you can call 'super' here etc.
|
93
|
+
# end
|
94
|
+
# end
|
95
|
+
def default_scope(scope = {})
|
96
|
+
scope = Proc.new if block_given?
|
97
|
+
self.default_scopes = default_scopes + [scope]
|
98
|
+
end
|
99
|
+
|
100
|
+
def build_default_scope #:nodoc:
|
101
|
+
if method(:default_scope).owner != ActiveRecord::Scoping::Default::ClassMethods
|
102
|
+
evaluate_default_scope { default_scope }
|
103
|
+
elsif default_scopes.any?
|
104
|
+
evaluate_default_scope do
|
105
|
+
default_scopes.inject(relation) do |default_scope, scope|
|
106
|
+
if scope.is_a?(Hash)
|
107
|
+
default_scope.apply_finder_options(scope)
|
108
|
+
elsif !scope.is_a?(Relation) && scope.respond_to?(:call)
|
109
|
+
default_scope.merge(scope.call)
|
110
|
+
else
|
111
|
+
default_scope.merge(scope)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def ignore_default_scope? #:nodoc:
|
119
|
+
Thread.current["#{self}_ignore_default_scope"]
|
120
|
+
end
|
121
|
+
|
122
|
+
def ignore_default_scope=(ignore) #:nodoc:
|
123
|
+
Thread.current["#{self}_ignore_default_scope"] = ignore
|
124
|
+
end
|
125
|
+
|
126
|
+
# The ignore_default_scope flag is used to prevent an infinite recursion situation where
|
127
|
+
# a default scope references a scope which has a default scope which references a scope...
|
128
|
+
def evaluate_default_scope
|
129
|
+
return if ignore_default_scope?
|
130
|
+
|
131
|
+
begin
|
132
|
+
self.ignore_default_scope = true
|
133
|
+
yield
|
134
|
+
ensure
|
135
|
+
self.ignore_default_scope = false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|