activerecord 2.0.5 → 2.1.0
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.
- data/CHANGELOG +168 -6
- data/README +27 -22
- data/RUNNING_UNIT_TESTS +7 -4
- data/Rakefile +22 -25
- data/lib/active_record.rb +8 -2
- data/lib/active_record/aggregations.rb +21 -12
- data/lib/active_record/association_preload.rb +277 -0
- data/lib/active_record/associations.rb +481 -295
- data/lib/active_record/associations/association_collection.rb +162 -37
- data/lib/active_record/associations/association_proxy.rb +71 -7
- data/lib/active_record/associations/belongs_to_association.rb +5 -3
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +5 -6
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +12 -64
- data/lib/active_record/associations/has_many_association.rb +8 -73
- data/lib/active_record/associations/has_many_through_association.rb +68 -117
- data/lib/active_record/associations/has_one_association.rb +7 -5
- data/lib/active_record/associations/has_one_through_association.rb +28 -0
- data/lib/active_record/attribute_methods.rb +69 -19
- data/lib/active_record/base.rb +496 -275
- data/lib/active_record/calculations.rb +28 -21
- data/lib/active_record/callbacks.rb +9 -38
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -2
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +232 -45
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +141 -27
- data/lib/active_record/connection_adapters/abstract_adapter.rb +9 -13
- data/lib/active_record/connection_adapters/mysql_adapter.rb +57 -24
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +143 -42
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +18 -10
- data/lib/active_record/dirty.rb +158 -0
- data/lib/active_record/fixtures.rb +121 -156
- data/lib/active_record/locking/optimistic.rb +14 -11
- data/lib/active_record/locking/pessimistic.rb +2 -2
- data/lib/active_record/migration.rb +157 -77
- data/lib/active_record/named_scope.rb +163 -0
- data/lib/active_record/observer.rb +19 -5
- data/lib/active_record/reflection.rb +34 -14
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +4 -4
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/serializers/json_serializer.rb +37 -28
- data/lib/active_record/serializers/xml_serializer.rb +52 -29
- data/lib/active_record/test_case.rb +36 -0
- data/lib/active_record/timestamp.rb +4 -4
- data/lib/active_record/transactions.rb +3 -3
- data/lib/active_record/validations.rb +182 -248
- data/lib/active_record/version.rb +2 -2
- data/test/{fixtures → assets}/example.log +0 -0
- data/test/{fixtures → assets}/flowers.jpg +0 -0
- data/test/cases/aaa_create_tables_test.rb +24 -0
- data/test/cases/active_schema_test_mysql.rb +95 -0
- data/test/cases/active_schema_test_postgresql.rb +24 -0
- data/test/{adapter_test.rb → cases/adapter_test.rb} +15 -14
- data/test/{adapter_test_sqlserver.rb → cases/adapter_test_sqlserver.rb} +95 -95
- data/test/{aggregations_test.rb → cases/aggregations_test.rb} +20 -20
- data/test/{ar_schema_test.rb → cases/ar_schema_test.rb} +6 -6
- data/test/cases/associations/belongs_to_associations_test.rb +412 -0
- data/test/{associations → cases/associations}/callbacks_test.rb +24 -10
- data/test/{associations → cases/associations}/cascaded_eager_loading_test.rb +18 -17
- data/test/cases/associations/eager_load_nested_include_test.rb +83 -0
- data/test/{associations → cases/associations}/eager_singularization_test.rb +5 -5
- data/test/{associations → cases/associations}/eager_test.rb +216 -51
- data/test/{associations → cases/associations}/extension_test.rb +8 -8
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +684 -0
- data/test/cases/associations/has_many_associations_test.rb +932 -0
- data/test/cases/associations/has_many_through_associations_test.rb +190 -0
- data/test/cases/associations/has_one_associations_test.rb +323 -0
- data/test/cases/associations/has_one_through_associations_test.rb +74 -0
- data/test/{associations → cases/associations}/inner_join_association_test.rb +20 -20
- data/test/{associations → cases/associations}/join_model_test.rb +175 -35
- data/test/cases/associations_test.rb +262 -0
- data/test/{attribute_methods_test.rb → cases/attribute_methods_test.rb} +103 -11
- data/test/{base_test.rb → cases/base_test.rb} +338 -191
- data/test/{binary_test.rb → cases/binary_test.rb} +6 -4
- data/test/{calculations_test.rb → cases/calculations_test.rb} +35 -23
- data/test/{callbacks_test.rb → cases/callbacks_test.rb} +7 -7
- data/test/{class_inheritable_attributes_test.rb → cases/class_inheritable_attributes_test.rb} +3 -3
- data/test/{column_alias_test.rb → cases/column_alias_test.rb} +3 -3
- data/test/{connection_test_firebird.rb → cases/connection_test_firebird.rb} +2 -2
- data/test/{connection_test_mysql.rb → cases/connection_test_mysql.rb} +2 -2
- data/test/{copy_table_test_sqlite.rb → cases/copy_table_test_sqlite.rb} +13 -13
- data/test/{datatype_test_postgresql.rb → cases/datatype_test_postgresql.rb} +8 -8
- data/test/{date_time_test.rb → cases/date_time_test.rb} +5 -5
- data/test/{default_test_firebird.rb → cases/default_test_firebird.rb} +3 -3
- data/test/{defaults_test.rb → cases/defaults_test.rb} +8 -6
- data/test/{deprecated_finder_test.rb → cases/deprecated_finder_test.rb} +3 -3
- data/test/cases/dirty_test.rb +163 -0
- data/test/cases/finder_respond_to_test.rb +76 -0
- data/test/{finder_test.rb → cases/finder_test.rb} +266 -33
- data/test/{fixtures_test.rb → cases/fixtures_test.rb} +88 -72
- data/test/cases/helper.rb +47 -0
- data/test/{inheritance_test.rb → cases/inheritance_test.rb} +61 -17
- data/test/cases/invalid_date_test.rb +24 -0
- data/test/{json_serialization_test.rb → cases/json_serialization_test.rb} +36 -11
- data/test/{lifecycle_test.rb → cases/lifecycle_test.rb} +16 -13
- data/test/{locking_test.rb → cases/locking_test.rb} +17 -10
- data/test/{method_scoping_test.rb → cases/method_scoping_test.rb} +75 -39
- data/test/{migration_test.rb → cases/migration_test.rb} +420 -80
- data/test/{migration_test_firebird.rb → cases/migration_test_firebird.rb} +3 -3
- data/test/{mixin_test.rb → cases/mixin_test.rb} +7 -6
- data/test/{modules_test.rb → cases/modules_test.rb} +11 -6
- data/test/{multiple_db_test.rb → cases/multiple_db_test.rb} +5 -5
- data/test/cases/named_scope_test.rb +157 -0
- data/test/{pk_test.rb → cases/pk_test.rb} +10 -10
- data/test/{query_cache_test.rb → cases/query_cache_test.rb} +12 -10
- data/test/{readonly_test.rb → cases/readonly_test.rb} +11 -11
- data/test/{reflection_test.rb → cases/reflection_test.rb} +15 -14
- data/test/{reserved_word_test_mysql.rb → cases/reserved_word_test_mysql.rb} +4 -5
- data/test/{schema_authorization_test_postgresql.rb → cases/schema_authorization_test_postgresql.rb} +5 -5
- data/test/cases/schema_dumper_test.rb +138 -0
- data/test/cases/schema_test_postgresql.rb +102 -0
- data/test/{serialization_test.rb → cases/serialization_test.rb} +7 -7
- data/test/{synonym_test_oracle.rb → cases/synonym_test_oracle.rb} +5 -5
- data/test/{table_name_test_sqlserver.rb → cases/table_name_test_sqlserver.rb} +3 -3
- data/test/{threaded_connections_test.rb → cases/threaded_connections_test.rb} +7 -7
- data/test/{transactions_test.rb → cases/transactions_test.rb} +31 -5
- data/test/{unconnected_test.rb → cases/unconnected_test.rb} +2 -2
- data/test/{validations_test.rb → cases/validations_test.rb} +141 -39
- data/test/{xml_serialization_test.rb → cases/xml_serialization_test.rb} +12 -12
- data/test/config.rb +5 -0
- data/test/connections/native_db2/connection.rb +1 -1
- data/test/connections/native_firebird/connection.rb +1 -1
- data/test/connections/native_frontbase/connection.rb +1 -1
- data/test/connections/native_mysql/connection.rb +1 -1
- data/test/connections/native_openbase/connection.rb +1 -1
- data/test/connections/native_oracle/connection.rb +1 -1
- data/test/connections/native_postgresql/connection.rb +1 -3
- data/test/connections/native_sqlite/connection.rb +2 -2
- data/test/connections/native_sqlite3/connection.rb +2 -2
- data/test/connections/native_sqlite3/in_memory_connection.rb +3 -3
- data/test/connections/native_sybase/connection.rb +1 -1
- data/test/fixtures/author_addresses.yml +5 -0
- data/test/fixtures/authors.yml +2 -0
- data/test/fixtures/clubs.yml +6 -0
- data/test/fixtures/jobs.yml +7 -0
- data/test/fixtures/members.yml +4 -0
- data/test/fixtures/memberships.yml +20 -0
- data/test/fixtures/owners.yml +7 -0
- data/test/fixtures/people.yml +4 -1
- data/test/fixtures/pets.yml +14 -0
- data/test/fixtures/posts.yml +1 -0
- data/test/fixtures/price_estimates.yml +7 -0
- data/test/fixtures/readers.yml +5 -0
- data/test/fixtures/references.yml +17 -0
- data/test/fixtures/sponsors.yml +9 -0
- data/test/fixtures/subscribers.yml +7 -0
- data/test/fixtures/subscriptions.yml +12 -0
- data/test/fixtures/taggings.yml +4 -1
- data/test/fixtures/topics.yml +22 -2
- data/test/fixtures/warehouse-things.yml +3 -0
- data/test/{fixtures/migrations_with_decimal → migrations/decimal}/1_give_me_big_numbers.rb +0 -0
- data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/1_people_have_last_names.rb +1 -1
- data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/2_we_need_reminders.rb +1 -1
- data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/3_foo.rb +0 -0
- data/test/{fixtures/migrations → migrations/duplicate}/3_innocent_jointable.rb +0 -0
- data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
- data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
- data/test/{fixtures/migrations_with_duplicate → migrations/interleaved/pass_1}/3_innocent_jointable.rb +0 -0
- data/test/{fixtures/migrations → migrations/interleaved/pass_2}/1_people_have_last_names.rb +1 -1
- data/test/{fixtures/migrations_with_missing_versions/4_innocent_jointable.rb → migrations/interleaved/pass_2/3_innocent_jointable.rb} +0 -0
- data/test/{fixtures/migrations_with_missing_versions → migrations/interleaved/pass_3}/1_people_have_last_names.rb +1 -1
- data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +8 -0
- data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +12 -0
- data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/1000_people_have_middle_names.rb +1 -1
- data/test/migrations/missing/1_people_have_last_names.rb +9 -0
- data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/3_we_need_reminders.rb +1 -1
- data/test/migrations/missing/4_innocent_jointable.rb +12 -0
- data/test/migrations/valid/1_people_have_last_names.rb +9 -0
- data/test/{fixtures/migrations → migrations/valid}/2_we_need_reminders.rb +1 -1
- data/test/migrations/valid/3_innocent_jointable.rb +12 -0
- data/test/{fixtures → models}/author.rb +28 -4
- data/test/{fixtures → models}/auto_id.rb +0 -0
- data/test/{fixtures → models}/binary.rb +0 -0
- data/test/{fixtures → models}/book.rb +0 -0
- data/test/{fixtures → models}/categorization.rb +0 -0
- data/test/{fixtures → models}/category.rb +8 -5
- data/test/{fixtures → models}/citation.rb +0 -0
- data/test/models/club.rb +7 -0
- data/test/{fixtures → models}/column_name.rb +0 -0
- data/test/{fixtures → models}/comment.rb +5 -3
- data/test/{fixtures → models}/company.rb +15 -6
- data/test/{fixtures → models}/company_in_module.rb +5 -3
- data/test/{fixtures → models}/computer.rb +0 -1
- data/test/{fixtures → models}/contact.rb +1 -1
- data/test/{fixtures → models}/course.rb +0 -0
- data/test/{fixtures → models}/customer.rb +8 -8
- data/test/{fixtures → models}/default.rb +0 -0
- data/test/{fixtures → models}/developer.rb +14 -10
- data/test/{fixtures → models}/edge.rb +0 -0
- data/test/{fixtures → models}/entrant.rb +0 -0
- data/test/models/guid.rb +2 -0
- data/test/{fixtures → models}/item.rb +0 -0
- data/test/models/job.rb +5 -0
- data/test/{fixtures → models}/joke.rb +0 -0
- data/test/{fixtures → models}/keyboard.rb +0 -0
- data/test/{fixtures → models}/legacy_thing.rb +0 -0
- data/test/{fixtures → models}/matey.rb +0 -0
- data/test/models/member.rb +9 -0
- data/test/models/membership.rb +9 -0
- data/test/{fixtures → models}/minimalistic.rb +0 -0
- data/test/{fixtures → models}/mixed_case_monkey.rb +0 -0
- data/test/{fixtures → models}/movie.rb +0 -0
- data/test/{fixtures → models}/order.rb +2 -2
- data/test/models/owner.rb +4 -0
- data/test/{fixtures → models}/parrot.rb +0 -0
- data/test/models/person.rb +10 -0
- data/test/models/pet.rb +4 -0
- data/test/models/pirate.rb +9 -0
- data/test/{fixtures → models}/post.rb +23 -2
- data/test/models/price_estimate.rb +3 -0
- data/test/{fixtures → models}/project.rb +1 -0
- data/test/{fixtures → models}/reader.rb +0 -0
- data/test/models/reference.rb +4 -0
- data/test/{fixtures → models}/reply.rb +7 -5
- data/test/{fixtures → models}/ship.rb +0 -0
- data/test/models/sponsor.rb +4 -0
- data/test/{fixtures → models}/subject.rb +0 -0
- data/test/{fixtures → models}/subscriber.rb +2 -0
- data/test/models/subscription.rb +4 -0
- data/test/{fixtures → models}/tag.rb +0 -0
- data/test/{fixtures → models}/tagging.rb +0 -0
- data/test/{fixtures → models}/task.rb +0 -0
- data/test/{fixtures → models}/topic.rb +32 -4
- data/test/{fixtures → models}/treasure.rb +2 -0
- data/test/{fixtures → models}/vertex.rb +0 -0
- data/test/models/warehouse_thing.rb +5 -0
- data/test/schema/mysql_specific_schema.rb +12 -0
- data/test/schema/postgresql_specific_schema.rb +103 -0
- data/test/schema/schema.rb +421 -0
- data/test/schema/schema2.rb +6 -0
- data/test/schema/sqlite_specific_schema.rb +25 -0
- data/test/schema/sqlserver_specific_schema.rb +5 -0
- metadata +192 -176
- data/test/aaa_create_tables_test.rb +0 -72
- data/test/abstract_unit.rb +0 -84
- data/test/active_schema_test_mysql.rb +0 -46
- data/test/all.sh +0 -8
- data/test/association_inheritance_reload.rb +0 -14
- data/test/associations_test.rb +0 -2177
- data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +0 -1
- data/test/fixtures/bad_fixtures/attr_with_spaces +0 -1
- data/test/fixtures/bad_fixtures/blank_line +0 -3
- data/test/fixtures/bad_fixtures/duplicate_attributes +0 -3
- data/test/fixtures/bad_fixtures/missing_value +0 -1
- data/test/fixtures/db_definitions/db2.drop.sql +0 -33
- data/test/fixtures/db_definitions/db2.sql +0 -235
- data/test/fixtures/db_definitions/db22.drop.sql +0 -2
- data/test/fixtures/db_definitions/db22.sql +0 -5
- data/test/fixtures/db_definitions/firebird.drop.sql +0 -65
- data/test/fixtures/db_definitions/firebird.sql +0 -310
- data/test/fixtures/db_definitions/firebird2.drop.sql +0 -2
- data/test/fixtures/db_definitions/firebird2.sql +0 -6
- data/test/fixtures/db_definitions/frontbase.drop.sql +0 -33
- data/test/fixtures/db_definitions/frontbase.sql +0 -273
- data/test/fixtures/db_definitions/frontbase2.drop.sql +0 -1
- data/test/fixtures/db_definitions/frontbase2.sql +0 -4
- data/test/fixtures/db_definitions/openbase.drop.sql +0 -2
- data/test/fixtures/db_definitions/openbase.sql +0 -318
- data/test/fixtures/db_definitions/openbase2.drop.sql +0 -2
- data/test/fixtures/db_definitions/openbase2.sql +0 -7
- data/test/fixtures/db_definitions/oracle.drop.sql +0 -67
- data/test/fixtures/db_definitions/oracle.sql +0 -330
- data/test/fixtures/db_definitions/oracle2.drop.sql +0 -2
- data/test/fixtures/db_definitions/oracle2.sql +0 -6
- data/test/fixtures/db_definitions/postgresql.drop.sql +0 -44
- data/test/fixtures/db_definitions/postgresql.sql +0 -292
- data/test/fixtures/db_definitions/postgresql2.drop.sql +0 -2
- data/test/fixtures/db_definitions/postgresql2.sql +0 -4
- data/test/fixtures/db_definitions/schema.rb +0 -354
- data/test/fixtures/db_definitions/schema2.rb +0 -11
- data/test/fixtures/db_definitions/sqlite.drop.sql +0 -33
- data/test/fixtures/db_definitions/sqlite.sql +0 -219
- data/test/fixtures/db_definitions/sqlite2.drop.sql +0 -2
- data/test/fixtures/db_definitions/sqlite2.sql +0 -5
- data/test/fixtures/db_definitions/sybase.drop.sql +0 -35
- data/test/fixtures/db_definitions/sybase.sql +0 -222
- data/test/fixtures/db_definitions/sybase2.drop.sql +0 -4
- data/test/fixtures/db_definitions/sybase2.sql +0 -5
- data/test/fixtures/developers_projects/david_action_controller +0 -3
- data/test/fixtures/developers_projects/david_active_record +0 -3
- data/test/fixtures/developers_projects/jamis_active_record +0 -2
- data/test/fixtures/person.rb +0 -4
- data/test/fixtures/pirate.rb +0 -5
- data/test/fixtures/subscribers/first +0 -2
- data/test/fixtures/subscribers/second +0 -2
- data/test/schema_dumper_test.rb +0 -131
- data/test/schema_test_postgresql.rb +0 -64
@@ -1,11 +1,11 @@
|
|
1
|
-
require
|
2
|
-
require '
|
3
|
-
require '
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/default'
|
3
|
+
require 'models/entrant'
|
4
4
|
|
5
|
-
class DefaultTest <
|
5
|
+
class DefaultTest < ActiveRecord::TestCase
|
6
6
|
def test_nil_defaults_for_not_null_columns
|
7
7
|
column_defaults =
|
8
|
-
if current_adapter?(:MysqlAdapter)
|
8
|
+
if current_adapter?(:MysqlAdapter) && Mysql.client_version < 50051
|
9
9
|
{ 'id' => nil, 'name' => '', 'course_id' => nil }
|
10
10
|
else
|
11
11
|
{ 'id' => nil, 'name' => nil, 'course_id' => nil }
|
@@ -61,7 +61,9 @@ class DefaultTest < Test::Unit::TestCase
|
|
61
61
|
|
62
62
|
if current_adapter?(:PostgreSQLAdapter)
|
63
63
|
def test_multiline_default_text
|
64
|
-
|
64
|
+
# older postgres versions represent the default with escapes ("\\012" for a newline)
|
65
|
+
assert ( "--- []\n\n" == Default.columns_hash['multiline_default'].default ||
|
66
|
+
"--- []\\012\\012" == Default.columns_hash['multiline_default'].default)
|
65
67
|
end
|
66
68
|
end
|
67
69
|
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require '
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/entrant'
|
3
3
|
|
4
|
-
class DeprecatedFinderTest <
|
4
|
+
class DeprecatedFinderTest < ActiveRecord::TestCase
|
5
5
|
fixtures :entrants
|
6
6
|
|
7
7
|
def test_deprecated_find_all_was_removed
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'cases/helper'
|
2
|
+
require 'models/topic' # For booleans
|
3
|
+
require 'models/pirate' # For timestamps
|
4
|
+
require 'models/parrot'
|
5
|
+
|
6
|
+
class Pirate # Just reopening it, not defining it
|
7
|
+
attr_accessor :detected_changes_in_after_update # Boolean for if changes are detected
|
8
|
+
attr_accessor :changes_detected_in_after_update # Actual changes
|
9
|
+
|
10
|
+
after_update :check_changes
|
11
|
+
|
12
|
+
private
|
13
|
+
# after_save/update in sweepers, observers, and the model itself
|
14
|
+
# can end up checking dirty status and acting on the results
|
15
|
+
def check_changes
|
16
|
+
if self.changed?
|
17
|
+
self.detected_changes_in_after_update = true
|
18
|
+
self.changes_detected_in_after_update = self.changes
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class DirtyTest < ActiveRecord::TestCase
|
24
|
+
def test_attribute_changes
|
25
|
+
# New record - no changes.
|
26
|
+
pirate = Pirate.new
|
27
|
+
assert !pirate.catchphrase_changed?
|
28
|
+
assert_nil pirate.catchphrase_change
|
29
|
+
|
30
|
+
# Change catchphrase.
|
31
|
+
pirate.catchphrase = 'arrr'
|
32
|
+
assert pirate.catchphrase_changed?
|
33
|
+
assert_nil pirate.catchphrase_was
|
34
|
+
assert_equal [nil, 'arrr'], pirate.catchphrase_change
|
35
|
+
|
36
|
+
# Saved - no changes.
|
37
|
+
pirate.save!
|
38
|
+
assert !pirate.catchphrase_changed?
|
39
|
+
assert_nil pirate.catchphrase_change
|
40
|
+
|
41
|
+
# Same value - no changes.
|
42
|
+
pirate.catchphrase = 'arrr'
|
43
|
+
assert !pirate.catchphrase_changed?
|
44
|
+
assert_nil pirate.catchphrase_change
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_nullable_integer_not_marked_as_changed_if_new_value_is_blank
|
48
|
+
pirate = Pirate.new
|
49
|
+
|
50
|
+
["", nil].each do |value|
|
51
|
+
pirate.parrot_id = value
|
52
|
+
assert !pirate.parrot_id_changed?
|
53
|
+
assert_nil pirate.parrot_id_change
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_object_should_be_changed_if_any_attribute_is_changed
|
58
|
+
pirate = Pirate.new
|
59
|
+
assert !pirate.changed?
|
60
|
+
assert_equal [], pirate.changed
|
61
|
+
assert_equal Hash.new, pirate.changes
|
62
|
+
|
63
|
+
pirate.catchphrase = 'arrr'
|
64
|
+
assert pirate.changed?
|
65
|
+
assert_nil pirate.catchphrase_was
|
66
|
+
assert_equal %w(catchphrase), pirate.changed
|
67
|
+
assert_equal({'catchphrase' => [nil, 'arrr']}, pirate.changes)
|
68
|
+
|
69
|
+
pirate.save
|
70
|
+
assert !pirate.changed?
|
71
|
+
assert_equal [], pirate.changed
|
72
|
+
assert_equal Hash.new, pirate.changes
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_attribute_will_change!
|
76
|
+
pirate = Pirate.create!(:catchphrase => 'arr')
|
77
|
+
|
78
|
+
pirate.catchphrase << ' matey'
|
79
|
+
assert !pirate.catchphrase_changed?
|
80
|
+
|
81
|
+
assert pirate.catchphrase_will_change!
|
82
|
+
assert pirate.catchphrase_changed?
|
83
|
+
assert_equal ['arr matey', 'arr matey'], pirate.catchphrase_change
|
84
|
+
|
85
|
+
pirate.catchphrase << '!'
|
86
|
+
assert pirate.catchphrase_changed?
|
87
|
+
assert_equal ['arr matey', 'arr matey!'], pirate.catchphrase_change
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_association_assignment_changes_foreign_key
|
91
|
+
pirate = Pirate.create!(:catchphrase => 'jarl')
|
92
|
+
pirate.parrot = Parrot.create!
|
93
|
+
assert pirate.changed?
|
94
|
+
assert_equal %w(parrot_id), pirate.changed
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_attribute_should_be_compared_with_type_cast
|
98
|
+
topic = Topic.new
|
99
|
+
assert topic.approved?
|
100
|
+
assert !topic.approved_changed?
|
101
|
+
|
102
|
+
# Coming from web form.
|
103
|
+
params = {:topic => {:approved => 1}}
|
104
|
+
# In the controller.
|
105
|
+
topic.attributes = params[:topic]
|
106
|
+
assert topic.approved?
|
107
|
+
assert !topic.approved_changed?
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_partial_update
|
111
|
+
pirate = Pirate.new(:catchphrase => 'foo')
|
112
|
+
old_updated_on = 1.hour.ago.beginning_of_day
|
113
|
+
|
114
|
+
with_partial_updates Pirate, false do
|
115
|
+
assert_queries(2) { 2.times { pirate.save! } }
|
116
|
+
Pirate.update_all({ :updated_on => old_updated_on }, :id => pirate.id)
|
117
|
+
end
|
118
|
+
|
119
|
+
with_partial_updates Pirate, true do
|
120
|
+
assert_queries(0) { 2.times { pirate.save! } }
|
121
|
+
assert_equal old_updated_on, pirate.reload.updated_on
|
122
|
+
|
123
|
+
assert_queries(1) { pirate.catchphrase = 'bar'; pirate.save! }
|
124
|
+
assert_not_equal old_updated_on, pirate.reload.updated_on
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_changed_attributes_should_be_preserved_if_save_failure
|
129
|
+
pirate = Pirate.new
|
130
|
+
pirate.parrot_id = 1
|
131
|
+
assert !pirate.save
|
132
|
+
check_pirate_after_save_failure(pirate)
|
133
|
+
|
134
|
+
pirate = Pirate.new
|
135
|
+
pirate.parrot_id = 1
|
136
|
+
assert_raises(ActiveRecord::RecordInvalid) { pirate.save! }
|
137
|
+
check_pirate_after_save_failure(pirate)
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_reload_should_clear_changed_attributes
|
141
|
+
pirate = Pirate.create!(:catchphrase => "shiver me timbers")
|
142
|
+
pirate.catchphrase = "*hic*"
|
143
|
+
assert pirate.changed?
|
144
|
+
pirate.reload
|
145
|
+
assert !pirate.changed?
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
def with_partial_updates(klass, on = true)
|
150
|
+
old = klass.partial_updates?
|
151
|
+
klass.partial_updates = on
|
152
|
+
yield
|
153
|
+
ensure
|
154
|
+
klass.partial_updates = old
|
155
|
+
end
|
156
|
+
|
157
|
+
def check_pirate_after_save_failure(pirate)
|
158
|
+
assert pirate.changed?
|
159
|
+
assert pirate.parrot_id_changed?
|
160
|
+
assert_equal %w(parrot_id), pirate.changed
|
161
|
+
assert_nil pirate.parrot_id_was
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/topic'
|
3
|
+
|
4
|
+
class FinderRespondToTest < ActiveRecord::TestCase
|
5
|
+
|
6
|
+
fixtures :topics
|
7
|
+
|
8
|
+
def test_should_preserve_normal_respond_to_behaviour_and_respond_to_newly_added_method
|
9
|
+
class << Topic; self; end.send(:define_method, :method_added_for_finder_respond_to_test) { }
|
10
|
+
assert Topic.respond_to?(:method_added_for_finder_respond_to_test)
|
11
|
+
ensure
|
12
|
+
class << Topic; self; end.send(:remove_method, :method_added_for_finder_respond_to_test)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_should_preserve_normal_respond_to_behaviour_and_respond_to_standard_object_method
|
16
|
+
assert Topic.respond_to?(:to_s)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_respond_to_find_by_one_attribute_before_caching
|
20
|
+
ensure_topic_method_is_not_cached(:find_by_title)
|
21
|
+
assert Topic.respond_to?(:find_by_title)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_should_respond_to_find_all_by_one_attribute
|
25
|
+
ensure_topic_method_is_not_cached(:find_all_by_title)
|
26
|
+
assert Topic.respond_to?(:find_all_by_title)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_should_respond_to_find_all_by_two_attributes
|
30
|
+
ensure_topic_method_is_not_cached(:find_all_by_title_and_author_name)
|
31
|
+
assert Topic.respond_to?(:find_all_by_title_and_author_name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_should_respond_to_find_by_two_attributes
|
35
|
+
ensure_topic_method_is_not_cached(:find_by_title_and_author_name)
|
36
|
+
assert Topic.respond_to?(:find_by_title_and_author_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_should_respond_to_find_or_initialize_from_one_attribute
|
40
|
+
ensure_topic_method_is_not_cached(:find_or_initialize_by_title)
|
41
|
+
assert Topic.respond_to?(:find_or_initialize_by_title)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_should_respond_to_find_or_initialize_from_two_attributes
|
45
|
+
ensure_topic_method_is_not_cached(:find_or_initialize_by_title_and_author_name)
|
46
|
+
assert Topic.respond_to?(:find_or_initialize_by_title_and_author_name)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_should_respond_to_find_or_create_from_one_attribute
|
50
|
+
ensure_topic_method_is_not_cached(:find_or_create_by_title)
|
51
|
+
assert Topic.respond_to?(:find_or_create_by_title)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_should_respond_to_find_or_create_from_two_attributes
|
55
|
+
ensure_topic_method_is_not_cached(:find_or_create_by_title_and_author_name)
|
56
|
+
assert Topic.respond_to?(:find_or_create_by_title_and_author_name)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_should_not_respond_to_find_by_one_missing_attribute
|
60
|
+
assert !Topic.respond_to?(:find_by_undertitle)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_should_not_respond_to_find_by_invalid_method_syntax
|
64
|
+
assert !Topic.respond_to?(:fail_to_find_by_title)
|
65
|
+
assert !Topic.respond_to?(:find_by_title?)
|
66
|
+
assert !Topic.respond_to?(:fail_to_find_or_create_by_title)
|
67
|
+
assert !Topic.respond_to?(:find_or_create_by_title?)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def ensure_topic_method_is_not_cached(method_id)
|
73
|
+
class << Topic; self; end.send(:remove_method, method_id) if Topic.public_methods.any? { |m| m.to_s == method_id.to_s }
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -1,15 +1,18 @@
|
|
1
|
-
require
|
2
|
-
require '
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
require '
|
7
|
-
require '
|
8
|
-
require '
|
9
|
-
require '
|
10
|
-
|
11
|
-
|
12
|
-
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/author'
|
3
|
+
require 'models/comment'
|
4
|
+
require 'models/company'
|
5
|
+
require 'models/topic'
|
6
|
+
require 'models/reply'
|
7
|
+
require 'models/entrant'
|
8
|
+
require 'models/developer'
|
9
|
+
require 'models/post'
|
10
|
+
require 'models/customer'
|
11
|
+
require 'models/job'
|
12
|
+
require 'models/categorization'
|
13
|
+
|
14
|
+
class FinderTest < ActiveRecord::TestCase
|
15
|
+
fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers
|
13
16
|
|
14
17
|
def test_find
|
15
18
|
assert_equal(topics(:first).title, Topic.find(1).title)
|
@@ -40,6 +43,21 @@ class FinderTest < Test::Unit::TestCase
|
|
40
43
|
assert_raise(NoMethodError) { Topic.exists?([1,2]) }
|
41
44
|
end
|
42
45
|
|
46
|
+
def test_exists_with_aggregate_having_three_mappings
|
47
|
+
existing_address = customers(:david).address
|
48
|
+
assert Customer.exists?(:address => existing_address)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_exists_with_aggregate_having_three_mappings_with_one_difference
|
52
|
+
existing_address = customers(:david).address
|
53
|
+
assert !Customer.exists?(:address =>
|
54
|
+
Address.new(existing_address.street, existing_address.city, existing_address.country + "1"))
|
55
|
+
assert !Customer.exists?(:address =>
|
56
|
+
Address.new(existing_address.street, existing_address.city + "1", existing_address.country))
|
57
|
+
assert !Customer.exists?(:address =>
|
58
|
+
Address.new(existing_address.street + "1", existing_address.city, existing_address.country))
|
59
|
+
end
|
60
|
+
|
43
61
|
def test_find_by_array_of_one_id
|
44
62
|
assert_kind_of(Array, Topic.find([ 1 ]))
|
45
63
|
assert_equal(1, Topic.find([ 1 ]).length)
|
@@ -127,6 +145,14 @@ class FinderTest < Test::Unit::TestCase
|
|
127
145
|
first = Topic.find(:first, :conditions => "title = 'The First Topic!'")
|
128
146
|
assert_nil(first)
|
129
147
|
end
|
148
|
+
|
149
|
+
def test_first
|
150
|
+
assert_equal topics(:second).title, Topic.first(:conditions => "title = 'The Second Topic of the day'").title
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_first_failing
|
154
|
+
assert_nil Topic.first(:conditions => "title = 'The Second Topic of the day!'")
|
155
|
+
end
|
130
156
|
|
131
157
|
def test_unexisting_record_exception_handling
|
132
158
|
assert_raises(ActiveRecord::RecordNotFound) {
|
@@ -145,13 +171,13 @@ class FinderTest < Test::Unit::TestCase
|
|
145
171
|
assert topic.attribute_present?("author_name")
|
146
172
|
assert topic.respond_to?("author_name")
|
147
173
|
end
|
148
|
-
|
174
|
+
|
149
175
|
def test_find_on_blank_conditions
|
150
176
|
[nil, " ", [], {}].each do |blank|
|
151
177
|
assert_nothing_raised { Topic.find(:first, :conditions => blank) }
|
152
178
|
end
|
153
179
|
end
|
154
|
-
|
180
|
+
|
155
181
|
def test_find_on_blank_bind_conditions
|
156
182
|
[ [""], ["",{}] ].each do |blank|
|
157
183
|
assert_nothing_raised { Topic.find(:first, :conditions => blank) }
|
@@ -173,6 +199,14 @@ class FinderTest < Test::Unit::TestCase
|
|
173
199
|
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { 'topics.approved' => true }) }
|
174
200
|
end
|
175
201
|
|
202
|
+
def test_find_on_hash_conditions_with_explicit_table_name_and_aggregate
|
203
|
+
david = customers(:david)
|
204
|
+
assert Customer.find(david.id, :conditions => { 'customers.name' => david.name, :address => david.address })
|
205
|
+
assert_raises(ActiveRecord::RecordNotFound) {
|
206
|
+
Customer.find(david.id, :conditions => { 'customers.name' => david.name + "1", :address => david.address })
|
207
|
+
}
|
208
|
+
end
|
209
|
+
|
176
210
|
def test_find_on_association_proxy_conditions
|
177
211
|
assert_equal [1, 2, 3, 5, 6, 7, 8, 9, 10], Comment.find_all_by_post_id(authors(:david).posts).map(&:id).sort
|
178
212
|
end
|
@@ -238,6 +272,48 @@ class FinderTest < Test::Unit::TestCase
|
|
238
272
|
assert_nil topic.last_read
|
239
273
|
end
|
240
274
|
|
275
|
+
def test_hash_condition_find_with_aggregate_having_one_mapping
|
276
|
+
balance = customers(:david).balance
|
277
|
+
assert_kind_of Money, balance
|
278
|
+
found_customer = Customer.find(:first, :conditions => {:balance => balance})
|
279
|
+
assert_equal customers(:david), found_customer
|
280
|
+
end
|
281
|
+
|
282
|
+
def test_hash_condition_find_with_aggregate_attribute_having_same_name_as_field_and_key_value_being_aggregate
|
283
|
+
gps_location = customers(:david).gps_location
|
284
|
+
assert_kind_of GpsLocation, gps_location
|
285
|
+
found_customer = Customer.find(:first, :conditions => {:gps_location => gps_location})
|
286
|
+
assert_equal customers(:david), found_customer
|
287
|
+
end
|
288
|
+
|
289
|
+
def test_hash_condition_find_with_aggregate_having_one_mapping_and_key_value_being_attribute_value
|
290
|
+
balance = customers(:david).balance
|
291
|
+
assert_kind_of Money, balance
|
292
|
+
found_customer = Customer.find(:first, :conditions => {:balance => balance.amount})
|
293
|
+
assert_equal customers(:david), found_customer
|
294
|
+
end
|
295
|
+
|
296
|
+
def test_hash_condition_find_with_aggregate_attribute_having_same_name_as_field_and_key_value_being_attribute_value
|
297
|
+
gps_location = customers(:david).gps_location
|
298
|
+
assert_kind_of GpsLocation, gps_location
|
299
|
+
found_customer = Customer.find(:first, :conditions => {:gps_location => gps_location.gps_location})
|
300
|
+
assert_equal customers(:david), found_customer
|
301
|
+
end
|
302
|
+
|
303
|
+
def test_hash_condition_find_with_aggregate_having_three_mappings
|
304
|
+
address = customers(:david).address
|
305
|
+
assert_kind_of Address, address
|
306
|
+
found_customer = Customer.find(:first, :conditions => {:address => address})
|
307
|
+
assert_equal customers(:david), found_customer
|
308
|
+
end
|
309
|
+
|
310
|
+
def test_hash_condition_find_with_one_condition_being_aggregate_and_another_not
|
311
|
+
address = customers(:david).address
|
312
|
+
assert_kind_of Address, address
|
313
|
+
found_customer = Customer.find(:first, :conditions => {:address => address, :name => customers(:david).name})
|
314
|
+
assert_equal customers(:david), found_customer
|
315
|
+
end
|
316
|
+
|
241
317
|
def test_bind_variables
|
242
318
|
assert_kind_of Firm, Company.find(:first, :conditions => ["name = ?", "37signals"])
|
243
319
|
assert_nil Company.find(:first, :conditions => ["name = ?", "37signals!"])
|
@@ -273,6 +349,8 @@ class FinderTest < Test::Unit::TestCase
|
|
273
349
|
def test_named_bind_variables
|
274
350
|
assert_equal '1', bind(':a', :a => 1) # ' ruby-mode
|
275
351
|
assert_equal '1 1', bind(':a :a', :a => 1) # ' ruby-mode
|
352
|
+
|
353
|
+
assert_nothing_raised { bind("'+00:00'", :foo => "bar") }
|
276
354
|
|
277
355
|
assert_kind_of Firm, Company.find(:first, :conditions => ["name = :name", { :name => "37signals" }])
|
278
356
|
assert_nil Company.find(:first, :conditions => ["name = :name", { :name => "37signals!" }])
|
@@ -337,18 +415,18 @@ class FinderTest < Test::Unit::TestCase
|
|
337
415
|
assert_equal topics(:first), Topic.find_by_title("The First Topic")
|
338
416
|
assert_nil Topic.find_by_title("The First Topic!")
|
339
417
|
end
|
340
|
-
|
418
|
+
|
341
419
|
def test_find_by_one_attribute_caches_dynamic_finder
|
342
420
|
# ensure this test can run independently of order
|
343
|
-
class << Topic; self; end.send(:remove_method, :find_by_title) if Topic.
|
344
|
-
assert !Topic.
|
421
|
+
class << Topic; self; end.send(:remove_method, :find_by_title) if Topic.public_methods.any? { |m| m.to_s == 'find_by_title' }
|
422
|
+
assert !Topic.public_methods.any? { |m| m.to_s == 'find_by_title' }
|
345
423
|
t = Topic.find_by_title("The First Topic")
|
346
|
-
assert Topic.
|
424
|
+
assert Topic.public_methods.any? { |m| m.to_s == 'find_by_title' }
|
347
425
|
end
|
348
426
|
|
349
427
|
def test_dynamic_finder_returns_same_results_after_caching
|
350
428
|
# ensure this test can run independently of order
|
351
|
-
class << Topic; self; end.send(:remove_method, :find_by_title) if Topic.
|
429
|
+
class << Topic; self; end.send(:remove_method, :find_by_title) if Topic.public_method_defined?(:find_by_title)
|
352
430
|
t = Topic.find_by_title("The First Topic")
|
353
431
|
assert_equal t, Topic.find_by_title("The First Topic") # find_by_title has been cached
|
354
432
|
end
|
@@ -362,17 +440,51 @@ class FinderTest < Test::Unit::TestCase
|
|
362
440
|
assert_equal accounts(:rails_core_account), Account.find_by_credit_limit(50, :conditions => ['firm_id = ?', 6])
|
363
441
|
end
|
364
442
|
|
443
|
+
def test_find_by_one_attribute_that_is_an_aggregate
|
444
|
+
address = customers(:david).address
|
445
|
+
assert_kind_of Address, address
|
446
|
+
found_customer = Customer.find_by_address(address)
|
447
|
+
assert_equal customers(:david), found_customer
|
448
|
+
end
|
449
|
+
|
450
|
+
def test_find_by_one_attribute_that_is_an_aggregate_with_one_attribute_difference
|
451
|
+
address = customers(:david).address
|
452
|
+
assert_kind_of Address, address
|
453
|
+
missing_address = Address.new(address.street, address.city, address.country + "1")
|
454
|
+
assert_nil Customer.find_by_address(missing_address)
|
455
|
+
missing_address = Address.new(address.street, address.city + "1", address.country)
|
456
|
+
assert_nil Customer.find_by_address(missing_address)
|
457
|
+
missing_address = Address.new(address.street + "1", address.city, address.country)
|
458
|
+
assert_nil Customer.find_by_address(missing_address)
|
459
|
+
end
|
460
|
+
|
461
|
+
def test_find_by_two_attributes_that_are_both_aggregates
|
462
|
+
balance = customers(:david).balance
|
463
|
+
address = customers(:david).address
|
464
|
+
assert_kind_of Money, balance
|
465
|
+
assert_kind_of Address, address
|
466
|
+
found_customer = Customer.find_by_balance_and_address(balance, address)
|
467
|
+
assert_equal customers(:david), found_customer
|
468
|
+
end
|
469
|
+
|
470
|
+
def test_find_by_two_attributes_with_one_being_an_aggregate
|
471
|
+
balance = customers(:david).balance
|
472
|
+
assert_kind_of Money, balance
|
473
|
+
found_customer = Customer.find_by_balance_and_name(balance, customers(:david).name)
|
474
|
+
assert_equal customers(:david), found_customer
|
475
|
+
end
|
476
|
+
|
365
477
|
def test_dynamic_finder_on_one_attribute_with_conditions_caches_method
|
366
478
|
# ensure this test can run independently of order
|
367
|
-
class << Account; self; end.send(:remove_method, :find_by_credit_limit) if Account.
|
368
|
-
assert !Account.
|
479
|
+
class << Account; self; end.send(:remove_method, :find_by_credit_limit) if Account.public_methods.any? { |m| m.to_s == 'find_by_credit_limit' }
|
480
|
+
assert !Account.public_methods.any? { |m| m.to_s == 'find_by_credit_limit' }
|
369
481
|
a = Account.find_by_credit_limit(50, :conditions => ['firm_id = ?', 6])
|
370
|
-
assert Account.
|
482
|
+
assert Account.public_methods.any? { |m| m.to_s == 'find_by_credit_limit' }
|
371
483
|
end
|
372
484
|
|
373
485
|
def test_dynamic_finder_on_one_attribute_with_conditions_returns_same_results_after_caching
|
374
486
|
# ensure this test can run independently of order
|
375
|
-
class << Account; self; end.send(:remove_method, :find_by_credit_limit) if Account.
|
487
|
+
class << Account; self; end.send(:remove_method, :find_by_credit_limit) if Account.public_methods.any? { |m| m.to_s == 'find_by_credit_limit' }
|
376
488
|
a = Account.find_by_credit_limit(50, :conditions => ['firm_id = ?', 6])
|
377
489
|
assert_equal a, Account.find_by_credit_limit(50, :conditions => ['firm_id = ?', 6]) # find_by_credit_limit has been cached
|
378
490
|
end
|
@@ -405,6 +517,32 @@ class FinderTest < Test::Unit::TestCase
|
|
405
517
|
assert_equal [], Topic.find_all_by_title("The First Topic!!")
|
406
518
|
end
|
407
519
|
|
520
|
+
def test_find_all_by_one_attribute_that_is_an_aggregate
|
521
|
+
balance = customers(:david).balance
|
522
|
+
assert_kind_of Money, balance
|
523
|
+
found_customers = Customer.find_all_by_balance(balance)
|
524
|
+
assert_equal 1, found_customers.size
|
525
|
+
assert_equal customers(:david), found_customers.first
|
526
|
+
end
|
527
|
+
|
528
|
+
def test_find_all_by_two_attributes_that_are_both_aggregates
|
529
|
+
balance = customers(:david).balance
|
530
|
+
address = customers(:david).address
|
531
|
+
assert_kind_of Money, balance
|
532
|
+
assert_kind_of Address, address
|
533
|
+
found_customers = Customer.find_all_by_balance_and_address(balance, address)
|
534
|
+
assert_equal 1, found_customers.size
|
535
|
+
assert_equal customers(:david), found_customers.first
|
536
|
+
end
|
537
|
+
|
538
|
+
def test_find_all_by_two_attributes_with_one_being_an_aggregate
|
539
|
+
balance = customers(:david).balance
|
540
|
+
assert_kind_of Money, balance
|
541
|
+
found_customers = Customer.find_all_by_balance_and_name(balance, customers(:david).name)
|
542
|
+
assert_equal 1, found_customers.size
|
543
|
+
assert_equal customers(:david), found_customers.first
|
544
|
+
end
|
545
|
+
|
408
546
|
def test_find_all_by_one_attribute_with_options
|
409
547
|
topics = Topic.find_all_by_content("Have a nice day", :order => "id DESC")
|
410
548
|
assert topics(:first), topics.last
|
@@ -414,7 +552,7 @@ class FinderTest < Test::Unit::TestCase
|
|
414
552
|
end
|
415
553
|
|
416
554
|
def test_find_all_by_array_attribute
|
417
|
-
assert_equal 2, Topic.find_all_by_title(["The First Topic", "The Second Topic
|
555
|
+
assert_equal 2, Topic.find_all_by_title(["The First Topic", "The Second Topic of the day"]).size
|
418
556
|
end
|
419
557
|
|
420
558
|
def test_find_all_by_boolean_attribute
|
@@ -423,7 +561,7 @@ class FinderTest < Test::Unit::TestCase
|
|
423
561
|
assert topics.include?(topics(:first))
|
424
562
|
|
425
563
|
topics = Topic.find_all_by_approved(true)
|
426
|
-
assert_equal
|
564
|
+
assert_equal 3, topics.size
|
427
565
|
assert topics.include?(topics(:second))
|
428
566
|
end
|
429
567
|
|
@@ -435,8 +573,8 @@ class FinderTest < Test::Unit::TestCase
|
|
435
573
|
|
436
574
|
def test_find_all_by_nil_attribute
|
437
575
|
topics = Topic.find_all_by_last_read nil
|
438
|
-
assert_equal
|
439
|
-
|
576
|
+
assert_equal 3, topics.size
|
577
|
+
assert topics.collect(&:last_read).all?(&:nil?)
|
440
578
|
end
|
441
579
|
|
442
580
|
def test_find_by_nil_and_not_nil_attributes
|
@@ -466,6 +604,14 @@ class FinderTest < Test::Unit::TestCase
|
|
466
604
|
assert !another.new_record?
|
467
605
|
end
|
468
606
|
|
607
|
+
def test_find_or_create_from_two_attributes_with_one_being_an_aggregate
|
608
|
+
number_of_customers = Customer.count
|
609
|
+
created_customer = Customer.find_or_create_by_balance_and_name(Money.new(123), "Elizabeth")
|
610
|
+
assert_equal number_of_customers + 1, Customer.count
|
611
|
+
assert_equal created_customer, Customer.find_or_create_by_balance(Money.new(123), "Elizabeth")
|
612
|
+
assert !created_customer.new_record?
|
613
|
+
end
|
614
|
+
|
469
615
|
def test_find_or_create_from_one_attribute_and_hash
|
470
616
|
number_of_companies = Company.count
|
471
617
|
sig38 = Company.find_or_create_by_name({:name => "38signals", :firm_id => 17, :client_of => 23})
|
@@ -477,18 +623,60 @@ class FinderTest < Test::Unit::TestCase
|
|
477
623
|
assert_equal 23, sig38.client_of
|
478
624
|
end
|
479
625
|
|
626
|
+
def test_find_or_create_from_one_aggregate_attribute
|
627
|
+
number_of_customers = Customer.count
|
628
|
+
created_customer = Customer.find_or_create_by_balance(Money.new(123))
|
629
|
+
assert_equal number_of_customers + 1, Customer.count
|
630
|
+
assert_equal created_customer, Customer.find_or_create_by_balance(Money.new(123))
|
631
|
+
assert !created_customer.new_record?
|
632
|
+
end
|
633
|
+
|
634
|
+
def test_find_or_create_from_one_aggregate_attribute_and_hash
|
635
|
+
number_of_customers = Customer.count
|
636
|
+
balance = Money.new(123)
|
637
|
+
name = "Elizabeth"
|
638
|
+
created_customer = Customer.find_or_create_by_balance({:balance => balance, :name => name})
|
639
|
+
assert_equal number_of_customers + 1, Customer.count
|
640
|
+
assert_equal created_customer, Customer.find_or_create_by_balance({:balance => balance, :name => name})
|
641
|
+
assert !created_customer.new_record?
|
642
|
+
assert_equal balance, created_customer.balance
|
643
|
+
assert_equal name, created_customer.name
|
644
|
+
end
|
645
|
+
|
480
646
|
def test_find_or_initialize_from_one_attribute
|
481
647
|
sig38 = Company.find_or_initialize_by_name("38signals")
|
482
648
|
assert_equal "38signals", sig38.name
|
483
649
|
assert sig38.new_record?
|
484
650
|
end
|
485
|
-
|
651
|
+
|
652
|
+
def test_find_or_initialize_from_one_aggregate_attribute
|
653
|
+
new_customer = Customer.find_or_initialize_by_balance(Money.new(123))
|
654
|
+
assert_equal 123, new_customer.balance.amount
|
655
|
+
assert new_customer.new_record?
|
656
|
+
end
|
657
|
+
|
658
|
+
def test_find_or_initialize_from_one_attribute_should_not_set_attribute_even_when_protected
|
659
|
+
c = Company.find_or_initialize_by_name({:name => "Fortune 1000", :rating => 1000})
|
660
|
+
assert_equal "Fortune 1000", c.name
|
661
|
+
assert_not_equal 1000, c.rating
|
662
|
+
assert c.valid?
|
663
|
+
assert c.new_record?
|
664
|
+
end
|
665
|
+
|
666
|
+
def test_find_or_create_from_one_attribute_should_set_not_attribute_even_when_protected
|
667
|
+
c = Company.find_or_create_by_name({:name => "Fortune 1000", :rating => 1000})
|
668
|
+
assert_equal "Fortune 1000", c.name
|
669
|
+
assert_not_equal 1000, c.rating
|
670
|
+
assert c.valid?
|
671
|
+
assert !c.new_record?
|
672
|
+
end
|
673
|
+
|
486
674
|
def test_find_or_initialize_from_one_attribute_should_set_attribute_even_when_protected
|
487
675
|
c = Company.find_or_initialize_by_name_and_rating("Fortune 1000", 1000)
|
488
676
|
assert_equal "Fortune 1000", c.name
|
489
677
|
assert_equal 1000, c.rating
|
490
678
|
assert c.valid?
|
491
|
-
assert c.new_record?
|
679
|
+
assert c.new_record?
|
492
680
|
end
|
493
681
|
|
494
682
|
def test_find_or_create_from_one_attribute_should_set_attribute_even_when_protected
|
@@ -496,14 +684,30 @@ class FinderTest < Test::Unit::TestCase
|
|
496
684
|
assert_equal "Fortune 1000", c.name
|
497
685
|
assert_equal 1000, c.rating
|
498
686
|
assert c.valid?
|
499
|
-
assert !c.new_record?
|
687
|
+
assert !c.new_record?
|
688
|
+
end
|
689
|
+
|
690
|
+
def test_find_or_initialize_should_set_protected_attributes_if_given_as_block
|
691
|
+
c = Company.find_or_initialize_by_name(:name => "Fortune 1000") { |f| f.rating = 1000 }
|
692
|
+
assert_equal "Fortune 1000", c.name
|
693
|
+
assert_equal 1000.to_f, c.rating.to_f
|
694
|
+
assert c.valid?
|
695
|
+
assert c.new_record?
|
500
696
|
end
|
501
697
|
|
698
|
+
def test_find_or_create_should_set_protected_attributes_if_given_as_block
|
699
|
+
c = Company.find_or_create_by_name(:name => "Fortune 1000") { |f| f.rating = 1000 }
|
700
|
+
assert_equal "Fortune 1000", c.name
|
701
|
+
assert_equal 1000.to_f, c.rating.to_f
|
702
|
+
assert c.valid?
|
703
|
+
assert !c.new_record?
|
704
|
+
end
|
705
|
+
|
502
706
|
def test_dynamic_find_or_initialize_from_one_attribute_caches_method
|
503
|
-
class << Company; self; end.send(:remove_method, :find_or_initialize_by_name) if Company.
|
504
|
-
assert !Company.
|
707
|
+
class << Company; self; end.send(:remove_method, :find_or_initialize_by_name) if Company.public_methods.any? { |m| m.to_s == 'find_or_initialize_by_name' }
|
708
|
+
assert !Company.public_methods.any? { |m| m.to_s == 'find_or_initialize_by_name' }
|
505
709
|
sig38 = Company.find_or_initialize_by_name("38signals")
|
506
|
-
assert Company.
|
710
|
+
assert Company.public_methods.any? { |m| m.to_s == 'find_or_initialize_by_name' }
|
507
711
|
end
|
508
712
|
|
509
713
|
def test_find_or_initialize_from_two_attributes
|
@@ -513,6 +717,13 @@ class FinderTest < Test::Unit::TestCase
|
|
513
717
|
assert another.new_record?
|
514
718
|
end
|
515
719
|
|
720
|
+
def test_find_or_initialize_from_one_aggregate_attribute_and_one_not
|
721
|
+
new_customer = Customer.find_or_initialize_by_balance_and_name(Money.new(123), "Elizabeth")
|
722
|
+
assert_equal 123, new_customer.balance.amount
|
723
|
+
assert_equal "Elizabeth", new_customer.name
|
724
|
+
assert new_customer.new_record?
|
725
|
+
end
|
726
|
+
|
516
727
|
def test_find_or_initialize_from_one_attribute_and_hash
|
517
728
|
sig38 = Company.find_or_initialize_by_name({:name => "38signals", :firm_id => 17, :client_of => 23})
|
518
729
|
assert_equal "38signals", sig38.name
|
@@ -521,6 +732,15 @@ class FinderTest < Test::Unit::TestCase
|
|
521
732
|
assert sig38.new_record?
|
522
733
|
end
|
523
734
|
|
735
|
+
def test_find_or_initialize_from_one_aggregate_attribute_and_hash
|
736
|
+
balance = Money.new(123)
|
737
|
+
name = "Elizabeth"
|
738
|
+
new_customer = Customer.find_or_initialize_by_balance({:balance => balance, :name => name})
|
739
|
+
assert_equal balance, new_customer.balance
|
740
|
+
assert_equal name, new_customer.name
|
741
|
+
assert new_customer.new_record?
|
742
|
+
end
|
743
|
+
|
524
744
|
def test_find_with_bad_sql
|
525
745
|
assert_raises(ActiveRecord::StatementInvalid) { Topic.find_by_sql "select 1 from badtable" }
|
526
746
|
end
|
@@ -639,6 +859,19 @@ class FinderTest < Test::Unit::TestCase
|
|
639
859
|
Company.connection.select_rows("SELECT id, name FROM companies WHERE id IN (1,2,3) ORDER BY id").map! {|i| i.map! {|j| j.to_s unless j.nil?}}
|
640
860
|
end
|
641
861
|
|
862
|
+
def test_find_with_order_on_included_associations_with_construct_finder_sql_for_association_limiting_and_is_distinct
|
863
|
+
assert_equal 2, Post.find(:all, :include => { :authors => :author_address }, :order => ' author_addresses.id DESC ', :limit => 2).size
|
864
|
+
|
865
|
+
assert_equal 3, Post.find(:all, :include => { :author => :author_address, :authors => :author_address},
|
866
|
+
:order => ' author_addresses_authors.id DESC ', :limit => 3).size
|
867
|
+
end
|
868
|
+
|
869
|
+
def test_with_limiting_with_custom_select
|
870
|
+
posts = Post.find(:all, :include => :author, :select => ' posts.*, authors.id as "author_id"', :limit => 3, :order => 'posts.id')
|
871
|
+
assert_equal 3, posts.size
|
872
|
+
assert_equal [0, 1, 1], posts.map(&:author_id).sort
|
873
|
+
end
|
874
|
+
|
642
875
|
protected
|
643
876
|
def bind(statement, *vars)
|
644
877
|
if vars.first.is_a?(Hash)
|