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,1684 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require "cases/helper"
|
3
|
-
require 'models/topic'
|
4
|
-
require 'models/reply'
|
5
|
-
require 'models/person'
|
6
|
-
require 'models/developer'
|
7
|
-
require 'models/warehouse_thing'
|
8
|
-
require 'models/guid'
|
9
|
-
require 'models/owner'
|
10
|
-
require 'models/pet'
|
11
|
-
require 'models/event'
|
12
|
-
require 'models/man'
|
13
|
-
require 'models/interest'
|
14
|
-
|
15
|
-
# The following methods in Topic are used in test_conditional_validation_*
|
16
|
-
class Topic
|
17
|
-
has_many :unique_replies, :dependent => :destroy, :foreign_key => "parent_id"
|
18
|
-
has_many :silly_unique_replies, :dependent => :destroy, :foreign_key => "parent_id"
|
19
|
-
|
20
|
-
def condition_is_true
|
21
|
-
true
|
22
|
-
end
|
23
|
-
|
24
|
-
def condition_is_true_but_its_not
|
25
|
-
false
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
class ProtectedPerson < ActiveRecord::Base
|
30
|
-
set_table_name 'people'
|
31
|
-
attr_accessor :addon
|
32
|
-
attr_protected :first_name
|
33
|
-
|
34
|
-
def special_error
|
35
|
-
this_method_does_not_exist!
|
36
|
-
rescue
|
37
|
-
errors.add(:special_error, "This method does not exist")
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
class UniqueReply < Reply
|
42
|
-
validates_uniqueness_of :content, :scope => 'parent_id'
|
43
|
-
end
|
44
|
-
|
45
|
-
class SillyUniqueReply < UniqueReply
|
46
|
-
end
|
47
|
-
|
48
|
-
class Wizard < ActiveRecord::Base
|
49
|
-
self.abstract_class = true
|
50
|
-
|
51
|
-
validates_uniqueness_of :name
|
52
|
-
end
|
53
|
-
|
54
|
-
class IneptWizard < Wizard
|
55
|
-
validates_uniqueness_of :city
|
56
|
-
end
|
57
|
-
|
58
|
-
class Conjurer < IneptWizard
|
59
|
-
end
|
60
|
-
|
61
|
-
class Thaumaturgist < IneptWizard
|
62
|
-
end
|
63
|
-
|
64
|
-
|
65
|
-
class ValidationsTest < ActiveRecord::TestCase
|
66
|
-
fixtures :topics, :developers, 'warehouse-things'
|
67
|
-
|
68
|
-
# Most of the tests mess with the validations of Topic, so lets repair it all the time.
|
69
|
-
# Other classes we mess with will be dealt with in the specific tests
|
70
|
-
repair_validations(Topic)
|
71
|
-
|
72
|
-
def test_single_field_validation
|
73
|
-
r = Reply.new
|
74
|
-
r.title = "There's no content!"
|
75
|
-
assert !r.valid?, "A reply without content shouldn't be saveable"
|
76
|
-
|
77
|
-
r.content = "Messa content!"
|
78
|
-
assert r.valid?, "A reply with content should be saveable"
|
79
|
-
end
|
80
|
-
|
81
|
-
def test_single_attr_validation_and_error_msg
|
82
|
-
r = Reply.new
|
83
|
-
r.title = "There's no content!"
|
84
|
-
assert !r.valid?
|
85
|
-
assert r.errors.invalid?("content"), "A reply without content should mark that attribute as invalid"
|
86
|
-
assert_equal "Empty", r.errors.on("content"), "A reply without content should contain an error"
|
87
|
-
assert_equal 1, r.errors.count
|
88
|
-
end
|
89
|
-
|
90
|
-
def test_double_attr_validation_and_error_msg
|
91
|
-
r = Reply.new
|
92
|
-
assert !r.valid?
|
93
|
-
|
94
|
-
assert r.errors.invalid?("title"), "A reply without title should mark that attribute as invalid"
|
95
|
-
assert_equal "Empty", r.errors.on("title"), "A reply without title should contain an error"
|
96
|
-
|
97
|
-
assert r.errors.invalid?("content"), "A reply without content should mark that attribute as invalid"
|
98
|
-
assert_equal "Empty", r.errors.on("content"), "A reply without content should contain an error"
|
99
|
-
|
100
|
-
assert_equal 2, r.errors.count
|
101
|
-
end
|
102
|
-
|
103
|
-
def test_error_on_create
|
104
|
-
r = Reply.new
|
105
|
-
r.title = "Wrong Create"
|
106
|
-
assert !r.valid?
|
107
|
-
assert r.errors.invalid?("title"), "A reply with a bad title should mark that attribute as invalid"
|
108
|
-
assert_equal "is Wrong Create", r.errors.on("title"), "A reply with a bad content should contain an error"
|
109
|
-
end
|
110
|
-
|
111
|
-
def test_error_on_update
|
112
|
-
r = Reply.new
|
113
|
-
r.title = "Bad"
|
114
|
-
r.content = "Good"
|
115
|
-
assert r.save, "First save should be successful"
|
116
|
-
|
117
|
-
r.title = "Wrong Update"
|
118
|
-
assert !r.save, "Second save should fail"
|
119
|
-
|
120
|
-
assert r.errors.invalid?("title"), "A reply with a bad title should mark that attribute as invalid"
|
121
|
-
assert_equal "is Wrong Update", r.errors.on("title"), "A reply with a bad content should contain an error"
|
122
|
-
end
|
123
|
-
|
124
|
-
def test_invalid_record_exception
|
125
|
-
assert_raise(ActiveRecord::RecordInvalid) { Reply.create! }
|
126
|
-
assert_raise(ActiveRecord::RecordInvalid) { Reply.new.save! }
|
127
|
-
|
128
|
-
begin
|
129
|
-
r = Reply.new
|
130
|
-
r.save!
|
131
|
-
flunk
|
132
|
-
rescue ActiveRecord::RecordInvalid => invalid
|
133
|
-
assert_equal r, invalid.record
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
def test_exception_on_create_bang_many
|
138
|
-
assert_raise(ActiveRecord::RecordInvalid) do
|
139
|
-
Reply.create!([ { "title" => "OK" }, { "title" => "Wrong Create" }])
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
def test_exception_on_create_bang_with_block
|
144
|
-
assert_raise(ActiveRecord::RecordInvalid) do
|
145
|
-
Reply.create!({ "title" => "OK" }) do |r|
|
146
|
-
r.content = nil
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def test_exception_on_create_bang_many_with_block
|
152
|
-
assert_raise(ActiveRecord::RecordInvalid) do
|
153
|
-
Reply.create!([{ "title" => "OK" }, { "title" => "Wrong Create" }]) do |r|
|
154
|
-
r.content = nil
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def test_scoped_create_without_attributes
|
160
|
-
Reply.with_scope(:create => {}) do
|
161
|
-
assert_raise(ActiveRecord::RecordInvalid) { Reply.create! }
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def test_create_with_exceptions_using_scope_for_protected_attributes
|
166
|
-
assert_nothing_raised do
|
167
|
-
ProtectedPerson.with_scope( :create => { :first_name => "Mary" } ) do
|
168
|
-
person = ProtectedPerson.create! :addon => "Addon"
|
169
|
-
assert_equal person.first_name, "Mary", "scope should ignore attr_protected"
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
def test_create_with_exceptions_using_scope_and_empty_attributes
|
175
|
-
assert_nothing_raised do
|
176
|
-
ProtectedPerson.with_scope( :create => { :first_name => "Mary" } ) do
|
177
|
-
person = ProtectedPerson.create!
|
178
|
-
assert_equal person.first_name, "Mary", "should be ok when no attributes are passed to create!"
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
def test_values_are_not_retrieved_unless_needed
|
184
|
-
assert_nothing_raised do
|
185
|
-
person = ProtectedPerson.new
|
186
|
-
person.special_error
|
187
|
-
assert_equal "This method does not exist", person.errors[:special_error]
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
def test_single_error_string_per_attr_iteration
|
192
|
-
r = Reply.new
|
193
|
-
r.save
|
194
|
-
|
195
|
-
errors = []
|
196
|
-
r.errors.each { |attr, msg| errors << [attr, msg] }
|
197
|
-
|
198
|
-
assert errors.include?(["title", "Empty"])
|
199
|
-
assert errors.include?(["content", "Empty"])
|
200
|
-
end
|
201
|
-
|
202
|
-
def test_single_error_object_per_attr_iteration
|
203
|
-
r = Reply.new
|
204
|
-
r.save
|
205
|
-
|
206
|
-
errors = []
|
207
|
-
r.errors.each_error { |attr, error| errors << [attr, error.attribute] }
|
208
|
-
|
209
|
-
assert errors.include?(["title", "title"])
|
210
|
-
assert errors.include?(["content", "content"])
|
211
|
-
end
|
212
|
-
|
213
|
-
def test_multiple_errors_per_attr_iteration_with_full_error_composition
|
214
|
-
r = Reply.new
|
215
|
-
r.title = "Wrong Create"
|
216
|
-
r.content = "Mismatch"
|
217
|
-
r.save
|
218
|
-
|
219
|
-
errors = []
|
220
|
-
r.errors.each_full { |error| errors << error }
|
221
|
-
|
222
|
-
assert_equal "Title is Wrong Create", errors[0]
|
223
|
-
assert_equal "Title is Content Mismatch", errors[1]
|
224
|
-
assert_equal 2, r.errors.count
|
225
|
-
end
|
226
|
-
|
227
|
-
def test_errors_on_base
|
228
|
-
r = Reply.new
|
229
|
-
r.content = "Mismatch"
|
230
|
-
r.save
|
231
|
-
r.errors.add_to_base "Reply is not dignifying"
|
232
|
-
|
233
|
-
errors = []
|
234
|
-
r.errors.each_full { |error| errors << error }
|
235
|
-
|
236
|
-
assert_equal "Reply is not dignifying", r.errors.on_base
|
237
|
-
|
238
|
-
assert errors.include?("Title Empty")
|
239
|
-
assert errors.include?("Reply is not dignifying")
|
240
|
-
assert_equal 2, r.errors.count
|
241
|
-
end
|
242
|
-
|
243
|
-
def test_create_without_validation
|
244
|
-
reply = Reply.new
|
245
|
-
assert !reply.save
|
246
|
-
assert reply.save(false)
|
247
|
-
end
|
248
|
-
|
249
|
-
def test_create_without_validation_bang
|
250
|
-
count = Reply.count
|
251
|
-
assert_nothing_raised { Reply.new.save_without_validation! }
|
252
|
-
assert count+1, Reply.count
|
253
|
-
end
|
254
|
-
|
255
|
-
def test_validates_each
|
256
|
-
hits = 0
|
257
|
-
Topic.validates_each(:title, :content, [:title, :content]) do |record, attr|
|
258
|
-
record.errors.add attr, 'gotcha'
|
259
|
-
hits += 1
|
260
|
-
end
|
261
|
-
t = Topic.new("title" => "valid", "content" => "whatever")
|
262
|
-
assert !t.save
|
263
|
-
assert_equal 4, hits
|
264
|
-
assert_equal %w(gotcha gotcha), t.errors.on(:title)
|
265
|
-
assert_equal %w(gotcha gotcha), t.errors.on(:content)
|
266
|
-
end
|
267
|
-
|
268
|
-
def test_no_title_confirmation
|
269
|
-
Topic.validates_confirmation_of(:title)
|
270
|
-
|
271
|
-
t = Topic.new(:author_name => "Plutarch")
|
272
|
-
assert t.valid?
|
273
|
-
|
274
|
-
t.title_confirmation = "Parallel Lives"
|
275
|
-
assert !t.valid?
|
276
|
-
|
277
|
-
t.title_confirmation = nil
|
278
|
-
t.title = "Parallel Lives"
|
279
|
-
assert t.valid?
|
280
|
-
|
281
|
-
t.title_confirmation = "Parallel Lives"
|
282
|
-
assert t.valid?
|
283
|
-
end
|
284
|
-
|
285
|
-
def test_title_confirmation
|
286
|
-
Topic.validates_confirmation_of(:title)
|
287
|
-
|
288
|
-
t = Topic.create("title" => "We should be confirmed","title_confirmation" => "")
|
289
|
-
assert !t.save
|
290
|
-
|
291
|
-
t.title_confirmation = "We should be confirmed"
|
292
|
-
assert t.save
|
293
|
-
end
|
294
|
-
|
295
|
-
def test_terms_of_service_agreement_no_acceptance
|
296
|
-
Topic.validates_acceptance_of(:terms_of_service, :on => :create)
|
297
|
-
|
298
|
-
t = Topic.create("title" => "We should not be confirmed")
|
299
|
-
assert t.save
|
300
|
-
end
|
301
|
-
|
302
|
-
def test_terms_of_service_agreement
|
303
|
-
Topic.validates_acceptance_of(:terms_of_service, :on => :create)
|
304
|
-
|
305
|
-
t = Topic.create("title" => "We should be confirmed","terms_of_service" => "")
|
306
|
-
assert !t.save
|
307
|
-
assert_equal "must be accepted", t.errors.on(:terms_of_service)
|
308
|
-
|
309
|
-
t.terms_of_service = "1"
|
310
|
-
assert t.save
|
311
|
-
end
|
312
|
-
|
313
|
-
|
314
|
-
def test_eula
|
315
|
-
Topic.validates_acceptance_of(:eula, :message => "must be abided", :on => :create)
|
316
|
-
|
317
|
-
t = Topic.create("title" => "We should be confirmed","eula" => "")
|
318
|
-
assert !t.save
|
319
|
-
assert_equal "must be abided", t.errors.on(:eula)
|
320
|
-
|
321
|
-
t.eula = "1"
|
322
|
-
assert t.save
|
323
|
-
end
|
324
|
-
|
325
|
-
def test_terms_of_service_agreement_with_accept_value
|
326
|
-
Topic.validates_acceptance_of(:terms_of_service, :on => :create, :accept => "I agree.")
|
327
|
-
|
328
|
-
t = Topic.create("title" => "We should be confirmed", "terms_of_service" => "")
|
329
|
-
assert !t.save
|
330
|
-
assert_equal "must be accepted", t.errors.on(:terms_of_service)
|
331
|
-
|
332
|
-
t.terms_of_service = "I agree."
|
333
|
-
assert t.save
|
334
|
-
end
|
335
|
-
|
336
|
-
def test_validates_acceptance_of_as_database_column
|
337
|
-
repair_validations(Reply) do
|
338
|
-
Reply.validates_acceptance_of(:author_name)
|
339
|
-
|
340
|
-
reply = Reply.create("author_name" => "Dan Brown")
|
341
|
-
assert_equal "Dan Brown", reply["author_name"]
|
342
|
-
end
|
343
|
-
end
|
344
|
-
|
345
|
-
def test_validates_acceptance_of_with_non_existant_table
|
346
|
-
Object.const_set :IncorporealModel, Class.new(ActiveRecord::Base)
|
347
|
-
|
348
|
-
assert_nothing_raised ActiveRecord::StatementInvalid do
|
349
|
-
IncorporealModel.validates_acceptance_of(:incorporeal_column)
|
350
|
-
end
|
351
|
-
end
|
352
|
-
|
353
|
-
def test_validate_presences
|
354
|
-
Topic.validates_presence_of(:title, :content)
|
355
|
-
|
356
|
-
t = Topic.create
|
357
|
-
assert !t.save
|
358
|
-
assert_equal "can't be blank", t.errors.on(:title)
|
359
|
-
assert_equal "can't be blank", t.errors.on(:content)
|
360
|
-
|
361
|
-
t.title = "something"
|
362
|
-
t.content = " "
|
363
|
-
|
364
|
-
assert !t.save
|
365
|
-
assert_equal "can't be blank", t.errors.on(:content)
|
366
|
-
|
367
|
-
t.content = "like stuff"
|
368
|
-
|
369
|
-
assert t.save
|
370
|
-
end
|
371
|
-
|
372
|
-
def test_validates_presence_of_belongs_to_association__parent_is_new_record
|
373
|
-
repair_validations(Interest) do
|
374
|
-
# Note that Interest and Man have the :inverse_of option set
|
375
|
-
Interest.validates_presence_of(:man)
|
376
|
-
man = Man.new(:name => 'John')
|
377
|
-
interest = man.interests.build(:topic => 'Airplanes')
|
378
|
-
assert interest.valid?, "Expected interest to be valid, but was not. Interest should have a man object associated"
|
379
|
-
end
|
380
|
-
end
|
381
|
-
|
382
|
-
def test_validates_presence_of_belongs_to_association__existing_parent
|
383
|
-
repair_validations(Interest) do
|
384
|
-
Interest.validates_presence_of(:man)
|
385
|
-
man = Man.create!(:name => 'John')
|
386
|
-
interest = man.interests.build(:topic => 'Airplanes')
|
387
|
-
assert interest.valid?, "Expected interest to be valid, but was not. Interest should have a man object associated"
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
|
-
def test_validate_uniqueness
|
392
|
-
Topic.validates_uniqueness_of(:title)
|
393
|
-
|
394
|
-
t = Topic.new("title" => "I'm uniqué!")
|
395
|
-
assert t.save, "Should save t as unique"
|
396
|
-
|
397
|
-
t.content = "Remaining unique"
|
398
|
-
assert t.save, "Should still save t as unique"
|
399
|
-
|
400
|
-
t2 = Topic.new("title" => "I'm uniqué!")
|
401
|
-
assert !t2.valid?, "Shouldn't be valid"
|
402
|
-
assert !t2.save, "Shouldn't save t2 as unique"
|
403
|
-
assert_equal "has already been taken", t2.errors.on(:title)
|
404
|
-
|
405
|
-
t2.title = "Now Im really also unique"
|
406
|
-
assert t2.save, "Should now save t2 as unique"
|
407
|
-
end
|
408
|
-
|
409
|
-
def test_validates_uniquness_with_newline_chars
|
410
|
-
Topic.validates_uniqueness_of(:title, :case_sensitive => false)
|
411
|
-
|
412
|
-
t = Topic.new("title" => "new\nline")
|
413
|
-
assert t.save, "Should save t as unique"
|
414
|
-
end
|
415
|
-
|
416
|
-
def test_validate_uniqueness_with_scope
|
417
|
-
repair_validations(Reply) do
|
418
|
-
Reply.validates_uniqueness_of(:content, :scope => "parent_id")
|
419
|
-
|
420
|
-
t = Topic.create("title" => "I'm unique!")
|
421
|
-
|
422
|
-
r1 = t.replies.create "title" => "r1", "content" => "hello world"
|
423
|
-
assert r1.valid?, "Saving r1"
|
424
|
-
|
425
|
-
r2 = t.replies.create "title" => "r2", "content" => "hello world"
|
426
|
-
assert !r2.valid?, "Saving r2 first time"
|
427
|
-
|
428
|
-
r2.content = "something else"
|
429
|
-
assert r2.save, "Saving r2 second time"
|
430
|
-
|
431
|
-
t2 = Topic.create("title" => "I'm unique too!")
|
432
|
-
r3 = t2.replies.create "title" => "r3", "content" => "hello world"
|
433
|
-
assert r3.valid?, "Saving r3"
|
434
|
-
end
|
435
|
-
end
|
436
|
-
|
437
|
-
def test_validate_uniqueness_with_reserved_word_as_scope
|
438
|
-
repair_validations(Reply) do
|
439
|
-
Topic.validates_uniqueness_of(:content, :scope => "group")
|
440
|
-
|
441
|
-
t1 = Topic.create "title" => "t1", "content" => "hello world2"
|
442
|
-
assert t1.valid?
|
443
|
-
|
444
|
-
t2 = Topic.create "title" => "t2", "content" => "hello world2"
|
445
|
-
assert !t2.valid?
|
446
|
-
end
|
447
|
-
end
|
448
|
-
|
449
|
-
def test_validate_uniqueness_scoped_to_defining_class
|
450
|
-
t = Topic.create("title" => "What, me worry?")
|
451
|
-
|
452
|
-
r1 = t.unique_replies.create "title" => "r1", "content" => "a barrel of fun"
|
453
|
-
assert r1.valid?, "Saving r1"
|
454
|
-
|
455
|
-
r2 = t.silly_unique_replies.create "title" => "r2", "content" => "a barrel of fun"
|
456
|
-
assert !r2.valid?, "Saving r2"
|
457
|
-
|
458
|
-
# Should succeed as validates_uniqueness_of only applies to
|
459
|
-
# UniqueReply and its subclasses
|
460
|
-
r3 = t.replies.create "title" => "r2", "content" => "a barrel of fun"
|
461
|
-
assert r3.valid?, "Saving r3"
|
462
|
-
end
|
463
|
-
|
464
|
-
def test_validate_uniqueness_with_scope_array
|
465
|
-
repair_validations(Reply) do
|
466
|
-
Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
|
467
|
-
|
468
|
-
t = Topic.create("title" => "The earth is actually flat!")
|
469
|
-
|
470
|
-
r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
|
471
|
-
assert r1.valid?, "Saving r1"
|
472
|
-
|
473
|
-
r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
|
474
|
-
assert !r2.valid?, "Saving r2. Double reply by same author."
|
475
|
-
|
476
|
-
r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
|
477
|
-
assert r2.save, "Saving r2 the second time."
|
478
|
-
|
479
|
-
r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
|
480
|
-
assert !r3.valid?, "Saving r3"
|
481
|
-
|
482
|
-
r3.author_name = "jj"
|
483
|
-
assert r3.save, "Saving r3 the second time."
|
484
|
-
|
485
|
-
r3.author_name = "jeremy"
|
486
|
-
assert !r3.save, "Saving r3 the third time."
|
487
|
-
end
|
488
|
-
end
|
489
|
-
|
490
|
-
def test_validate_case_insensitive_uniqueness
|
491
|
-
Topic.validates_uniqueness_of(:title, :parent_id, :case_sensitive => false, :allow_nil => true)
|
492
|
-
|
493
|
-
t = Topic.new("title" => "I'm unique!", :parent_id => 2)
|
494
|
-
assert t.save, "Should save t as unique"
|
495
|
-
|
496
|
-
t.content = "Remaining unique"
|
497
|
-
assert t.save, "Should still save t as unique"
|
498
|
-
|
499
|
-
t2 = Topic.new("title" => "I'm UNIQUE!", :parent_id => 1)
|
500
|
-
assert !t2.valid?, "Shouldn't be valid"
|
501
|
-
assert !t2.save, "Shouldn't save t2 as unique"
|
502
|
-
assert t2.errors.on(:title)
|
503
|
-
assert t2.errors.on(:parent_id)
|
504
|
-
assert_equal "has already been taken", t2.errors.on(:title)
|
505
|
-
|
506
|
-
t2.title = "I'm truly UNIQUE!"
|
507
|
-
assert !t2.valid?, "Shouldn't be valid"
|
508
|
-
assert !t2.save, "Shouldn't save t2 as unique"
|
509
|
-
assert_nil t2.errors.on(:title)
|
510
|
-
assert t2.errors.on(:parent_id)
|
511
|
-
|
512
|
-
t2.parent_id = 4
|
513
|
-
assert t2.save, "Should now save t2 as unique"
|
514
|
-
|
515
|
-
t2.parent_id = nil
|
516
|
-
t2.title = nil
|
517
|
-
assert t2.valid?, "should validate with nil"
|
518
|
-
assert t2.save, "should save with nil"
|
519
|
-
|
520
|
-
with_kcode('UTF8') do
|
521
|
-
t_utf8 = Topic.new("title" => "Я тоже уникальный!")
|
522
|
-
assert t_utf8.save, "Should save t_utf8 as unique"
|
523
|
-
|
524
|
-
# If database hasn't UTF-8 character set, this test fails
|
525
|
-
if Topic.find(t_utf8, :select => 'LOWER(title) AS title').title == "я тоже уникальный!"
|
526
|
-
t2_utf8 = Topic.new("title" => "я тоже УНИКАЛЬНЫЙ!")
|
527
|
-
assert !t2_utf8.valid?, "Shouldn't be valid"
|
528
|
-
assert !t2_utf8.save, "Shouldn't save t2_utf8 as unique"
|
529
|
-
end
|
530
|
-
end
|
531
|
-
end
|
532
|
-
|
533
|
-
def test_validate_case_sensitive_uniqueness
|
534
|
-
Topic.validates_uniqueness_of(:title, :case_sensitive => true, :allow_nil => true)
|
535
|
-
|
536
|
-
t = Topic.new("title" => "I'm unique!")
|
537
|
-
assert t.save, "Should save t as unique"
|
538
|
-
|
539
|
-
t.content = "Remaining unique"
|
540
|
-
assert t.save, "Should still save t as unique"
|
541
|
-
|
542
|
-
t2 = Topic.new("title" => "I'M UNIQUE!")
|
543
|
-
assert t2.valid?, "Should be valid"
|
544
|
-
assert t2.save, "Should save t2 as unique"
|
545
|
-
assert !t2.errors.on(:title)
|
546
|
-
assert !t2.errors.on(:parent_id)
|
547
|
-
assert_not_equal "has already been taken", t2.errors.on(:title)
|
548
|
-
|
549
|
-
t3 = Topic.new("title" => "I'M uNiQUe!")
|
550
|
-
assert t3.valid?, "Should be valid"
|
551
|
-
assert t3.save, "Should save t2 as unique"
|
552
|
-
assert !t3.errors.on(:title)
|
553
|
-
assert !t3.errors.on(:parent_id)
|
554
|
-
assert_not_equal "has already been taken", t3.errors.on(:title)
|
555
|
-
end
|
556
|
-
|
557
|
-
def test_validate_case_sensitive_uniqueness_with_attribute_passed_as_integer
|
558
|
-
Topic.validates_uniqueness_of(:title, :case_sensitve => true)
|
559
|
-
t = Topic.create!('title' => 101)
|
560
|
-
|
561
|
-
t2 = Topic.new('title' => 101)
|
562
|
-
assert !t2.valid?
|
563
|
-
assert t2.errors.on(:title)
|
564
|
-
end
|
565
|
-
|
566
|
-
def test_validate_uniqueness_with_non_standard_table_names
|
567
|
-
i1 = WarehouseThing.create(:value => 1000)
|
568
|
-
assert !i1.valid?, "i1 should not be valid"
|
569
|
-
assert i1.errors.on(:value), "Should not be empty"
|
570
|
-
end
|
571
|
-
|
572
|
-
def test_validates_uniqueness_inside_with_scope
|
573
|
-
Topic.validates_uniqueness_of(:title)
|
574
|
-
|
575
|
-
Topic.with_scope(:find => { :conditions => { :author_name => "David" } }) do
|
576
|
-
t1 = Topic.new("title" => "I'm unique!", "author_name" => "Mary")
|
577
|
-
assert t1.save
|
578
|
-
t2 = Topic.new("title" => "I'm unique!", "author_name" => "David")
|
579
|
-
assert !t2.valid?
|
580
|
-
end
|
581
|
-
end
|
582
|
-
|
583
|
-
def test_validate_uniqueness_with_columns_which_are_sql_keywords
|
584
|
-
repair_validations(Guid) do
|
585
|
-
Guid.validates_uniqueness_of :key
|
586
|
-
g = Guid.new
|
587
|
-
g.key = "foo"
|
588
|
-
assert_nothing_raised { !g.valid? }
|
589
|
-
end
|
590
|
-
end
|
591
|
-
|
592
|
-
def test_validate_uniqueness_with_limit
|
593
|
-
# Event.title is limited to 5 characters
|
594
|
-
e1 = Event.create(:title => "abcde")
|
595
|
-
assert e1.valid?, "Could not create an event with a unique, 5 character title"
|
596
|
-
e2 = Event.create(:title => "abcdefgh")
|
597
|
-
assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique"
|
598
|
-
end
|
599
|
-
|
600
|
-
def test_validate_uniqueness_with_limit_and_utf8
|
601
|
-
with_kcode('UTF8') do
|
602
|
-
# Event.title is limited to 5 characters
|
603
|
-
e1 = Event.create(:title => "一二三四五")
|
604
|
-
assert e1.valid?, "Could not create an event with a unique, 5 character title"
|
605
|
-
e2 = Event.create(:title => "一二三四五六七八")
|
606
|
-
assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique"
|
607
|
-
end
|
608
|
-
end
|
609
|
-
|
610
|
-
def test_validate_straight_inheritance_uniqueness
|
611
|
-
w1 = IneptWizard.create(:name => "Rincewind", :city => "Ankh-Morpork")
|
612
|
-
assert w1.valid?, "Saving w1"
|
613
|
-
|
614
|
-
# Should use validation from base class (which is abstract)
|
615
|
-
w2 = IneptWizard.new(:name => "Rincewind", :city => "Quirm")
|
616
|
-
assert !w2.valid?, "w2 shouldn't be valid"
|
617
|
-
assert w2.errors.on(:name), "Should have errors for name"
|
618
|
-
assert_equal "has already been taken", w2.errors.on(:name), "Should have uniqueness message for name"
|
619
|
-
|
620
|
-
w3 = Conjurer.new(:name => "Rincewind", :city => "Quirm")
|
621
|
-
assert !w3.valid?, "w3 shouldn't be valid"
|
622
|
-
assert w3.errors.on(:name), "Should have errors for name"
|
623
|
-
assert_equal "has already been taken", w3.errors.on(:name), "Should have uniqueness message for name"
|
624
|
-
|
625
|
-
w4 = Conjurer.create(:name => "The Amazing Bonko", :city => "Quirm")
|
626
|
-
assert w4.valid?, "Saving w4"
|
627
|
-
|
628
|
-
w5 = Thaumaturgist.new(:name => "The Amazing Bonko", :city => "Lancre")
|
629
|
-
assert !w5.valid?, "w5 shouldn't be valid"
|
630
|
-
assert w5.errors.on(:name), "Should have errors for name"
|
631
|
-
assert_equal "has already been taken", w5.errors.on(:name), "Should have uniqueness message for name"
|
632
|
-
|
633
|
-
w6 = Thaumaturgist.new(:name => "Mustrum Ridcully", :city => "Quirm")
|
634
|
-
assert !w6.valid?, "w6 shouldn't be valid"
|
635
|
-
assert w6.errors.on(:city), "Should have errors for city"
|
636
|
-
assert_equal "has already been taken", w6.errors.on(:city), "Should have uniqueness message for city"
|
637
|
-
end
|
638
|
-
|
639
|
-
def test_validate_format
|
640
|
-
Topic.validates_format_of(:title, :content, :with => /^Validation\smacros \w+!$/, :message => "is bad data")
|
641
|
-
|
642
|
-
t = Topic.create("title" => "i'm incorrect", "content" => "Validation macros rule!")
|
643
|
-
assert !t.valid?, "Shouldn't be valid"
|
644
|
-
assert !t.save, "Shouldn't save because it's invalid"
|
645
|
-
assert_equal "is bad data", t.errors.on(:title)
|
646
|
-
assert_nil t.errors.on(:content)
|
647
|
-
|
648
|
-
t.title = "Validation macros rule!"
|
649
|
-
|
650
|
-
assert t.save
|
651
|
-
assert_nil t.errors.on(:title)
|
652
|
-
|
653
|
-
assert_raise(ArgumentError) { Topic.validates_format_of(:title, :content) }
|
654
|
-
end
|
655
|
-
|
656
|
-
def test_validate_format_with_allow_blank
|
657
|
-
Topic.validates_format_of(:title, :with => /^Validation\smacros \w+!$/, :allow_blank=>true)
|
658
|
-
assert !Topic.create("title" => "Shouldn't be valid").valid?
|
659
|
-
assert Topic.create("title" => "").valid?
|
660
|
-
assert Topic.create("title" => nil).valid?
|
661
|
-
assert Topic.create("title" => "Validation macros rule!").valid?
|
662
|
-
end
|
663
|
-
|
664
|
-
# testing ticket #3142
|
665
|
-
def test_validate_format_numeric
|
666
|
-
Topic.validates_format_of(:title, :content, :with => /^[1-9][0-9]*$/, :message => "is bad data")
|
667
|
-
|
668
|
-
t = Topic.create("title" => "72x", "content" => "6789")
|
669
|
-
assert !t.valid?, "Shouldn't be valid"
|
670
|
-
assert !t.save, "Shouldn't save because it's invalid"
|
671
|
-
assert_equal "is bad data", t.errors.on(:title)
|
672
|
-
assert_nil t.errors.on(:content)
|
673
|
-
|
674
|
-
t.title = "-11"
|
675
|
-
assert !t.valid?, "Shouldn't be valid"
|
676
|
-
|
677
|
-
t.title = "03"
|
678
|
-
assert !t.valid?, "Shouldn't be valid"
|
679
|
-
|
680
|
-
t.title = "z44"
|
681
|
-
assert !t.valid?, "Shouldn't be valid"
|
682
|
-
|
683
|
-
t.title = "5v7"
|
684
|
-
assert !t.valid?, "Shouldn't be valid"
|
685
|
-
|
686
|
-
t.title = "1"
|
687
|
-
|
688
|
-
assert t.save
|
689
|
-
assert_nil t.errors.on(:title)
|
690
|
-
end
|
691
|
-
|
692
|
-
def test_validate_format_with_formatted_message
|
693
|
-
Topic.validates_format_of(:title, :with => /^Valid Title$/, :message => "can't be %{value}")
|
694
|
-
t = Topic.create(:title => 'Invalid title')
|
695
|
-
assert_equal "can't be Invalid title", t.errors.on(:title)
|
696
|
-
end
|
697
|
-
|
698
|
-
def test_validates_inclusion_of
|
699
|
-
Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ) )
|
700
|
-
|
701
|
-
assert !Topic.create("title" => "a!", "content" => "abc").valid?
|
702
|
-
assert !Topic.create("title" => "a b", "content" => "abc").valid?
|
703
|
-
assert !Topic.create("title" => nil, "content" => "def").valid?
|
704
|
-
|
705
|
-
t = Topic.create("title" => "a", "content" => "I know you are but what am I?")
|
706
|
-
assert t.valid?
|
707
|
-
t.title = "uhoh"
|
708
|
-
assert !t.valid?
|
709
|
-
assert t.errors.on(:title)
|
710
|
-
assert_equal "is not included in the list", t.errors["title"]
|
711
|
-
|
712
|
-
assert_raise(ArgumentError) { Topic.validates_inclusion_of( :title, :in => nil ) }
|
713
|
-
assert_raise(ArgumentError) { Topic.validates_inclusion_of( :title, :in => 0) }
|
714
|
-
|
715
|
-
assert_nothing_raised(ArgumentError) { Topic.validates_inclusion_of( :title, :in => "hi!" ) }
|
716
|
-
assert_nothing_raised(ArgumentError) { Topic.validates_inclusion_of( :title, :in => {} ) }
|
717
|
-
assert_nothing_raised(ArgumentError) { Topic.validates_inclusion_of( :title, :in => [] ) }
|
718
|
-
end
|
719
|
-
|
720
|
-
def test_validates_inclusion_of_with_allow_nil
|
721
|
-
Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ), :allow_nil=>true )
|
722
|
-
|
723
|
-
assert !Topic.create("title" => "a!", "content" => "abc").valid?
|
724
|
-
assert !Topic.create("title" => "", "content" => "abc").valid?
|
725
|
-
assert Topic.create("title" => nil, "content" => "abc").valid?
|
726
|
-
end
|
727
|
-
|
728
|
-
def test_numericality_with_getter_method
|
729
|
-
repair_validations(Developer) do
|
730
|
-
Developer.validates_numericality_of( :salary )
|
731
|
-
developer = Developer.new("name" => "michael", "salary" => nil)
|
732
|
-
developer.instance_eval("def salary; read_attribute('salary') ? read_attribute('salary') : 100000; end")
|
733
|
-
assert developer.valid?
|
734
|
-
end
|
735
|
-
end
|
736
|
-
|
737
|
-
def test_validates_length_of_with_allow_nil
|
738
|
-
Topic.validates_length_of( :title, :is => 5, :allow_nil=>true )
|
739
|
-
|
740
|
-
assert !Topic.create("title" => "ab").valid?
|
741
|
-
assert !Topic.create("title" => "").valid?
|
742
|
-
assert Topic.create("title" => nil).valid?
|
743
|
-
assert Topic.create("title" => "abcde").valid?
|
744
|
-
end
|
745
|
-
|
746
|
-
def test_validates_length_of_with_allow_blank
|
747
|
-
Topic.validates_length_of( :title, :is => 5, :allow_blank=>true )
|
748
|
-
|
749
|
-
assert !Topic.create("title" => "ab").valid?
|
750
|
-
assert Topic.create("title" => "").valid?
|
751
|
-
assert Topic.create("title" => nil).valid?
|
752
|
-
assert Topic.create("title" => "abcde").valid?
|
753
|
-
end
|
754
|
-
|
755
|
-
def test_validates_inclusion_of_with_formatted_message
|
756
|
-
Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ), :message => "option %{value} is not in the list" )
|
757
|
-
|
758
|
-
assert Topic.create("title" => "a", "content" => "abc").valid?
|
759
|
-
|
760
|
-
t = Topic.create("title" => "uhoh", "content" => "abc")
|
761
|
-
assert !t.valid?
|
762
|
-
assert t.errors.on(:title)
|
763
|
-
assert_equal "option uhoh is not in the list", t.errors["title"]
|
764
|
-
end
|
765
|
-
|
766
|
-
def test_numericality_with_allow_nil_and_getter_method
|
767
|
-
repair_validations(Developer) do
|
768
|
-
Developer.validates_numericality_of( :salary, :allow_nil => true)
|
769
|
-
developer = Developer.new("name" => "michael", "salary" => nil)
|
770
|
-
developer.instance_eval("def salary; read_attribute('salary') ? read_attribute('salary') : 100000; end")
|
771
|
-
assert developer.valid?
|
772
|
-
end
|
773
|
-
end
|
774
|
-
|
775
|
-
def test_validates_exclusion_of
|
776
|
-
Topic.validates_exclusion_of( :title, :in => %w( abe monkey ) )
|
777
|
-
|
778
|
-
assert Topic.create("title" => "something", "content" => "abc").valid?
|
779
|
-
assert !Topic.create("title" => "monkey", "content" => "abc").valid?
|
780
|
-
end
|
781
|
-
|
782
|
-
def test_validates_exclusion_of_with_formatted_message
|
783
|
-
Topic.validates_exclusion_of( :title, :in => %w( abe monkey ), :message => "option %{value} is restricted" )
|
784
|
-
|
785
|
-
assert Topic.create("title" => "something", "content" => "abc")
|
786
|
-
|
787
|
-
t = Topic.create("title" => "monkey")
|
788
|
-
assert !t.valid?
|
789
|
-
assert t.errors.on(:title)
|
790
|
-
assert_equal "option monkey is restricted", t.errors["title"]
|
791
|
-
end
|
792
|
-
|
793
|
-
def test_validates_length_of_using_minimum
|
794
|
-
Topic.validates_length_of :title, :minimum => 5
|
795
|
-
|
796
|
-
t = Topic.create("title" => "valid", "content" => "whatever")
|
797
|
-
assert t.valid?
|
798
|
-
|
799
|
-
t.title = "not"
|
800
|
-
assert !t.valid?
|
801
|
-
assert t.errors.on(:title)
|
802
|
-
assert_equal "is too short (minimum is 5 characters)", t.errors["title"]
|
803
|
-
|
804
|
-
t.title = ""
|
805
|
-
assert !t.valid?
|
806
|
-
assert t.errors.on(:title)
|
807
|
-
assert_equal "is too short (minimum is 5 characters)", t.errors["title"]
|
808
|
-
|
809
|
-
t.title = nil
|
810
|
-
assert !t.valid?
|
811
|
-
assert t.errors.on(:title)
|
812
|
-
assert_equal "is too short (minimum is 5 characters)", t.errors["title"]
|
813
|
-
end
|
814
|
-
|
815
|
-
def test_optionally_validates_length_of_using_minimum
|
816
|
-
Topic.validates_length_of :title, :minimum => 5, :allow_nil => true
|
817
|
-
|
818
|
-
t = Topic.create("title" => "valid", "content" => "whatever")
|
819
|
-
assert t.valid?
|
820
|
-
|
821
|
-
t.title = nil
|
822
|
-
assert t.valid?
|
823
|
-
end
|
824
|
-
|
825
|
-
def test_validates_length_of_using_maximum
|
826
|
-
Topic.validates_length_of :title, :maximum => 5
|
827
|
-
|
828
|
-
t = Topic.create("title" => "valid", "content" => "whatever")
|
829
|
-
assert t.valid?
|
830
|
-
|
831
|
-
t.title = "notvalid"
|
832
|
-
assert !t.valid?
|
833
|
-
assert t.errors.on(:title)
|
834
|
-
assert_equal "is too long (maximum is 5 characters)", t.errors["title"]
|
835
|
-
|
836
|
-
t.title = ""
|
837
|
-
assert t.valid?
|
838
|
-
|
839
|
-
t.title = nil
|
840
|
-
assert !t.valid?
|
841
|
-
end
|
842
|
-
|
843
|
-
def test_optionally_validates_length_of_using_maximum
|
844
|
-
Topic.validates_length_of :title, :maximum => 5, :allow_nil => true
|
845
|
-
|
846
|
-
t = Topic.create("title" => "valid", "content" => "whatever")
|
847
|
-
assert t.valid?
|
848
|
-
|
849
|
-
t.title = nil
|
850
|
-
assert t.valid?
|
851
|
-
end
|
852
|
-
|
853
|
-
def test_validates_length_of_using_within
|
854
|
-
Topic.validates_length_of(:title, :content, :within => 3..5)
|
855
|
-
|
856
|
-
t = Topic.new("title" => "a!", "content" => "I'm ooooooooh so very long")
|
857
|
-
assert !t.valid?
|
858
|
-
assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title)
|
859
|
-
assert_equal "is too long (maximum is 5 characters)", t.errors.on(:content)
|
860
|
-
|
861
|
-
t.title = nil
|
862
|
-
t.content = nil
|
863
|
-
assert !t.valid?
|
864
|
-
assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title)
|
865
|
-
assert_equal "is too short (minimum is 3 characters)", t.errors.on(:content)
|
866
|
-
|
867
|
-
t.title = "abe"
|
868
|
-
t.content = "mad"
|
869
|
-
assert t.valid?
|
870
|
-
end
|
871
|
-
|
872
|
-
def test_optionally_validates_length_of_using_within
|
873
|
-
Topic.validates_length_of :title, :content, :within => 3..5, :allow_nil => true
|
874
|
-
|
875
|
-
t = Topic.create('title' => 'abc', 'content' => 'abcd')
|
876
|
-
assert t.valid?
|
877
|
-
|
878
|
-
t.title = nil
|
879
|
-
assert t.valid?
|
880
|
-
end
|
881
|
-
|
882
|
-
def test_optionally_validates_length_of_using_within_on_create
|
883
|
-
Topic.validates_length_of :title, :content, :within => 5..10, :on => :create, :too_long => "my string is too long: %{count}"
|
884
|
-
|
885
|
-
t = Topic.create("title" => "thisisnotvalid", "content" => "whatever")
|
886
|
-
assert !t.save
|
887
|
-
assert t.errors.on(:title)
|
888
|
-
assert_equal "my string is too long: 10", t.errors[:title]
|
889
|
-
|
890
|
-
t.title = "butthisis"
|
891
|
-
assert t.save
|
892
|
-
|
893
|
-
t.title = "few"
|
894
|
-
assert t.save
|
895
|
-
|
896
|
-
t.content = "andthisislong"
|
897
|
-
assert t.save
|
898
|
-
|
899
|
-
t.content = t.title = "iamfine"
|
900
|
-
assert t.save
|
901
|
-
end
|
902
|
-
|
903
|
-
def test_optionally_validates_length_of_using_within_on_update
|
904
|
-
Topic.validates_length_of :title, :content, :within => 5..10, :on => :update, :too_short => "my string is too short: %{count}"
|
905
|
-
|
906
|
-
t = Topic.create("title" => "vali", "content" => "whatever")
|
907
|
-
assert !t.save
|
908
|
-
assert t.errors.on(:title)
|
909
|
-
|
910
|
-
t.title = "not"
|
911
|
-
assert !t.save
|
912
|
-
assert t.errors.on(:title)
|
913
|
-
assert_equal "my string is too short: 5", t.errors[:title]
|
914
|
-
|
915
|
-
t.title = "valid"
|
916
|
-
t.content = "andthisistoolong"
|
917
|
-
assert !t.save
|
918
|
-
assert t.errors.on(:content)
|
919
|
-
|
920
|
-
t.content = "iamfine"
|
921
|
-
assert t.save
|
922
|
-
end
|
923
|
-
|
924
|
-
def test_validates_length_of_using_is
|
925
|
-
Topic.validates_length_of :title, :is => 5
|
926
|
-
|
927
|
-
t = Topic.create("title" => "valid", "content" => "whatever")
|
928
|
-
assert t.valid?
|
929
|
-
|
930
|
-
t.title = "notvalid"
|
931
|
-
assert !t.valid?
|
932
|
-
assert t.errors.on(:title)
|
933
|
-
assert_equal "is the wrong length (should be 5 characters)", t.errors["title"]
|
934
|
-
|
935
|
-
t.title = ""
|
936
|
-
assert !t.valid?
|
937
|
-
|
938
|
-
t.title = nil
|
939
|
-
assert !t.valid?
|
940
|
-
end
|
941
|
-
|
942
|
-
def test_optionally_validates_length_of_using_is
|
943
|
-
Topic.validates_length_of :title, :is => 5, :allow_nil => true
|
944
|
-
|
945
|
-
t = Topic.create("title" => "valid", "content" => "whatever")
|
946
|
-
assert t.valid?
|
947
|
-
|
948
|
-
t.title = nil
|
949
|
-
assert t.valid?
|
950
|
-
end
|
951
|
-
|
952
|
-
def test_validates_length_of_using_bignum
|
953
|
-
bigmin = 2 ** 30
|
954
|
-
bigmax = 2 ** 32
|
955
|
-
bigrange = bigmin...bigmax
|
956
|
-
assert_nothing_raised do
|
957
|
-
Topic.validates_length_of :title, :is => bigmin + 5
|
958
|
-
Topic.validates_length_of :title, :within => bigrange
|
959
|
-
Topic.validates_length_of :title, :in => bigrange
|
960
|
-
Topic.validates_length_of :title, :minimum => bigmin
|
961
|
-
Topic.validates_length_of :title, :maximum => bigmax
|
962
|
-
end
|
963
|
-
end
|
964
|
-
|
965
|
-
def test_validates_length_with_globally_modified_error_message
|
966
|
-
defaults = ActiveSupport::Deprecation.silence { ActiveRecord::Errors.default_error_messages }
|
967
|
-
original_message = defaults[:too_short]
|
968
|
-
defaults[:too_short] = 'tu est trops petit hombre %{count}'
|
969
|
-
|
970
|
-
Topic.validates_length_of :title, :minimum => 10
|
971
|
-
t = Topic.create(:title => 'too short')
|
972
|
-
assert !t.valid?
|
973
|
-
|
974
|
-
assert_equal 'tu est trops petit hombre 10', t.errors['title']
|
975
|
-
|
976
|
-
ensure
|
977
|
-
defaults[:too_short] = original_message
|
978
|
-
end
|
979
|
-
|
980
|
-
def test_validates_size_of_association
|
981
|
-
repair_validations(Owner) do
|
982
|
-
assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
|
983
|
-
o = Owner.new('name' => 'nopets')
|
984
|
-
assert !o.save
|
985
|
-
assert o.errors.on(:pets)
|
986
|
-
pet = o.pets.build('name' => 'apet')
|
987
|
-
assert o.valid?
|
988
|
-
end
|
989
|
-
end
|
990
|
-
|
991
|
-
def test_validates_size_of_association_using_within
|
992
|
-
repair_validations(Owner) do
|
993
|
-
assert_nothing_raised { Owner.validates_size_of :pets, :within => 1..2 }
|
994
|
-
o = Owner.new('name' => 'nopets')
|
995
|
-
assert !o.save
|
996
|
-
assert o.errors.on(:pets)
|
997
|
-
|
998
|
-
pet = o.pets.build('name' => 'apet')
|
999
|
-
assert o.valid?
|
1000
|
-
|
1001
|
-
2.times { o.pets.build('name' => 'apet') }
|
1002
|
-
assert !o.save
|
1003
|
-
assert o.errors.on(:pets)
|
1004
|
-
end
|
1005
|
-
end
|
1006
|
-
|
1007
|
-
def test_validates_length_of_nasty_params
|
1008
|
-
assert_raise(ArgumentError) { Topic.validates_length_of(:title, :minimum=>6, :maximum=>9) }
|
1009
|
-
assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>6, :maximum=>9) }
|
1010
|
-
assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>6, :minimum=>9) }
|
1011
|
-
assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>6, :is=>9) }
|
1012
|
-
assert_raise(ArgumentError) { Topic.validates_length_of(:title, :minimum=>"a") }
|
1013
|
-
assert_raise(ArgumentError) { Topic.validates_length_of(:title, :maximum=>"a") }
|
1014
|
-
assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>"a") }
|
1015
|
-
assert_raise(ArgumentError) { Topic.validates_length_of(:title, :is=>"a") }
|
1016
|
-
end
|
1017
|
-
|
1018
|
-
def test_validates_length_of_custom_errors_for_minimum_with_message
|
1019
|
-
Topic.validates_length_of( :title, :minimum=>5, :message=>"boo %{count}" )
|
1020
|
-
t = Topic.create("title" => "uhoh", "content" => "whatever")
|
1021
|
-
assert !t.valid?
|
1022
|
-
assert t.errors.on(:title)
|
1023
|
-
assert_equal "boo 5", t.errors["title"]
|
1024
|
-
end
|
1025
|
-
|
1026
|
-
def test_validates_length_of_custom_errors_for_minimum_with_too_short
|
1027
|
-
Topic.validates_length_of( :title, :minimum=>5, :too_short=>"hoo %{count}" )
|
1028
|
-
t = Topic.create("title" => "uhoh", "content" => "whatever")
|
1029
|
-
assert !t.valid?
|
1030
|
-
assert t.errors.on(:title)
|
1031
|
-
assert_equal "hoo 5", t.errors["title"]
|
1032
|
-
end
|
1033
|
-
|
1034
|
-
def test_validates_length_of_custom_errors_for_maximum_with_message
|
1035
|
-
Topic.validates_length_of( :title, :maximum=>5, :message=>"boo %{count}" )
|
1036
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1037
|
-
assert !t.valid?
|
1038
|
-
assert t.errors.on(:title)
|
1039
|
-
assert_equal "boo 5", t.errors["title"]
|
1040
|
-
end
|
1041
|
-
|
1042
|
-
def test_validates_length_of_custom_errors_for_in
|
1043
|
-
Topic.validates_length_of(:title, :in => 10..20, :message => "hoo %{count}")
|
1044
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1045
|
-
assert !t.valid?
|
1046
|
-
assert t.errors.on(:title)
|
1047
|
-
assert_equal "hoo 10", t.errors["title"]
|
1048
|
-
|
1049
|
-
t = Topic.create("title" => "uhohuhohuhohuhohuhohuhohuhohuhoh", "content" => "whatever")
|
1050
|
-
assert !t.valid?
|
1051
|
-
assert t.errors.on(:title)
|
1052
|
-
assert_equal "hoo 20", t.errors["title"]
|
1053
|
-
end
|
1054
|
-
|
1055
|
-
def test_validates_length_of_custom_errors_for_maximum_with_too_long
|
1056
|
-
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}" )
|
1057
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1058
|
-
assert !t.valid?
|
1059
|
-
assert t.errors.on(:title)
|
1060
|
-
assert_equal "hoo 5", t.errors["title"]
|
1061
|
-
end
|
1062
|
-
|
1063
|
-
def test_validates_length_of_custom_errors_for_is_with_message
|
1064
|
-
Topic.validates_length_of( :title, :is=>5, :message=>"boo %{count}" )
|
1065
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1066
|
-
assert !t.valid?
|
1067
|
-
assert t.errors.on(:title)
|
1068
|
-
assert_equal "boo 5", t.errors["title"]
|
1069
|
-
end
|
1070
|
-
|
1071
|
-
def test_validates_length_of_custom_errors_for_is_with_wrong_length
|
1072
|
-
Topic.validates_length_of( :title, :is=>5, :wrong_length=>"hoo %{count}" )
|
1073
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1074
|
-
assert !t.valid?
|
1075
|
-
assert t.errors.on(:title)
|
1076
|
-
assert_equal "hoo 5", t.errors["title"]
|
1077
|
-
end
|
1078
|
-
|
1079
|
-
def test_validates_length_of_using_minimum_utf8
|
1080
|
-
with_kcode('UTF8') do
|
1081
|
-
Topic.validates_length_of :title, :minimum => 5
|
1082
|
-
|
1083
|
-
t = Topic.create("title" => "一二三四五", "content" => "whatever")
|
1084
|
-
assert t.valid?
|
1085
|
-
|
1086
|
-
t.title = "一二三四"
|
1087
|
-
assert !t.valid?
|
1088
|
-
assert t.errors.on(:title)
|
1089
|
-
assert_equal "is too short (minimum is 5 characters)", t.errors["title"]
|
1090
|
-
end
|
1091
|
-
end
|
1092
|
-
|
1093
|
-
def test_validates_length_of_using_maximum_utf8
|
1094
|
-
with_kcode('UTF8') do
|
1095
|
-
Topic.validates_length_of :title, :maximum => 5
|
1096
|
-
|
1097
|
-
t = Topic.create("title" => "一二三四五", "content" => "whatever")
|
1098
|
-
assert t.valid?
|
1099
|
-
|
1100
|
-
t.title = "一二34五六"
|
1101
|
-
assert !t.valid?
|
1102
|
-
assert t.errors.on(:title)
|
1103
|
-
assert_equal "is too long (maximum is 5 characters)", t.errors["title"]
|
1104
|
-
end
|
1105
|
-
end
|
1106
|
-
|
1107
|
-
def test_validates_length_of_using_within_utf8
|
1108
|
-
with_kcode('UTF8') do
|
1109
|
-
Topic.validates_length_of(:title, :content, :within => 3..5)
|
1110
|
-
|
1111
|
-
t = Topic.new("title" => "一二", "content" => "12三四五六七")
|
1112
|
-
assert !t.valid?
|
1113
|
-
assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title)
|
1114
|
-
assert_equal "is too long (maximum is 5 characters)", t.errors.on(:content)
|
1115
|
-
t.title = "一二三"
|
1116
|
-
t.content = "12三"
|
1117
|
-
assert t.valid?
|
1118
|
-
end
|
1119
|
-
end
|
1120
|
-
|
1121
|
-
def test_optionally_validates_length_of_using_within_utf8
|
1122
|
-
with_kcode('UTF8') do
|
1123
|
-
Topic.validates_length_of :title, :within => 3..5, :allow_nil => true
|
1124
|
-
|
1125
|
-
t = Topic.create(:title => "一二三四五")
|
1126
|
-
assert t.valid?, t.errors.inspect
|
1127
|
-
|
1128
|
-
t = Topic.create(:title => "一二三")
|
1129
|
-
assert t.valid?, t.errors.inspect
|
1130
|
-
|
1131
|
-
t.title = nil
|
1132
|
-
assert t.valid?, t.errors.inspect
|
1133
|
-
end
|
1134
|
-
end
|
1135
|
-
|
1136
|
-
def test_optionally_validates_length_of_using_within_on_create_utf8
|
1137
|
-
with_kcode('UTF8') do
|
1138
|
-
Topic.validates_length_of :title, :within => 5..10, :on => :create, :too_long => "長すぎます: %{count}"
|
1139
|
-
|
1140
|
-
t = Topic.create("title" => "一二三四五六七八九十A", "content" => "whatever")
|
1141
|
-
assert !t.save
|
1142
|
-
assert t.errors.on(:title)
|
1143
|
-
assert_equal "長すぎます: 10", t.errors[:title]
|
1144
|
-
|
1145
|
-
t.title = "一二三四五六七八九"
|
1146
|
-
assert t.save
|
1147
|
-
|
1148
|
-
t.title = "一二3"
|
1149
|
-
assert t.save
|
1150
|
-
|
1151
|
-
t.content = "一二三四五六七八九十"
|
1152
|
-
assert t.save
|
1153
|
-
|
1154
|
-
t.content = t.title = "一二三四五六"
|
1155
|
-
assert t.save
|
1156
|
-
end
|
1157
|
-
end
|
1158
|
-
|
1159
|
-
def test_optionally_validates_length_of_using_within_on_update_utf8
|
1160
|
-
with_kcode('UTF8') do
|
1161
|
-
Topic.validates_length_of :title, :within => 5..10, :on => :update, :too_short => "短すぎます: %{count}"
|
1162
|
-
|
1163
|
-
t = Topic.create("title" => "一二三4", "content" => "whatever")
|
1164
|
-
assert !t.save
|
1165
|
-
assert t.errors.on(:title)
|
1166
|
-
|
1167
|
-
t.title = "1二三4"
|
1168
|
-
assert !t.save
|
1169
|
-
assert t.errors.on(:title)
|
1170
|
-
assert_equal "短すぎます: 5", t.errors[:title]
|
1171
|
-
|
1172
|
-
t.title = "一二三四五六七八九十A"
|
1173
|
-
assert !t.save
|
1174
|
-
assert t.errors.on(:title)
|
1175
|
-
|
1176
|
-
t.title = "一二345"
|
1177
|
-
assert t.save
|
1178
|
-
end
|
1179
|
-
end
|
1180
|
-
|
1181
|
-
def test_validates_length_of_using_is_utf8
|
1182
|
-
with_kcode('UTF8') do
|
1183
|
-
Topic.validates_length_of :title, :is => 5
|
1184
|
-
|
1185
|
-
t = Topic.create("title" => "一二345", "content" => "whatever")
|
1186
|
-
assert t.valid?
|
1187
|
-
|
1188
|
-
t.title = "一二345六"
|
1189
|
-
assert !t.valid?
|
1190
|
-
assert t.errors.on(:title)
|
1191
|
-
assert_equal "is the wrong length (should be 5 characters)", t.errors["title"]
|
1192
|
-
end
|
1193
|
-
end
|
1194
|
-
|
1195
|
-
def test_validates_length_of_with_block
|
1196
|
-
Topic.validates_length_of :content, :minimum => 5, :too_short=>"Your essay must be at least %{count} words.",
|
1197
|
-
:tokenizer => lambda {|str| str.scan(/\w+/) }
|
1198
|
-
t = Topic.create!(:content => "this content should be long enough")
|
1199
|
-
assert t.valid?
|
1200
|
-
|
1201
|
-
t.content = "not long enough"
|
1202
|
-
assert !t.valid?
|
1203
|
-
assert t.errors.on(:content)
|
1204
|
-
assert_equal "Your essay must be at least 5 words.", t.errors[:content]
|
1205
|
-
end
|
1206
|
-
|
1207
|
-
def test_validates_size_of_association_utf8
|
1208
|
-
repair_validations(Owner) do
|
1209
|
-
with_kcode('UTF8') do
|
1210
|
-
assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
|
1211
|
-
o = Owner.new('name' => 'あいうえおかきくけこ')
|
1212
|
-
assert !o.save
|
1213
|
-
assert o.errors.on(:pets)
|
1214
|
-
o.pets.build('name' => 'あいうえおかきくけこ')
|
1215
|
-
assert o.valid?
|
1216
|
-
end
|
1217
|
-
end
|
1218
|
-
end
|
1219
|
-
|
1220
|
-
def test_validates_associated_many
|
1221
|
-
Topic.validates_associated( :replies )
|
1222
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1223
|
-
t.replies << [r = Reply.new("title" => "A reply"), r2 = Reply.new("title" => "Another reply", "content" => "non-empty"), r3 = Reply.new("title" => "Yet another reply"), r4 = Reply.new("title" => "The last reply", "content" => "non-empty")]
|
1224
|
-
assert !t.valid?
|
1225
|
-
assert t.errors.on(:replies)
|
1226
|
-
assert_equal 1, r.errors.count # make sure all associated objects have been validated
|
1227
|
-
assert_equal 0, r2.errors.count
|
1228
|
-
assert_equal 1, r3.errors.count
|
1229
|
-
assert_equal 0, r4.errors.count
|
1230
|
-
r.content = r3.content = "non-empty"
|
1231
|
-
assert t.valid?
|
1232
|
-
end
|
1233
|
-
|
1234
|
-
def test_validates_associated_one
|
1235
|
-
repair_validations(Reply) do
|
1236
|
-
Reply.validates_associated( :topic )
|
1237
|
-
Topic.validates_presence_of( :content )
|
1238
|
-
r = Reply.new("title" => "A reply", "content" => "with content!")
|
1239
|
-
r.topic = Topic.create("title" => "uhohuhoh")
|
1240
|
-
assert !r.valid?
|
1241
|
-
assert r.errors.on(:topic)
|
1242
|
-
r.topic.content = "non-empty"
|
1243
|
-
assert r.valid?
|
1244
|
-
end
|
1245
|
-
end
|
1246
|
-
|
1247
|
-
def test_validate_block
|
1248
|
-
Topic.validate { |topic| topic.errors.add("title", "will never be valid") }
|
1249
|
-
t = Topic.create("title" => "Title", "content" => "whatever")
|
1250
|
-
assert !t.valid?
|
1251
|
-
assert t.errors.on(:title)
|
1252
|
-
assert_equal "will never be valid", t.errors["title"]
|
1253
|
-
end
|
1254
|
-
|
1255
|
-
def test_invalid_validator
|
1256
|
-
Topic.validate 3
|
1257
|
-
assert_raise(ArgumentError) { t = Topic.create }
|
1258
|
-
end
|
1259
|
-
|
1260
|
-
def test_throw_away_typing
|
1261
|
-
d = Developer.new("name" => "David", "salary" => "100,000")
|
1262
|
-
assert !d.valid?
|
1263
|
-
assert_equal 100, d.salary
|
1264
|
-
assert_equal "100,000", d.salary_before_type_cast
|
1265
|
-
end
|
1266
|
-
|
1267
|
-
def test_validates_acceptance_of_with_custom_error_using_quotes
|
1268
|
-
repair_validations(Developer) do
|
1269
|
-
Developer.validates_acceptance_of :salary, :message=> "This string contains 'single' and \"double\" quotes"
|
1270
|
-
d = Developer.new
|
1271
|
-
d.salary = "0"
|
1272
|
-
assert !d.valid?
|
1273
|
-
assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:salary).last
|
1274
|
-
end
|
1275
|
-
end
|
1276
|
-
|
1277
|
-
def test_validates_confirmation_of_with_custom_error_using_quotes
|
1278
|
-
repair_validations(Developer) do
|
1279
|
-
Developer.validates_confirmation_of :name, :message=> "confirm 'single' and \"double\" quotes"
|
1280
|
-
d = Developer.new
|
1281
|
-
d.name = "John"
|
1282
|
-
d.name_confirmation = "Johnny"
|
1283
|
-
assert !d.valid?
|
1284
|
-
assert_equal "confirm 'single' and \"double\" quotes", d.errors.on(:name)
|
1285
|
-
end
|
1286
|
-
end
|
1287
|
-
|
1288
|
-
def test_validates_format_of_with_custom_error_using_quotes
|
1289
|
-
repair_validations(Developer) do
|
1290
|
-
Developer.validates_format_of :name, :with => /^(A-Z*)$/, :message=> "format 'single' and \"double\" quotes"
|
1291
|
-
d = Developer.new
|
1292
|
-
d.name = d.name_confirmation = "John 32"
|
1293
|
-
assert !d.valid?
|
1294
|
-
assert_equal "format 'single' and \"double\" quotes", d.errors.on(:name)
|
1295
|
-
end
|
1296
|
-
end
|
1297
|
-
|
1298
|
-
def test_validates_inclusion_of_with_custom_error_using_quotes
|
1299
|
-
repair_validations(Developer) do
|
1300
|
-
Developer.validates_inclusion_of :salary, :in => 1000..80000, :message=> "This string contains 'single' and \"double\" quotes"
|
1301
|
-
d = Developer.new
|
1302
|
-
d.salary = "90,000"
|
1303
|
-
assert !d.valid?
|
1304
|
-
assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:salary).last
|
1305
|
-
end
|
1306
|
-
end
|
1307
|
-
|
1308
|
-
def test_validates_length_of_with_custom_too_long_using_quotes
|
1309
|
-
repair_validations(Developer) do
|
1310
|
-
Developer.validates_length_of :name, :maximum => 4, :too_long=> "This string contains 'single' and \"double\" quotes"
|
1311
|
-
d = Developer.new
|
1312
|
-
d.name = "Jeffrey"
|
1313
|
-
assert !d.valid?
|
1314
|
-
assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name)
|
1315
|
-
end
|
1316
|
-
end
|
1317
|
-
|
1318
|
-
def test_validates_length_of_with_custom_too_short_using_quotes
|
1319
|
-
repair_validations(Developer) do
|
1320
|
-
Developer.validates_length_of :name, :minimum => 4, :too_short=> "This string contains 'single' and \"double\" quotes"
|
1321
|
-
d = Developer.new
|
1322
|
-
d.name = "Joe"
|
1323
|
-
assert !d.valid?
|
1324
|
-
assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name)
|
1325
|
-
end
|
1326
|
-
end
|
1327
|
-
|
1328
|
-
def test_validates_length_of_with_custom_message_using_quotes
|
1329
|
-
repair_validations(Developer) do
|
1330
|
-
Developer.validates_length_of :name, :minimum => 4, :message=> "This string contains 'single' and \"double\" quotes"
|
1331
|
-
d = Developer.new
|
1332
|
-
d.name = "Joe"
|
1333
|
-
assert !d.valid?
|
1334
|
-
assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name)
|
1335
|
-
end
|
1336
|
-
end
|
1337
|
-
|
1338
|
-
def test_validates_presence_of_with_custom_message_using_quotes
|
1339
|
-
repair_validations(Developer) do
|
1340
|
-
Developer.validates_presence_of :non_existent, :message=> "This string contains 'single' and \"double\" quotes"
|
1341
|
-
d = Developer.new
|
1342
|
-
d.name = "Joe"
|
1343
|
-
assert !d.valid?
|
1344
|
-
assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:non_existent)
|
1345
|
-
end
|
1346
|
-
end
|
1347
|
-
|
1348
|
-
def test_validates_uniqueness_of_with_custom_message_using_quotes
|
1349
|
-
repair_validations(Developer) do
|
1350
|
-
Developer.validates_uniqueness_of :name, :message=> "This string contains 'single' and \"double\" quotes"
|
1351
|
-
d = Developer.new
|
1352
|
-
d.name = "David"
|
1353
|
-
assert !d.valid?
|
1354
|
-
assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name)
|
1355
|
-
end
|
1356
|
-
end
|
1357
|
-
|
1358
|
-
def test_validates_associated_with_custom_message_using_quotes
|
1359
|
-
repair_validations(Reply) do
|
1360
|
-
Reply.validates_associated :topic, :message=> "This string contains 'single' and \"double\" quotes"
|
1361
|
-
Topic.validates_presence_of :content
|
1362
|
-
r = Reply.create("title" => "A reply", "content" => "with content!")
|
1363
|
-
r.topic = Topic.create("title" => "uhohuhoh")
|
1364
|
-
assert !r.valid?
|
1365
|
-
assert_equal "This string contains 'single' and \"double\" quotes", r.errors.on(:topic)
|
1366
|
-
end
|
1367
|
-
end
|
1368
|
-
|
1369
|
-
def test_if_validation_using_method_true
|
1370
|
-
# When the method returns true
|
1371
|
-
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :if => :condition_is_true )
|
1372
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1373
|
-
assert !t.valid?
|
1374
|
-
assert t.errors.on(:title)
|
1375
|
-
assert_equal "hoo 5", t.errors["title"]
|
1376
|
-
end
|
1377
|
-
|
1378
|
-
def test_unless_validation_using_method_true
|
1379
|
-
# When the method returns true
|
1380
|
-
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :unless => :condition_is_true )
|
1381
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1382
|
-
assert t.valid?
|
1383
|
-
assert !t.errors.on(:title)
|
1384
|
-
end
|
1385
|
-
|
1386
|
-
def test_if_validation_using_method_false
|
1387
|
-
# When the method returns false
|
1388
|
-
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :if => :condition_is_true_but_its_not )
|
1389
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1390
|
-
assert t.valid?
|
1391
|
-
assert !t.errors.on(:title)
|
1392
|
-
end
|
1393
|
-
|
1394
|
-
def test_unless_validation_using_method_false
|
1395
|
-
# When the method returns false
|
1396
|
-
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :unless => :condition_is_true_but_its_not )
|
1397
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1398
|
-
assert !t.valid?
|
1399
|
-
assert t.errors.on(:title)
|
1400
|
-
assert_equal "hoo 5", t.errors["title"]
|
1401
|
-
end
|
1402
|
-
|
1403
|
-
def test_if_validation_using_string_true
|
1404
|
-
# When the evaluated string returns true
|
1405
|
-
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :if => "a = 1; a == 1" )
|
1406
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1407
|
-
assert !t.valid?
|
1408
|
-
assert t.errors.on(:title)
|
1409
|
-
assert_equal "hoo 5", t.errors["title"]
|
1410
|
-
end
|
1411
|
-
|
1412
|
-
def test_unless_validation_using_string_true
|
1413
|
-
# When the evaluated string returns true
|
1414
|
-
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :unless => "a = 1; a == 1" )
|
1415
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1416
|
-
assert t.valid?
|
1417
|
-
assert !t.errors.on(:title)
|
1418
|
-
end
|
1419
|
-
|
1420
|
-
def test_if_validation_using_string_false
|
1421
|
-
# When the evaluated string returns false
|
1422
|
-
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :if => "false")
|
1423
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1424
|
-
assert t.valid?
|
1425
|
-
assert !t.errors.on(:title)
|
1426
|
-
end
|
1427
|
-
|
1428
|
-
def test_unless_validation_using_string_false
|
1429
|
-
# When the evaluated string returns false
|
1430
|
-
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}", :unless => "false")
|
1431
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1432
|
-
assert !t.valid?
|
1433
|
-
assert t.errors.on(:title)
|
1434
|
-
assert_equal "hoo 5", t.errors["title"]
|
1435
|
-
end
|
1436
|
-
|
1437
|
-
def test_if_validation_using_block_true
|
1438
|
-
# When the block returns true
|
1439
|
-
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}",
|
1440
|
-
:if => Proc.new { |r| r.content.size > 4 } )
|
1441
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1442
|
-
assert !t.valid?
|
1443
|
-
assert t.errors.on(:title)
|
1444
|
-
assert_equal "hoo 5", t.errors["title"]
|
1445
|
-
end
|
1446
|
-
|
1447
|
-
def test_unless_validation_using_block_true
|
1448
|
-
# When the block returns true
|
1449
|
-
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}",
|
1450
|
-
:unless => Proc.new { |r| r.content.size > 4 } )
|
1451
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1452
|
-
assert t.valid?
|
1453
|
-
assert !t.errors.on(:title)
|
1454
|
-
end
|
1455
|
-
|
1456
|
-
def test_if_validation_using_block_false
|
1457
|
-
# When the block returns false
|
1458
|
-
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}",
|
1459
|
-
:if => Proc.new { |r| r.title != "uhohuhoh"} )
|
1460
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1461
|
-
assert t.valid?
|
1462
|
-
assert !t.errors.on(:title)
|
1463
|
-
end
|
1464
|
-
|
1465
|
-
def test_unless_validation_using_block_false
|
1466
|
-
# When the block returns false
|
1467
|
-
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %{count}",
|
1468
|
-
:unless => Proc.new { |r| r.title != "uhohuhoh"} )
|
1469
|
-
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
1470
|
-
assert !t.valid?
|
1471
|
-
assert t.errors.on(:title)
|
1472
|
-
assert_equal "hoo 5", t.errors["title"]
|
1473
|
-
end
|
1474
|
-
|
1475
|
-
def test_validates_associated_missing
|
1476
|
-
repair_validations(Reply) do
|
1477
|
-
Reply.validates_presence_of(:topic)
|
1478
|
-
r = Reply.create("title" => "A reply", "content" => "with content!")
|
1479
|
-
assert !r.valid?
|
1480
|
-
assert r.errors.on(:topic)
|
1481
|
-
|
1482
|
-
r.topic = Topic.find :first
|
1483
|
-
assert r.valid?
|
1484
|
-
end
|
1485
|
-
end
|
1486
|
-
|
1487
|
-
def test_errors_to_xml
|
1488
|
-
r = Reply.new :title => "Wrong Create"
|
1489
|
-
assert !r.valid?
|
1490
|
-
xml = r.errors.to_xml(:skip_instruct => true)
|
1491
|
-
assert_equal "<errors>", xml.first(8)
|
1492
|
-
assert xml.include?("<error>Title is Wrong Create</error>")
|
1493
|
-
assert xml.include?("<error>Content Empty</error>")
|
1494
|
-
end
|
1495
|
-
|
1496
|
-
def test_validation_order
|
1497
|
-
Topic.validates_presence_of :title, :author_name
|
1498
|
-
Topic.validate {|topic| topic.errors.add('author_email_address', 'will never be valid')}
|
1499
|
-
Topic.validates_length_of :title, :content, :minimum => 2
|
1500
|
-
|
1501
|
-
t = Topic.new :title => ''
|
1502
|
-
t.valid?
|
1503
|
-
e = t.errors.instance_variable_get '@errors'
|
1504
|
-
assert_equal 'title', key = e.keys.first
|
1505
|
-
assert_equal "can't be blank", t.errors.on(key).first
|
1506
|
-
assert_equal 'is too short (minimum is 2 characters)', t.errors.on(key).second
|
1507
|
-
assert_equal 'author_name', key = e.keys.second
|
1508
|
-
assert_equal "can't be blank", t.errors.on(key)
|
1509
|
-
assert_equal 'author_email_address', key = e.keys.third
|
1510
|
-
assert_equal 'will never be valid', t.errors.on(key)
|
1511
|
-
assert_equal 'content', key = e.keys.fourth
|
1512
|
-
assert_equal 'is too short (minimum is 2 characters)', t.errors.on(key)
|
1513
|
-
end
|
1514
|
-
|
1515
|
-
def test_invalid_should_be_the_opposite_of_valid
|
1516
|
-
Topic.validates_presence_of :title
|
1517
|
-
|
1518
|
-
t = Topic.new
|
1519
|
-
assert t.invalid?
|
1520
|
-
assert t.errors.invalid?(:title)
|
1521
|
-
|
1522
|
-
t.title = 'Things are going to change'
|
1523
|
-
assert !t.invalid?
|
1524
|
-
end
|
1525
|
-
|
1526
|
-
# previous implementation of validates_presence_of eval'd the
|
1527
|
-
# string with the wrong binding, this regression test is to
|
1528
|
-
# ensure that it works correctly
|
1529
|
-
def test_validation_with_if_as_string
|
1530
|
-
Topic.validates_presence_of(:title)
|
1531
|
-
Topic.validates_presence_of(:author_name, :if => "title.to_s.match('important')")
|
1532
|
-
|
1533
|
-
t = Topic.new
|
1534
|
-
assert !t.valid?, "A topic without a title should not be valid"
|
1535
|
-
assert !t.errors.invalid?("author_name"), "A topic without an 'important' title should not require an author"
|
1536
|
-
|
1537
|
-
t.title = "Just a title"
|
1538
|
-
assert t.valid?, "A topic with a basic title should be valid"
|
1539
|
-
|
1540
|
-
t.title = "A very important title"
|
1541
|
-
assert !t.valid?, "A topic with an important title, but without an author, should not be valid"
|
1542
|
-
assert t.errors.invalid?("author_name"), "A topic with an 'important' title should require an author"
|
1543
|
-
|
1544
|
-
t.author_name = "Hubert J. Farnsworth"
|
1545
|
-
assert t.valid?, "A topic with an important title and author should be valid"
|
1546
|
-
end
|
1547
|
-
end
|
1548
|
-
|
1549
|
-
|
1550
|
-
class ValidatesNumericalityTest < ActiveRecord::TestCase
|
1551
|
-
NIL = [nil]
|
1552
|
-
BLANK = ["", " ", " \t \r \n"]
|
1553
|
-
BIGDECIMAL_STRINGS = %w(12345678901234567890.1234567890) # 30 significent digits
|
1554
|
-
FLOAT_STRINGS = %w(0.0 +0.0 -0.0 10.0 10.5 -10.5 -0.0001 -090.1 90.1e1 -90.1e5 -90.1e-5 90e-5)
|
1555
|
-
INTEGER_STRINGS = %w(0 +0 -0 10 +10 -10 0090 -090)
|
1556
|
-
FLOATS = [0.0, 10.0, 10.5, -10.5, -0.0001] + FLOAT_STRINGS
|
1557
|
-
INTEGERS = [0, 10, -10] + INTEGER_STRINGS
|
1558
|
-
BIGDECIMAL = BIGDECIMAL_STRINGS.collect! { |bd| BigDecimal.new(bd) }
|
1559
|
-
JUNK = ["not a number", "42 not a number", "0xdeadbeef", "00-1", "--3", "+-3", "+3-1", "-+019.0", "12.12.13.12", "123\nnot a number"]
|
1560
|
-
INFINITY = [1.0/0.0]
|
1561
|
-
|
1562
|
-
repair_validations(Topic)
|
1563
|
-
|
1564
|
-
def test_default_validates_numericality_of
|
1565
|
-
Topic.validates_numericality_of :approved
|
1566
|
-
|
1567
|
-
invalid!(NIL + BLANK + JUNK)
|
1568
|
-
valid!(FLOATS + INTEGERS + BIGDECIMAL + INFINITY)
|
1569
|
-
end
|
1570
|
-
|
1571
|
-
def test_validates_numericality_of_with_nil_allowed
|
1572
|
-
Topic.validates_numericality_of :approved, :allow_nil => true
|
1573
|
-
|
1574
|
-
invalid!(JUNK)
|
1575
|
-
valid!(NIL + BLANK + FLOATS + INTEGERS + BIGDECIMAL + INFINITY)
|
1576
|
-
end
|
1577
|
-
|
1578
|
-
def test_validates_numericality_of_with_integer_only
|
1579
|
-
Topic.validates_numericality_of :approved, :only_integer => true
|
1580
|
-
|
1581
|
-
invalid!(NIL + BLANK + JUNK + FLOATS + BIGDECIMAL + INFINITY)
|
1582
|
-
valid!(INTEGERS)
|
1583
|
-
end
|
1584
|
-
|
1585
|
-
def test_validates_numericality_of_with_integer_only_and_nil_allowed
|
1586
|
-
Topic.validates_numericality_of :approved, :only_integer => true, :allow_nil => true
|
1587
|
-
|
1588
|
-
invalid!(JUNK + FLOATS + BIGDECIMAL + INFINITY)
|
1589
|
-
valid!(NIL + BLANK + INTEGERS)
|
1590
|
-
end
|
1591
|
-
|
1592
|
-
def test_validates_numericality_with_greater_than
|
1593
|
-
Topic.validates_numericality_of :approved, :greater_than => 10
|
1594
|
-
|
1595
|
-
invalid!([-10, 10], 'must be greater than 10')
|
1596
|
-
valid!([11])
|
1597
|
-
end
|
1598
|
-
|
1599
|
-
def test_validates_numericality_with_greater_than_or_equal
|
1600
|
-
Topic.validates_numericality_of :approved, :greater_than_or_equal_to => 10
|
1601
|
-
|
1602
|
-
invalid!([-9, 9], 'must be greater than or equal to 10')
|
1603
|
-
valid!([10])
|
1604
|
-
end
|
1605
|
-
|
1606
|
-
def test_validates_numericality_with_equal_to
|
1607
|
-
Topic.validates_numericality_of :approved, :equal_to => 10
|
1608
|
-
|
1609
|
-
invalid!([-10, 11] + INFINITY, 'must be equal to 10')
|
1610
|
-
valid!([10])
|
1611
|
-
end
|
1612
|
-
|
1613
|
-
def test_validates_numericality_with_less_than
|
1614
|
-
Topic.validates_numericality_of :approved, :less_than => 10
|
1615
|
-
|
1616
|
-
invalid!([10], 'must be less than 10')
|
1617
|
-
valid!([-9, 9])
|
1618
|
-
end
|
1619
|
-
|
1620
|
-
def test_validates_numericality_with_less_than_or_equal_to
|
1621
|
-
Topic.validates_numericality_of :approved, :less_than_or_equal_to => 10
|
1622
|
-
|
1623
|
-
invalid!([11], 'must be less than or equal to 10')
|
1624
|
-
valid!([-10, 10])
|
1625
|
-
end
|
1626
|
-
|
1627
|
-
def test_validates_numericality_with_odd
|
1628
|
-
Topic.validates_numericality_of :approved, :odd => true
|
1629
|
-
|
1630
|
-
invalid!([-2, 2], 'must be odd')
|
1631
|
-
valid!([-1, 1])
|
1632
|
-
end
|
1633
|
-
|
1634
|
-
def test_validates_numericality_with_even
|
1635
|
-
Topic.validates_numericality_of :approved, :even => true
|
1636
|
-
|
1637
|
-
invalid!([-1, 1], 'must be even')
|
1638
|
-
valid!([-2, 2])
|
1639
|
-
end
|
1640
|
-
|
1641
|
-
def test_validates_numericality_with_greater_than_less_than_and_even
|
1642
|
-
Topic.validates_numericality_of :approved, :greater_than => 1, :less_than => 4, :even => true
|
1643
|
-
|
1644
|
-
invalid!([1, 3, 4])
|
1645
|
-
valid!([2])
|
1646
|
-
end
|
1647
|
-
|
1648
|
-
def test_validates_numericality_with_numeric_message
|
1649
|
-
Topic.validates_numericality_of :approved, :less_than => 4, :message => "smaller than %{count}"
|
1650
|
-
topic = Topic.new("title" => "numeric test", "approved" => 10)
|
1651
|
-
|
1652
|
-
assert !topic.valid?
|
1653
|
-
assert_equal "smaller than 4", topic.errors.on(:approved)
|
1654
|
-
|
1655
|
-
Topic.validates_numericality_of :approved, :greater_than => 4, :message => "greater than %{count}"
|
1656
|
-
topic = Topic.new("title" => "numeric test", "approved" => 1)
|
1657
|
-
|
1658
|
-
assert !topic.valid?
|
1659
|
-
assert_equal "greater than 4", topic.errors.on(:approved)
|
1660
|
-
end
|
1661
|
-
|
1662
|
-
private
|
1663
|
-
def invalid!(values, error=nil)
|
1664
|
-
with_each_topic_approved_value(values) do |topic, value|
|
1665
|
-
assert !topic.valid?, "#{value.inspect} not rejected as a number"
|
1666
|
-
assert topic.errors.on(:approved)
|
1667
|
-
assert_equal error, topic.errors.on(:approved) if error
|
1668
|
-
end
|
1669
|
-
end
|
1670
|
-
|
1671
|
-
def valid!(values)
|
1672
|
-
with_each_topic_approved_value(values) do |topic, value|
|
1673
|
-
assert topic.valid?, "#{value.inspect} not accepted as a number"
|
1674
|
-
end
|
1675
|
-
end
|
1676
|
-
|
1677
|
-
def with_each_topic_approved_value(values)
|
1678
|
-
topic = Topic.new("title" => "numeric test", "content" => "whatever")
|
1679
|
-
values.each do |value|
|
1680
|
-
topic.approved = value
|
1681
|
-
yield topic, value
|
1682
|
-
end
|
1683
|
-
end
|
1684
|
-
end
|