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,5 +1,10 @@
|
|
1
|
+
require 'active_support/core_ext/array/wrap'
|
2
|
+
require 'active_support/core_ext/hash/conversions'
|
3
|
+
|
1
4
|
module ActiveRecord #:nodoc:
|
2
5
|
module Serialization
|
6
|
+
include ActiveModel::Serializers::Xml
|
7
|
+
|
3
8
|
# Builds an XML document to represent the model. Some configuration is
|
4
9
|
# available through +options+. However more complicated cases should
|
5
10
|
# override ActiveRecord::Base#to_xml.
|
@@ -69,6 +74,21 @@ module ActiveRecord #:nodoc:
|
|
69
74
|
# </account>
|
70
75
|
# </firm>
|
71
76
|
#
|
77
|
+
# Additionally, the record being serialized will be passed to a Proc's second
|
78
|
+
# parameter. This allows for ad hoc additions to the resultant document that
|
79
|
+
# incorporate the context of the record being serialized. And by leveraging the
|
80
|
+
# closure created by a Proc, to_xml can be used to add elements that normally fall
|
81
|
+
# outside of the scope of the model -- for example, generating and appending URLs
|
82
|
+
# associated with models.
|
83
|
+
#
|
84
|
+
# proc = Proc.new { |options, record| options[:builder].tag!('name-reverse', record.name.reverse) }
|
85
|
+
# firm.to_xml :procs => [ proc ]
|
86
|
+
#
|
87
|
+
# <firm>
|
88
|
+
# # ... normal attributes as shown above ...
|
89
|
+
# <name-reverse>slangis73</name-reverse>
|
90
|
+
# </firm>
|
91
|
+
#
|
72
92
|
# To include deeper levels of associations pass a hash like this:
|
73
93
|
#
|
74
94
|
# firm.to_xml :include => {:account => {}, :clients => {:include => :address}}
|
@@ -143,8 +163,9 @@ module ActiveRecord #:nodoc:
|
|
143
163
|
#
|
144
164
|
# class IHaveMyOwnXML < ActiveRecord::Base
|
145
165
|
# def to_xml(options = {})
|
166
|
+
# require 'builder'
|
146
167
|
# options[:indent] ||= 2
|
147
|
-
# xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
|
168
|
+
# xml = options[:builder] ||= ::Builder::XmlMarkup.new(:indent => options[:indent])
|
148
169
|
# xml.instruct! unless options[:skip_instruct]
|
149
170
|
# xml.level_one do
|
150
171
|
# xml.tag!(:second_level, 'content')
|
@@ -152,206 +173,31 @@ module ActiveRecord #:nodoc:
|
|
152
173
|
# end
|
153
174
|
# end
|
154
175
|
def to_xml(options = {}, &block)
|
155
|
-
|
156
|
-
block_given? ? serializer.to_s(&block) : serializer.to_s
|
157
|
-
end
|
158
|
-
|
159
|
-
def from_xml(xml)
|
160
|
-
self.attributes = Hash.from_xml(xml).values.first
|
161
|
-
self
|
176
|
+
XmlSerializer.new(self, options).serialize(&block)
|
162
177
|
end
|
163
178
|
end
|
164
179
|
|
165
|
-
class XmlSerializer <
|
166
|
-
def
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
180
|
+
class XmlSerializer < ActiveModel::Serializers::Xml::Serializer #:nodoc:
|
181
|
+
def initialize(*args)
|
182
|
+
super
|
183
|
+
options[:except] = Array.wrap(options[:except]) | Array.wrap(@serializable.class.inheritance_column)
|
184
|
+
end
|
185
|
+
|
186
|
+
class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc:
|
187
|
+
def compute_type
|
188
|
+
klass = @serializable.class
|
189
|
+
type = if klass.serialized_attributes.key?(name)
|
190
|
+
super
|
191
|
+
elsif klass.columns_hash.key?(name)
|
192
|
+
klass.columns_hash[name].type
|
193
|
+
else
|
194
|
+
NilClass
|
195
|
+
end
|
196
|
+
|
197
|
+
{ :text => :string,
|
198
|
+
:time => :datetime }[type] || type
|
177
199
|
end
|
178
|
-
|
179
|
-
|
180
|
-
def root
|
181
|
-
root = (options[:root] || @record.class.model_name.singular).to_s
|
182
|
-
reformat_name(root)
|
183
|
-
end
|
184
|
-
|
185
|
-
def dasherize?
|
186
|
-
!options.has_key?(:dasherize) || options[:dasherize]
|
187
|
-
end
|
188
|
-
|
189
|
-
def camelize?
|
190
|
-
options.has_key?(:camelize) && options[:camelize]
|
191
|
-
end
|
192
|
-
|
193
|
-
def reformat_name(name)
|
194
|
-
name = name.camelize if camelize?
|
195
|
-
dasherize? ? name.dasherize : name
|
196
|
-
end
|
197
|
-
|
198
|
-
def serializable_attributes
|
199
|
-
serializable_attribute_names.collect { |name| Attribute.new(name, @record) }
|
200
|
-
end
|
201
|
-
|
202
|
-
def serializable_method_attributes
|
203
|
-
Array(options[:methods]).inject([]) do |method_attributes, name|
|
204
|
-
method_attributes << MethodAttribute.new(name.to_s, @record) if @record.respond_to?(name.to_s)
|
205
|
-
method_attributes
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
def add_attributes
|
210
|
-
(serializable_attributes + serializable_method_attributes).each do |attribute|
|
211
|
-
add_tag(attribute)
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
def add_procs
|
216
|
-
if procs = options.delete(:procs)
|
217
|
-
[ *procs ].each do |proc|
|
218
|
-
proc.call(options)
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
def add_tag(attribute)
|
224
|
-
builder.tag!(
|
225
|
-
reformat_name(attribute.name),
|
226
|
-
attribute.value.to_s,
|
227
|
-
attribute.decorations(!options[:skip_types])
|
228
|
-
)
|
229
|
-
end
|
230
|
-
|
231
|
-
def add_associations(association, records, opts)
|
232
|
-
if records.is_a?(Enumerable)
|
233
|
-
tag = reformat_name(association.to_s)
|
234
|
-
type = options[:skip_types] ? {} : {:type => "array"}
|
235
|
-
|
236
|
-
if records.empty?
|
237
|
-
builder.tag!(tag, type)
|
238
|
-
else
|
239
|
-
builder.tag!(tag, type) do
|
240
|
-
association_name = association.to_s.singularize
|
241
|
-
records.each do |record|
|
242
|
-
if options[:skip_types]
|
243
|
-
record_type = {}
|
244
|
-
else
|
245
|
-
record_class = (record.class.to_s.underscore == association_name) ? nil : record.class.name
|
246
|
-
record_type = {:type => record_class}
|
247
|
-
end
|
248
|
-
|
249
|
-
record.to_xml opts.merge(:root => association_name).merge(record_type)
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
else
|
254
|
-
if record = @record.send(association)
|
255
|
-
record.to_xml(opts.merge(:root => association))
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
def serialize
|
261
|
-
args = [root]
|
262
|
-
if options[:namespace]
|
263
|
-
args << {:xmlns=>options[:namespace]}
|
264
|
-
end
|
265
|
-
|
266
|
-
if options[:type]
|
267
|
-
args << {:type=>options[:type]}
|
268
|
-
end
|
269
|
-
|
270
|
-
builder.tag!(*args) do
|
271
|
-
add_attributes
|
272
|
-
procs = options.delete(:procs)
|
273
|
-
add_includes { |association, records, opts| add_associations(association, records, opts) }
|
274
|
-
options[:procs] = procs
|
275
|
-
add_procs
|
276
|
-
yield builder if block_given?
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
class Attribute #:nodoc:
|
281
|
-
attr_reader :name, :value, :type
|
282
|
-
|
283
|
-
def initialize(name, record)
|
284
|
-
@name, @record = name, record
|
285
|
-
|
286
|
-
@type = compute_type
|
287
|
-
@value = compute_value
|
288
|
-
end
|
289
|
-
|
290
|
-
# There is a significant speed improvement if the value
|
291
|
-
# does not need to be escaped, as <tt>tag!</tt> escapes all values
|
292
|
-
# to ensure that valid XML is generated. For known binary
|
293
|
-
# values, it is at least an order of magnitude faster to
|
294
|
-
# Base64 encode binary values and directly put them in the
|
295
|
-
# output XML than to pass the original value or the Base64
|
296
|
-
# encoded value to the <tt>tag!</tt> method. It definitely makes
|
297
|
-
# no sense to Base64 encode the value and then give it to
|
298
|
-
# <tt>tag!</tt>, since that just adds additional overhead.
|
299
|
-
def needs_encoding?
|
300
|
-
![ :binary, :date, :datetime, :boolean, :float, :integer ].include?(type)
|
301
|
-
end
|
302
|
-
|
303
|
-
def decorations(include_types = true)
|
304
|
-
decorations = {}
|
305
|
-
|
306
|
-
if type == :binary
|
307
|
-
decorations[:encoding] = 'base64'
|
308
|
-
end
|
309
|
-
|
310
|
-
if include_types && type != :string
|
311
|
-
decorations[:type] = type
|
312
|
-
end
|
313
|
-
|
314
|
-
if value.nil?
|
315
|
-
decorations[:nil] = true
|
316
|
-
end
|
317
|
-
|
318
|
-
decorations
|
319
|
-
end
|
320
|
-
|
321
|
-
protected
|
322
|
-
def compute_type
|
323
|
-
type = if @record.class.serialized_attributes.has_key?(name)
|
324
|
-
:yaml
|
325
|
-
else
|
326
|
-
@record.class.columns_hash[name].try(:type)
|
327
|
-
end
|
328
|
-
|
329
|
-
case type
|
330
|
-
when :text
|
331
|
-
:string
|
332
|
-
when :time
|
333
|
-
:datetime
|
334
|
-
else
|
335
|
-
type
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
def compute_value
|
340
|
-
value = @record.send(name)
|
341
|
-
|
342
|
-
if formatter = Hash::XML_FORMATTING[type.to_s]
|
343
|
-
value ? formatter.call(value) : nil
|
344
|
-
else
|
345
|
-
value
|
346
|
-
end
|
347
|
-
end
|
348
|
-
end
|
349
|
-
|
350
|
-
class MethodAttribute < Attribute #:nodoc:
|
351
|
-
protected
|
352
|
-
def compute_type
|
353
|
-
Hash::XML_TYPE_NAMES[@record.send(name).class.name] || :string
|
354
|
-
end
|
200
|
+
protected :compute_type
|
355
201
|
end
|
356
202
|
end
|
357
203
|
end
|
@@ -1,24 +1,31 @@
|
|
1
|
+
require 'action_dispatch/middleware/session/abstract_store'
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
#
|
4
|
+
# = Active Record Session Store
|
5
|
+
#
|
6
|
+
# A session store backed by an Active Record class. A default class is
|
3
7
|
# provided, but any object duck-typing to an Active Record Session class
|
4
8
|
# with text +session_id+ and +data+ attributes is sufficient.
|
5
9
|
#
|
6
10
|
# The default assumes a +sessions+ tables with columns:
|
7
11
|
# +id+ (numeric primary key),
|
8
|
-
# +session_id+ (
|
12
|
+
# +session_id+ (string, :limit => 255), and
|
9
13
|
# +data+ (text or longtext; careful if your session data exceeds 65KB).
|
14
|
+
#
|
10
15
|
# The +session_id+ column should always be indexed for speedy lookups.
|
11
16
|
# Session data is marshaled to the +data+ column in Base64 format.
|
12
17
|
# If the data you write is larger than the column's size limit,
|
13
18
|
# ActionController::SessionOverflowError will be raised.
|
14
19
|
#
|
15
20
|
# You may configure the table name, primary key, and data column.
|
16
|
-
# For example, at the end of <tt>config/
|
21
|
+
# For example, at the end of <tt>config/application.rb</tt>:
|
22
|
+
#
|
17
23
|
# ActiveRecord::SessionStore::Session.table_name = 'legacy_session_table'
|
18
24
|
# ActiveRecord::SessionStore::Session.primary_key = 'session_id'
|
19
25
|
# ActiveRecord::SessionStore::Session.data_column_name = 'legacy_session_data'
|
26
|
+
#
|
20
27
|
# Note that setting the primary key to the +session_id+ frees you from
|
21
|
-
# having a separate +id+ column if you don't want it.
|
28
|
+
# having a separate +id+ column if you don't want it. However, you must
|
22
29
|
# set <tt>session.model.id = session.session_id</tt> by hand! A before filter
|
23
30
|
# on ApplicationController is a good place.
|
24
31
|
#
|
@@ -29,32 +36,63 @@ module ActiveRecord
|
|
29
36
|
# You may provide your own session class implementation, whether a
|
30
37
|
# feature-packed Active Record or a bare-metal high-performance SQL
|
31
38
|
# store, by setting
|
39
|
+
#
|
32
40
|
# ActiveRecord::SessionStore.session_class = MySessionClass
|
41
|
+
#
|
33
42
|
# You must implement these methods:
|
43
|
+
#
|
34
44
|
# self.find_by_session_id(session_id)
|
35
|
-
# initialize(hash_of_session_id_and_data)
|
45
|
+
# initialize(hash_of_session_id_and_data, options_hash = {})
|
36
46
|
# attr_reader :session_id
|
37
47
|
# attr_accessor :data
|
38
48
|
# save
|
39
49
|
# destroy
|
40
50
|
#
|
41
|
-
# The example SqlBypass class is a generic SQL session store.
|
51
|
+
# The example SqlBypass class is a generic SQL session store. You may
|
42
52
|
# use it as a basis for high-performance database-specific stores.
|
43
|
-
class SessionStore <
|
53
|
+
class SessionStore < ActionDispatch::Session::AbstractStore
|
54
|
+
module ClassMethods # :nodoc:
|
55
|
+
def marshal(data)
|
56
|
+
::Base64.encode64(Marshal.dump(data)) if data
|
57
|
+
end
|
58
|
+
|
59
|
+
def unmarshal(data)
|
60
|
+
Marshal.load(::Base64.decode64(data)) if data
|
61
|
+
end
|
62
|
+
|
63
|
+
def drop_table!
|
64
|
+
connection.schema_cache.clear_table_cache!(table_name)
|
65
|
+
connection.drop_table table_name
|
66
|
+
end
|
67
|
+
|
68
|
+
def create_table!
|
69
|
+
connection.schema_cache.clear_table_cache!(table_name)
|
70
|
+
connection.create_table(table_name) do |t|
|
71
|
+
t.string session_id_column, :limit => 255
|
72
|
+
t.text data_column_name
|
73
|
+
end
|
74
|
+
connection.add_index table_name, session_id_column, :unique => true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
44
78
|
# The default Active Record class.
|
45
79
|
class Session < ActiveRecord::Base
|
80
|
+
extend ClassMethods
|
81
|
+
|
46
82
|
##
|
47
83
|
# :singleton-method:
|
48
|
-
# Customizable data column name.
|
84
|
+
# Customizable data column name. Defaults to 'data'.
|
49
85
|
cattr_accessor :data_column_name
|
50
86
|
self.data_column_name = 'data'
|
51
87
|
|
88
|
+
attr_accessible :session_id, :data, :marshaled_data
|
89
|
+
|
52
90
|
before_save :marshal_data!
|
53
91
|
before_save :raise_on_session_data_overflow!
|
54
92
|
|
55
93
|
class << self
|
56
94
|
def data_column_size_limit
|
57
|
-
@data_column_size_limit ||= columns_hash[
|
95
|
+
@data_column_size_limit ||= columns_hash[data_column_name].limit
|
58
96
|
end
|
59
97
|
|
60
98
|
# Hook to set up sessid compatibility.
|
@@ -63,29 +101,11 @@ module ActiveRecord
|
|
63
101
|
find_by_session_id(session_id)
|
64
102
|
end
|
65
103
|
|
66
|
-
def marshal(data)
|
67
|
-
ActiveSupport::Base64.encode64(Marshal.dump(data)) if data
|
68
|
-
end
|
69
|
-
|
70
|
-
def unmarshal(data)
|
71
|
-
Marshal.load(ActiveSupport::Base64.decode64(data)) if data
|
72
|
-
end
|
73
|
-
|
74
|
-
def create_table!
|
75
|
-
connection.execute <<-end_sql
|
76
|
-
CREATE TABLE #{table_name} (
|
77
|
-
id INTEGER PRIMARY KEY,
|
78
|
-
#{connection.quote_column_name('session_id')} TEXT UNIQUE,
|
79
|
-
#{connection.quote_column_name(@@data_column_name)} TEXT(255)
|
80
|
-
)
|
81
|
-
end_sql
|
82
|
-
end
|
83
|
-
|
84
|
-
def drop_table!
|
85
|
-
connection.execute "DROP TABLE #{table_name}"
|
86
|
-
end
|
87
|
-
|
88
104
|
private
|
105
|
+
def session_id_column
|
106
|
+
'session_id'
|
107
|
+
end
|
108
|
+
|
89
109
|
# Compatibility with tables using sessid instead of session_id.
|
90
110
|
def setup_sessid_compatibility!
|
91
111
|
# Reset column info since it may be stale.
|
@@ -98,6 +118,8 @@ module ActiveRecord
|
|
98
118
|
define_method(:session_id) { sessid }
|
99
119
|
define_method(:session_id=) { |session_id| self.sessid = session_id }
|
100
120
|
else
|
121
|
+
class << self; remove_method :find_by_session_id; end
|
122
|
+
|
101
123
|
def self.find_by_session_id(session_id)
|
102
124
|
find :first, :conditions => {:session_id=>session_id}
|
103
125
|
end
|
@@ -105,6 +127,11 @@ module ActiveRecord
|
|
105
127
|
end
|
106
128
|
end
|
107
129
|
|
130
|
+
def initialize(attributes = nil, options = {})
|
131
|
+
@data = nil
|
132
|
+
super
|
133
|
+
end
|
134
|
+
|
108
135
|
# Lazy-unmarshal session state.
|
109
136
|
def data
|
110
137
|
@data ||= self.class.unmarshal(read_attribute(@@data_column_name)) || {}
|
@@ -114,50 +141,47 @@ module ActiveRecord
|
|
114
141
|
|
115
142
|
# Has the session been loaded yet?
|
116
143
|
def loaded?
|
117
|
-
|
144
|
+
@data
|
118
145
|
end
|
119
146
|
|
120
147
|
private
|
121
148
|
def marshal_data!
|
122
|
-
return false
|
123
|
-
write_attribute(@@data_column_name, self.class.marshal(
|
149
|
+
return false unless loaded?
|
150
|
+
write_attribute(@@data_column_name, self.class.marshal(data))
|
124
151
|
end
|
125
152
|
|
126
153
|
# Ensures that the data about to be stored in the database is not
|
127
154
|
# larger than the data storage column. Raises
|
128
155
|
# ActionController::SessionOverflowError.
|
129
156
|
def raise_on_session_data_overflow!
|
130
|
-
return false
|
157
|
+
return false unless loaded?
|
131
158
|
limit = self.class.data_column_size_limit
|
132
|
-
if
|
159
|
+
if limit and read_attribute(@@data_column_name).size > limit
|
133
160
|
raise ActionController::SessionOverflowError
|
134
161
|
end
|
135
162
|
end
|
136
163
|
end
|
137
164
|
|
138
165
|
# A barebones session store which duck-types with the default session
|
139
|
-
# store but bypasses Active Record and issues SQL directly.
|
166
|
+
# store but bypasses Active Record and issues SQL directly. This is
|
140
167
|
# an example session model class meant as a basis for your own classes.
|
141
168
|
#
|
142
169
|
# The database connection, table name, and session id and data columns
|
143
|
-
# are configurable class attributes.
|
144
|
-
# are implemented as class methods that you may override.
|
170
|
+
# are configurable class attributes. Marshaling and unmarshaling
|
171
|
+
# are implemented as class methods that you may override. By default,
|
145
172
|
# marshaling data is
|
146
173
|
#
|
147
|
-
#
|
174
|
+
# ::Base64.encode64(Marshal.dump(data))
|
148
175
|
#
|
149
176
|
# and unmarshaling data is
|
150
177
|
#
|
151
|
-
# Marshal.load(
|
178
|
+
# Marshal.load(::Base64.decode64(data))
|
152
179
|
#
|
153
180
|
# This marshaling behavior is intended to store the widest range of
|
154
|
-
# binary session data in a +text+ column.
|
181
|
+
# binary session data in a +text+ column. For higher performance,
|
155
182
|
# store in a +blob+ column instead and forgo the Base64 encoding.
|
156
183
|
class SqlBypass
|
157
|
-
|
158
|
-
# :singleton-method:
|
159
|
-
# Use the ActiveRecord::Base.connection by default.
|
160
|
-
cattr_accessor :connection
|
184
|
+
extend ClassMethods
|
161
185
|
|
162
186
|
##
|
163
187
|
# :singleton-method:
|
@@ -178,8 +202,20 @@ module ActiveRecord
|
|
178
202
|
@@data_column = 'data'
|
179
203
|
|
180
204
|
class << self
|
205
|
+
alias :data_column_name :data_column
|
206
|
+
|
207
|
+
# Use the ActiveRecord::Base.connection by default.
|
208
|
+
attr_writer :connection
|
209
|
+
|
210
|
+
# Use the ActiveRecord::Base.connection_pool by default.
|
211
|
+
attr_writer :connection_pool
|
212
|
+
|
181
213
|
def connection
|
182
|
-
|
214
|
+
@connection ||= ActiveRecord::Base.connection
|
215
|
+
end
|
216
|
+
|
217
|
+
def connection_pool
|
218
|
+
@connection_pool ||= ActiveRecord::Base.connection_pool
|
183
219
|
end
|
184
220
|
|
185
221
|
# Look up a session by id and unmarshal its data if found.
|
@@ -188,43 +224,23 @@ module ActiveRecord
|
|
188
224
|
new(:session_id => session_id, :marshaled_data => record['data'])
|
189
225
|
end
|
190
226
|
end
|
191
|
-
|
192
|
-
def marshal(data)
|
193
|
-
ActiveSupport::Base64.encode64(Marshal.dump(data)) if data
|
194
|
-
end
|
195
|
-
|
196
|
-
def unmarshal(data)
|
197
|
-
Marshal.load(ActiveSupport::Base64.decode64(data)) if data
|
198
|
-
end
|
199
|
-
|
200
|
-
def create_table!
|
201
|
-
@@connection.execute <<-end_sql
|
202
|
-
CREATE TABLE #{table_name} (
|
203
|
-
id INTEGER PRIMARY KEY,
|
204
|
-
#{@@connection.quote_column_name(session_id_column)} TEXT UNIQUE,
|
205
|
-
#{@@connection.quote_column_name(data_column)} TEXT
|
206
|
-
)
|
207
|
-
end_sql
|
208
|
-
end
|
209
|
-
|
210
|
-
def drop_table!
|
211
|
-
@@connection.execute "DROP TABLE #{table_name}"
|
212
|
-
end
|
213
227
|
end
|
228
|
+
|
229
|
+
delegate :connection, :connection=, :connection_pool, :connection_pool=, :to => self
|
230
|
+
|
231
|
+
attr_reader :session_id, :new_record
|
232
|
+
alias :new_record? :new_record
|
214
233
|
|
215
|
-
attr_reader :session_id
|
216
234
|
attr_writer :data
|
217
235
|
|
218
236
|
# Look for normal and marshaled data, self.find_by_session_id's way of
|
219
237
|
# telling us to postpone unmarshaling until the data is requested.
|
220
238
|
# We need to handle a normal data attribute in case of a new record.
|
221
239
|
def initialize(attributes)
|
222
|
-
@session_id
|
223
|
-
@
|
224
|
-
|
225
|
-
|
226
|
-
def new_record?
|
227
|
-
@new_record
|
240
|
+
@session_id = attributes[:session_id]
|
241
|
+
@data = attributes[:data]
|
242
|
+
@marshaled_data = attributes[:marshaled_data]
|
243
|
+
@new_record = @marshaled_data.nil?
|
228
244
|
end
|
229
245
|
|
230
246
|
# Lazy-unmarshal session state.
|
@@ -240,60 +256,67 @@ module ActiveRecord
|
|
240
256
|
end
|
241
257
|
|
242
258
|
def loaded?
|
243
|
-
|
259
|
+
@data
|
244
260
|
end
|
245
261
|
|
246
262
|
def save
|
247
|
-
return false
|
263
|
+
return false unless loaded?
|
248
264
|
marshaled_data = self.class.marshal(data)
|
265
|
+
connect = connection
|
249
266
|
|
250
267
|
if @new_record
|
251
268
|
@new_record = false
|
252
|
-
|
253
|
-
INSERT INTO #{
|
254
|
-
#{
|
255
|
-
#{
|
269
|
+
connect.update <<-end_sql, 'Create session'
|
270
|
+
INSERT INTO #{table_name} (
|
271
|
+
#{connect.quote_column_name(session_id_column)},
|
272
|
+
#{connect.quote_column_name(data_column)} )
|
256
273
|
VALUES (
|
257
|
-
#{
|
258
|
-
#{
|
274
|
+
#{connect.quote(session_id)},
|
275
|
+
#{connect.quote(marshaled_data)} )
|
259
276
|
end_sql
|
260
277
|
else
|
261
|
-
|
262
|
-
UPDATE #{
|
263
|
-
SET #{
|
264
|
-
WHERE #{
|
278
|
+
connect.update <<-end_sql, 'Update session'
|
279
|
+
UPDATE #{table_name}
|
280
|
+
SET #{connect.quote_column_name(data_column)}=#{connect.quote(marshaled_data)}
|
281
|
+
WHERE #{connect.quote_column_name(session_id_column)}=#{connect.quote(session_id)}
|
265
282
|
end_sql
|
266
283
|
end
|
267
284
|
end
|
268
285
|
|
269
286
|
def destroy
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
287
|
+
return if @new_record
|
288
|
+
|
289
|
+
connect = connection
|
290
|
+
connect.delete <<-end_sql, 'Destroy session'
|
291
|
+
DELETE FROM #{table_name}
|
292
|
+
WHERE #{connect.quote_column_name(session_id_column)}=#{connect.quote(session_id)}
|
293
|
+
end_sql
|
276
294
|
end
|
277
295
|
end
|
278
296
|
|
279
|
-
# The class used for session storage.
|
297
|
+
# The class used for session storage. Defaults to
|
280
298
|
# ActiveRecord::SessionStore::Session
|
281
299
|
cattr_accessor :session_class
|
282
300
|
self.session_class = Session
|
283
301
|
|
284
|
-
SESSION_RECORD_KEY = 'rack.session.record'
|
302
|
+
SESSION_RECORD_KEY = 'rack.session.record'
|
303
|
+
ENV_SESSION_OPTIONS_KEY = Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY
|
285
304
|
|
286
305
|
private
|
287
306
|
def get_session(env, sid)
|
288
307
|
Base.silence do
|
289
|
-
sid
|
290
|
-
|
308
|
+
unless sid and session = @@session_class.find_by_session_id(sid)
|
309
|
+
# If the sid was nil or if there is no pre-existing session under the sid,
|
310
|
+
# force the generation of a new sid and associate a new session associated with the new sid
|
311
|
+
sid = generate_sid
|
312
|
+
session = @@session_class.new(:session_id => sid, :data => {})
|
313
|
+
end
|
291
314
|
env[SESSION_RECORD_KEY] = session
|
292
315
|
[sid, session.data]
|
293
316
|
end
|
294
317
|
end
|
295
318
|
|
296
|
-
def set_session(env, sid, session_data)
|
319
|
+
def set_session(env, sid, session_data, options)
|
297
320
|
Base.silence do
|
298
321
|
record = get_session_model(env, sid)
|
299
322
|
record.data = session_data
|
@@ -307,17 +330,20 @@ module ActiveRecord
|
|
307
330
|
end
|
308
331
|
end
|
309
332
|
|
310
|
-
|
333
|
+
sid
|
311
334
|
end
|
312
|
-
|
313
|
-
def
|
335
|
+
|
336
|
+
def destroy_session(env, session_id, options)
|
314
337
|
if sid = current_session_id(env)
|
315
338
|
Base.silence do
|
316
339
|
get_session_model(env, sid).destroy
|
340
|
+
env[SESSION_RECORD_KEY] = nil
|
317
341
|
end
|
318
342
|
end
|
343
|
+
|
344
|
+
generate_sid unless options[:drop]
|
319
345
|
end
|
320
|
-
|
346
|
+
|
321
347
|
def get_session_model(env, sid)
|
322
348
|
if env[ENV_SESSION_OPTIONS_KEY][:id].nil?
|
323
349
|
env[SESSION_RECORD_KEY] = find_session(sid)
|