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,16 +1,16 @@
|
|
1
|
-
require
|
2
|
-
require '
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require '
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/post'
|
3
|
+
require 'models/comment'
|
4
|
+
require 'models/project'
|
5
|
+
require 'models/developer'
|
6
6
|
|
7
|
-
class AssociationsExtensionsTest <
|
7
|
+
class AssociationsExtensionsTest < ActiveRecord::TestCase
|
8
8
|
fixtures :projects, :developers, :developers_projects, :comments, :posts
|
9
9
|
|
10
10
|
def test_extension_on_has_many
|
11
11
|
assert_equal comments(:more_greetings), posts(:welcome).comments.find_most_recent
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def test_extension_on_habtm
|
15
15
|
assert_equal projects(:action_controller), developers(:david).projects.find_most_recent
|
16
16
|
end
|
@@ -44,4 +44,4 @@ class AssociationsExtensionsTest < Test::Unit::TestCase
|
|
44
44
|
david = Marshal.load(Marshal.dump(david))
|
45
45
|
assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
|
46
46
|
end
|
47
|
-
end
|
47
|
+
end
|
@@ -0,0 +1,684 @@
|
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/developer'
|
3
|
+
require 'models/project'
|
4
|
+
require 'models/company'
|
5
|
+
require 'models/topic'
|
6
|
+
require 'models/reply'
|
7
|
+
require 'models/computer'
|
8
|
+
require 'models/customer'
|
9
|
+
require 'models/order'
|
10
|
+
require 'models/categorization'
|
11
|
+
require 'models/category'
|
12
|
+
require 'models/post'
|
13
|
+
require 'models/author'
|
14
|
+
require 'models/comment'
|
15
|
+
require 'models/tag'
|
16
|
+
require 'models/tagging'
|
17
|
+
require 'models/person'
|
18
|
+
require 'models/reader'
|
19
|
+
require 'models/parrot'
|
20
|
+
require 'models/pirate'
|
21
|
+
require 'models/treasure'
|
22
|
+
require 'models/price_estimate'
|
23
|
+
require 'models/club'
|
24
|
+
require 'models/member'
|
25
|
+
require 'models/membership'
|
26
|
+
require 'models/sponsor'
|
27
|
+
|
28
|
+
class ProjectWithAfterCreateHook < ActiveRecord::Base
|
29
|
+
set_table_name 'projects'
|
30
|
+
has_and_belongs_to_many :developers,
|
31
|
+
:class_name => "DeveloperForProjectWithAfterCreateHook",
|
32
|
+
:join_table => "developers_projects",
|
33
|
+
:foreign_key => "project_id",
|
34
|
+
:association_foreign_key => "developer_id"
|
35
|
+
|
36
|
+
after_create :add_david
|
37
|
+
|
38
|
+
def add_david
|
39
|
+
david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
|
40
|
+
david.projects << self
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class DeveloperForProjectWithAfterCreateHook < ActiveRecord::Base
|
45
|
+
set_table_name 'developers'
|
46
|
+
has_and_belongs_to_many :projects,
|
47
|
+
:class_name => "ProjectWithAfterCreateHook",
|
48
|
+
:join_table => "developers_projects",
|
49
|
+
:association_foreign_key => "project_id",
|
50
|
+
:foreign_key => "developer_id"
|
51
|
+
end
|
52
|
+
|
53
|
+
class ProjectWithSymbolsForKeys < ActiveRecord::Base
|
54
|
+
set_table_name 'projects'
|
55
|
+
has_and_belongs_to_many :developers,
|
56
|
+
:class_name => "DeveloperWithSymbolsForKeys",
|
57
|
+
:join_table => :developers_projects,
|
58
|
+
:foreign_key => :project_id,
|
59
|
+
:association_foreign_key => "developer_id"
|
60
|
+
end
|
61
|
+
|
62
|
+
class DeveloperWithSymbolsForKeys < ActiveRecord::Base
|
63
|
+
set_table_name 'developers'
|
64
|
+
has_and_belongs_to_many :projects,
|
65
|
+
:class_name => "ProjectWithSymbolsForKeys",
|
66
|
+
:join_table => :developers_projects,
|
67
|
+
:association_foreign_key => :project_id,
|
68
|
+
:foreign_key => "developer_id"
|
69
|
+
end
|
70
|
+
|
71
|
+
class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
|
72
|
+
fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects,
|
73
|
+
:parrots, :pirates, :treasures, :price_estimates
|
74
|
+
|
75
|
+
def test_has_and_belongs_to_many
|
76
|
+
david = Developer.find(1)
|
77
|
+
|
78
|
+
assert !david.projects.empty?
|
79
|
+
assert_equal 2, david.projects.size
|
80
|
+
|
81
|
+
active_record = Project.find(1)
|
82
|
+
assert !active_record.developers.empty?
|
83
|
+
assert_equal 3, active_record.developers.size
|
84
|
+
assert active_record.developers.include?(david)
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_triple_equality
|
88
|
+
assert !(Array === Developer.find(1).projects)
|
89
|
+
assert Developer.find(1).projects === Array
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_adding_single
|
93
|
+
jamis = Developer.find(2)
|
94
|
+
jamis.projects.reload # causing the collection to load
|
95
|
+
action_controller = Project.find(2)
|
96
|
+
assert_equal 1, jamis.projects.size
|
97
|
+
assert_equal 1, action_controller.developers.size
|
98
|
+
|
99
|
+
jamis.projects << action_controller
|
100
|
+
|
101
|
+
assert_equal 2, jamis.projects.size
|
102
|
+
assert_equal 2, jamis.projects(true).size
|
103
|
+
assert_equal 2, action_controller.developers(true).size
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_adding_type_mismatch
|
107
|
+
jamis = Developer.find(2)
|
108
|
+
assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << nil }
|
109
|
+
assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << 1 }
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_adding_from_the_project
|
113
|
+
jamis = Developer.find(2)
|
114
|
+
action_controller = Project.find(2)
|
115
|
+
action_controller.developers.reload
|
116
|
+
assert_equal 1, jamis.projects.size
|
117
|
+
assert_equal 1, action_controller.developers.size
|
118
|
+
|
119
|
+
action_controller.developers << jamis
|
120
|
+
|
121
|
+
assert_equal 2, jamis.projects(true).size
|
122
|
+
assert_equal 2, action_controller.developers.size
|
123
|
+
assert_equal 2, action_controller.developers(true).size
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_adding_from_the_project_fixed_timestamp
|
127
|
+
jamis = Developer.find(2)
|
128
|
+
action_controller = Project.find(2)
|
129
|
+
action_controller.developers.reload
|
130
|
+
assert_equal 1, jamis.projects.size
|
131
|
+
assert_equal 1, action_controller.developers.size
|
132
|
+
updated_at = jamis.updated_at
|
133
|
+
|
134
|
+
action_controller.developers << jamis
|
135
|
+
|
136
|
+
assert_equal updated_at, jamis.updated_at
|
137
|
+
assert_equal 2, jamis.projects(true).size
|
138
|
+
assert_equal 2, action_controller.developers.size
|
139
|
+
assert_equal 2, action_controller.developers(true).size
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_adding_multiple
|
143
|
+
aredridel = Developer.new("name" => "Aredridel")
|
144
|
+
aredridel.save
|
145
|
+
aredridel.projects.reload
|
146
|
+
aredridel.projects.push(Project.find(1), Project.find(2))
|
147
|
+
assert_equal 2, aredridel.projects.size
|
148
|
+
assert_equal 2, aredridel.projects(true).size
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_adding_a_collection
|
152
|
+
aredridel = Developer.new("name" => "Aredridel")
|
153
|
+
aredridel.save
|
154
|
+
aredridel.projects.reload
|
155
|
+
aredridel.projects.concat([Project.find(1), Project.find(2)])
|
156
|
+
assert_equal 2, aredridel.projects.size
|
157
|
+
assert_equal 2, aredridel.projects(true).size
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_adding_uses_default_values_on_join_table
|
161
|
+
ac = projects(:action_controller)
|
162
|
+
assert !developers(:jamis).projects.include?(ac)
|
163
|
+
developers(:jamis).projects << ac
|
164
|
+
|
165
|
+
assert developers(:jamis, :reload).projects.include?(ac)
|
166
|
+
project = developers(:jamis).projects.detect { |p| p == ac }
|
167
|
+
assert_equal 1, project.access_level.to_i
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_habtm_attribute_access_and_respond_to
|
171
|
+
project = developers(:jamis).projects[0]
|
172
|
+
assert project.has_attribute?("name")
|
173
|
+
assert project.has_attribute?("joined_on")
|
174
|
+
assert project.has_attribute?("access_level")
|
175
|
+
assert project.respond_to?("name")
|
176
|
+
assert project.respond_to?("name=")
|
177
|
+
assert project.respond_to?("name?")
|
178
|
+
assert project.respond_to?("joined_on")
|
179
|
+
# given that the 'join attribute' won't be persisted, I don't
|
180
|
+
# think we should define the mutators
|
181
|
+
#assert project.respond_to?("joined_on=")
|
182
|
+
assert project.respond_to?("joined_on?")
|
183
|
+
assert project.respond_to?("access_level")
|
184
|
+
#assert project.respond_to?("access_level=")
|
185
|
+
assert project.respond_to?("access_level?")
|
186
|
+
end
|
187
|
+
|
188
|
+
def test_habtm_adding_before_save
|
189
|
+
no_of_devels = Developer.count
|
190
|
+
no_of_projects = Project.count
|
191
|
+
aredridel = Developer.new("name" => "Aredridel")
|
192
|
+
aredridel.projects.concat([Project.find(1), p = Project.new("name" => "Projekt")])
|
193
|
+
assert aredridel.new_record?
|
194
|
+
assert p.new_record?
|
195
|
+
assert aredridel.save
|
196
|
+
assert !aredridel.new_record?
|
197
|
+
assert_equal no_of_devels+1, Developer.count
|
198
|
+
assert_equal no_of_projects+1, Project.count
|
199
|
+
assert_equal 2, aredridel.projects.size
|
200
|
+
assert_equal 2, aredridel.projects(true).size
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_habtm_saving_multiple_relationships
|
204
|
+
new_project = Project.new("name" => "Grimetime")
|
205
|
+
amount_of_developers = 4
|
206
|
+
developers = (0...amount_of_developers).collect {|i| Developer.create(:name => "JME #{i}") }.reverse
|
207
|
+
|
208
|
+
new_project.developer_ids = [developers[0].id, developers[1].id]
|
209
|
+
new_project.developers_with_callback_ids = [developers[2].id, developers[3].id]
|
210
|
+
assert new_project.save
|
211
|
+
|
212
|
+
new_project.reload
|
213
|
+
assert_equal amount_of_developers, new_project.developers.size
|
214
|
+
assert_equal developers, new_project.developers
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_habtm_unique_order_preserved
|
218
|
+
assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).non_unique_developers
|
219
|
+
assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).developers
|
220
|
+
end
|
221
|
+
|
222
|
+
def test_build
|
223
|
+
devel = Developer.find(1)
|
224
|
+
proj = assert_no_queries { devel.projects.build("name" => "Projekt") }
|
225
|
+
assert !devel.projects.loaded?
|
226
|
+
|
227
|
+
assert_equal devel.projects.last, proj
|
228
|
+
assert devel.projects.loaded?
|
229
|
+
|
230
|
+
assert proj.new_record?
|
231
|
+
devel.save
|
232
|
+
assert !proj.new_record?
|
233
|
+
assert_equal devel.projects.last, proj
|
234
|
+
assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
|
235
|
+
end
|
236
|
+
|
237
|
+
def test_build_by_new_record
|
238
|
+
devel = Developer.new(:name => "Marcel", :salary => 75000)
|
239
|
+
proj1 = devel.projects.build(:name => "Make bed")
|
240
|
+
proj2 = devel.projects.build(:name => "Lie in it")
|
241
|
+
assert_equal devel.projects.last, proj2
|
242
|
+
assert proj2.new_record?
|
243
|
+
devel.save
|
244
|
+
assert !devel.new_record?
|
245
|
+
assert !proj2.new_record?
|
246
|
+
assert_equal devel.projects.last, proj2
|
247
|
+
assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
|
248
|
+
end
|
249
|
+
|
250
|
+
def test_create
|
251
|
+
devel = Developer.find(1)
|
252
|
+
proj = devel.projects.create("name" => "Projekt")
|
253
|
+
assert !devel.projects.loaded?
|
254
|
+
|
255
|
+
assert_equal devel.projects.last, proj
|
256
|
+
assert devel.projects.loaded?
|
257
|
+
|
258
|
+
assert !proj.new_record?
|
259
|
+
assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
|
260
|
+
end
|
261
|
+
|
262
|
+
def test_create_by_new_record
|
263
|
+
devel = Developer.new(:name => "Marcel", :salary => 75000)
|
264
|
+
proj1 = devel.projects.build(:name => "Make bed")
|
265
|
+
proj2 = devel.projects.build(:name => "Lie in it")
|
266
|
+
assert_equal devel.projects.last, proj2
|
267
|
+
assert proj2.new_record?
|
268
|
+
devel.save
|
269
|
+
assert !devel.new_record?
|
270
|
+
assert !proj2.new_record?
|
271
|
+
assert_equal devel.projects.last, proj2
|
272
|
+
assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
|
273
|
+
end
|
274
|
+
|
275
|
+
def test_creation_respects_hash_condition
|
276
|
+
post = categories(:general).post_with_conditions.build(:body => '')
|
277
|
+
|
278
|
+
assert post.save
|
279
|
+
assert_equal 'Yet Another Testing Title', post.title
|
280
|
+
|
281
|
+
another_post = categories(:general).post_with_conditions.create(:body => '')
|
282
|
+
|
283
|
+
assert !another_post.new_record?
|
284
|
+
assert_equal 'Yet Another Testing Title', another_post.title
|
285
|
+
end
|
286
|
+
|
287
|
+
def test_uniq_after_the_fact
|
288
|
+
dev = developers(:jamis)
|
289
|
+
dev.projects << projects(:active_record)
|
290
|
+
dev.projects << projects(:active_record)
|
291
|
+
|
292
|
+
assert_equal 3, dev.projects.size
|
293
|
+
assert_equal 1, dev.projects.uniq.size
|
294
|
+
end
|
295
|
+
|
296
|
+
def test_uniq_before_the_fact
|
297
|
+
projects(:active_record).developers << developers(:jamis)
|
298
|
+
projects(:active_record).developers << developers(:david)
|
299
|
+
assert_equal 3, projects(:active_record, :reload).developers.size
|
300
|
+
end
|
301
|
+
|
302
|
+
def test_deleting
|
303
|
+
david = Developer.find(1)
|
304
|
+
active_record = Project.find(1)
|
305
|
+
david.projects.reload
|
306
|
+
assert_equal 2, david.projects.size
|
307
|
+
assert_equal 3, active_record.developers.size
|
308
|
+
|
309
|
+
david.projects.delete(active_record)
|
310
|
+
|
311
|
+
assert_equal 1, david.projects.size
|
312
|
+
assert_equal 1, david.projects(true).size
|
313
|
+
assert_equal 2, active_record.developers(true).size
|
314
|
+
end
|
315
|
+
|
316
|
+
def test_deleting_array
|
317
|
+
david = Developer.find(1)
|
318
|
+
david.projects.reload
|
319
|
+
david.projects.delete(Project.find(:all))
|
320
|
+
assert_equal 0, david.projects.size
|
321
|
+
assert_equal 0, david.projects(true).size
|
322
|
+
end
|
323
|
+
|
324
|
+
def test_deleting_with_sql
|
325
|
+
david = Developer.find(1)
|
326
|
+
active_record = Project.find(1)
|
327
|
+
active_record.developers.reload
|
328
|
+
assert_equal 3, active_record.developers_by_sql.size
|
329
|
+
|
330
|
+
active_record.developers_by_sql.delete(david)
|
331
|
+
assert_equal 2, active_record.developers_by_sql(true).size
|
332
|
+
end
|
333
|
+
|
334
|
+
def test_deleting_array_with_sql
|
335
|
+
active_record = Project.find(1)
|
336
|
+
active_record.developers.reload
|
337
|
+
assert_equal 3, active_record.developers_by_sql.size
|
338
|
+
|
339
|
+
active_record.developers_by_sql.delete(Developer.find(:all))
|
340
|
+
assert_equal 0, active_record.developers_by_sql(true).size
|
341
|
+
end
|
342
|
+
|
343
|
+
def test_deleting_all
|
344
|
+
david = Developer.find(1)
|
345
|
+
david.projects.reload
|
346
|
+
david.projects.clear
|
347
|
+
assert_equal 0, david.projects.size
|
348
|
+
assert_equal 0, david.projects(true).size
|
349
|
+
end
|
350
|
+
|
351
|
+
def test_removing_associations_on_destroy
|
352
|
+
david = DeveloperWithBeforeDestroyRaise.find(1)
|
353
|
+
assert !david.projects.empty?
|
354
|
+
assert_nothing_raised { david.destroy }
|
355
|
+
assert david.projects.empty?
|
356
|
+
assert DeveloperWithBeforeDestroyRaise.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = 1").empty?
|
357
|
+
end
|
358
|
+
|
359
|
+
def test_additional_columns_from_join_table
|
360
|
+
assert_date_from_db Date.new(2004, 10, 10), Developer.find(1).projects.first.joined_on.to_date
|
361
|
+
end
|
362
|
+
|
363
|
+
def test_destroy_all
|
364
|
+
david = Developer.find(1)
|
365
|
+
david.projects.reload
|
366
|
+
assert !david.projects.empty?
|
367
|
+
david.projects.destroy_all
|
368
|
+
assert david.projects.empty?
|
369
|
+
assert david.projects(true).empty?
|
370
|
+
end
|
371
|
+
|
372
|
+
def test_deprecated_push_with_attributes_was_removed
|
373
|
+
jamis = developers(:jamis)
|
374
|
+
assert_raise(NoMethodError) do
|
375
|
+
jamis.projects.push_with_attributes(projects(:action_controller), :joined_on => Date.today)
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
def test_associations_with_conditions
|
380
|
+
assert_equal 3, projects(:active_record).developers.size
|
381
|
+
assert_equal 1, projects(:active_record).developers_named_david.size
|
382
|
+
assert_equal 1, projects(:active_record).developers_named_david_with_hash_conditions.size
|
383
|
+
|
384
|
+
assert_equal developers(:david), projects(:active_record).developers_named_david.find(developers(:david).id)
|
385
|
+
assert_equal developers(:david), projects(:active_record).developers_named_david_with_hash_conditions.find(developers(:david).id)
|
386
|
+
assert_equal developers(:david), projects(:active_record).salaried_developers.find(developers(:david).id)
|
387
|
+
|
388
|
+
projects(:active_record).developers_named_david.clear
|
389
|
+
assert_equal 2, projects(:active_record, :reload).developers.size
|
390
|
+
end
|
391
|
+
|
392
|
+
def test_find_in_association
|
393
|
+
# Using sql
|
394
|
+
assert_equal developers(:david), projects(:active_record).developers.find(developers(:david).id), "SQL find"
|
395
|
+
|
396
|
+
# Using ruby
|
397
|
+
active_record = projects(:active_record)
|
398
|
+
active_record.developers.reload
|
399
|
+
assert_equal developers(:david), active_record.developers.find(developers(:david).id), "Ruby find"
|
400
|
+
end
|
401
|
+
|
402
|
+
def test_include_uses_array_include_after_loaded
|
403
|
+
project = projects(:active_record)
|
404
|
+
project.developers.class # force load target
|
405
|
+
|
406
|
+
developer = project.developers.first
|
407
|
+
|
408
|
+
assert_no_queries do
|
409
|
+
assert project.developers.loaded?
|
410
|
+
assert project.developers.include?(developer)
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
def test_include_checks_if_record_exists_if_target_not_loaded
|
415
|
+
project = projects(:active_record)
|
416
|
+
developer = project.developers.first
|
417
|
+
|
418
|
+
project.reload
|
419
|
+
assert ! project.developers.loaded?
|
420
|
+
assert_queries(1) do
|
421
|
+
assert project.developers.include?(developer)
|
422
|
+
end
|
423
|
+
assert ! project.developers.loaded?
|
424
|
+
end
|
425
|
+
|
426
|
+
def test_include_returns_false_for_non_matching_record_to_verify_scoping
|
427
|
+
project = projects(:active_record)
|
428
|
+
developer = Developer.create :name => "Bryan", :salary => 50_000
|
429
|
+
|
430
|
+
assert ! project.developers.loaded?
|
431
|
+
assert ! project.developers.include?(developer)
|
432
|
+
end
|
433
|
+
|
434
|
+
def test_find_in_association_with_custom_finder_sql
|
435
|
+
assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id), "SQL find"
|
436
|
+
|
437
|
+
active_record = projects(:active_record)
|
438
|
+
active_record.developers_with_finder_sql.reload
|
439
|
+
assert_equal developers(:david), active_record.developers_with_finder_sql.find(developers(:david).id), "Ruby find"
|
440
|
+
end
|
441
|
+
|
442
|
+
def test_find_in_association_with_custom_finder_sql_and_string_id
|
443
|
+
assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id.to_s), "SQL find"
|
444
|
+
end
|
445
|
+
|
446
|
+
def test_find_with_merged_options
|
447
|
+
assert_equal 1, projects(:active_record).limited_developers.size
|
448
|
+
assert_equal 1, projects(:active_record).limited_developers.find(:all).size
|
449
|
+
assert_equal 3, projects(:active_record).limited_developers.find(:all, :limit => nil).size
|
450
|
+
end
|
451
|
+
|
452
|
+
def test_dynamic_find_should_respect_association_order
|
453
|
+
# Developers are ordered 'name DESC, id DESC'
|
454
|
+
low_id_jamis = developers(:jamis)
|
455
|
+
middle_id_jamis = developers(:poor_jamis)
|
456
|
+
high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
|
457
|
+
|
458
|
+
assert_equal high_id_jamis, projects(:active_record).developers.find(:first, :conditions => "name = 'Jamis'")
|
459
|
+
assert_equal high_id_jamis, projects(:active_record).developers.find_by_name('Jamis')
|
460
|
+
end
|
461
|
+
|
462
|
+
def test_dynamic_find_order_should_override_association_order
|
463
|
+
# Developers are ordered 'name DESC, id DESC'
|
464
|
+
low_id_jamis = developers(:jamis)
|
465
|
+
middle_id_jamis = developers(:poor_jamis)
|
466
|
+
high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
|
467
|
+
|
468
|
+
assert_equal low_id_jamis, projects(:active_record).developers.find(:first, :conditions => "name = 'Jamis'", :order => 'id')
|
469
|
+
assert_equal low_id_jamis, projects(:active_record).developers.find_by_name('Jamis', :order => 'id')
|
470
|
+
end
|
471
|
+
|
472
|
+
def test_dynamic_find_all_should_respect_association_order
|
473
|
+
# Developers are ordered 'name DESC, id DESC'
|
474
|
+
low_id_jamis = developers(:jamis)
|
475
|
+
middle_id_jamis = developers(:poor_jamis)
|
476
|
+
high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
|
477
|
+
|
478
|
+
assert_equal [high_id_jamis, middle_id_jamis, low_id_jamis], projects(:active_record).developers.find(:all, :conditions => "name = 'Jamis'")
|
479
|
+
assert_equal [high_id_jamis, middle_id_jamis, low_id_jamis], projects(:active_record).developers.find_all_by_name('Jamis')
|
480
|
+
end
|
481
|
+
|
482
|
+
def test_dynamic_find_all_order_should_override_association_order
|
483
|
+
# Developers are ordered 'name DESC, id DESC'
|
484
|
+
low_id_jamis = developers(:jamis)
|
485
|
+
middle_id_jamis = developers(:poor_jamis)
|
486
|
+
high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
|
487
|
+
|
488
|
+
assert_equal [low_id_jamis, middle_id_jamis, high_id_jamis], projects(:active_record).developers.find(:all, :conditions => "name = 'Jamis'", :order => 'id')
|
489
|
+
assert_equal [low_id_jamis, middle_id_jamis, high_id_jamis], projects(:active_record).developers.find_all_by_name('Jamis', :order => 'id')
|
490
|
+
end
|
491
|
+
|
492
|
+
def test_dynamic_find_all_should_respect_association_limit
|
493
|
+
assert_equal 1, projects(:active_record).limited_developers.find(:all, :conditions => "name = 'Jamis'").length
|
494
|
+
assert_equal 1, projects(:active_record).limited_developers.find_all_by_name('Jamis').length
|
495
|
+
end
|
496
|
+
|
497
|
+
def test_dynamic_find_all_order_should_override_association_limit
|
498
|
+
assert_equal 2, projects(:active_record).limited_developers.find(:all, :conditions => "name = 'Jamis'", :limit => 9_000).length
|
499
|
+
assert_equal 2, projects(:active_record).limited_developers.find_all_by_name('Jamis', :limit => 9_000).length
|
500
|
+
end
|
501
|
+
|
502
|
+
def test_dynamic_find_all_should_respect_readonly_access
|
503
|
+
projects(:active_record).readonly_developers.each { |d| assert_raise(ActiveRecord::ReadOnlyRecord) { d.save! } if d.valid?}
|
504
|
+
projects(:active_record).readonly_developers.each { |d| d.readonly? }
|
505
|
+
end
|
506
|
+
|
507
|
+
def test_new_with_values_in_collection
|
508
|
+
jamis = DeveloperForProjectWithAfterCreateHook.find_by_name('Jamis')
|
509
|
+
david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
|
510
|
+
project = ProjectWithAfterCreateHook.new(:name => "Cooking with Bertie")
|
511
|
+
project.developers << jamis
|
512
|
+
project.save!
|
513
|
+
project.reload
|
514
|
+
|
515
|
+
assert project.developers.include?(jamis)
|
516
|
+
assert project.developers.include?(david)
|
517
|
+
end
|
518
|
+
|
519
|
+
def test_find_in_association_with_options
|
520
|
+
developers = projects(:active_record).developers.find(:all)
|
521
|
+
assert_equal 3, developers.size
|
522
|
+
|
523
|
+
assert_equal developers(:poor_jamis), projects(:active_record).developers.find(:first, :conditions => "salary < 10000")
|
524
|
+
assert_equal developers(:jamis), projects(:active_record).developers.find(:first, :order => "salary DESC")
|
525
|
+
end
|
526
|
+
|
527
|
+
def test_replace_with_less
|
528
|
+
david = developers(:david)
|
529
|
+
david.projects = [projects(:action_controller)]
|
530
|
+
assert david.save
|
531
|
+
assert_equal 1, david.projects.length
|
532
|
+
end
|
533
|
+
|
534
|
+
def test_replace_with_new
|
535
|
+
david = developers(:david)
|
536
|
+
david.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
|
537
|
+
david.save
|
538
|
+
assert_equal 2, david.projects.length
|
539
|
+
assert !david.projects.include?(projects(:active_record))
|
540
|
+
end
|
541
|
+
|
542
|
+
def test_replace_on_new_object
|
543
|
+
new_developer = Developer.new("name" => "Matz")
|
544
|
+
new_developer.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
|
545
|
+
new_developer.save
|
546
|
+
assert_equal 2, new_developer.projects.length
|
547
|
+
end
|
548
|
+
|
549
|
+
def test_consider_type
|
550
|
+
developer = Developer.find(:first)
|
551
|
+
special_project = SpecialProject.create("name" => "Special Project")
|
552
|
+
|
553
|
+
other_project = developer.projects.first
|
554
|
+
developer.special_projects << special_project
|
555
|
+
developer.reload
|
556
|
+
|
557
|
+
assert developer.projects.include?(special_project)
|
558
|
+
assert developer.special_projects.include?(special_project)
|
559
|
+
assert !developer.special_projects.include?(other_project)
|
560
|
+
end
|
561
|
+
|
562
|
+
def test_update_attributes_after_push_without_duplicate_join_table_rows
|
563
|
+
developer = Developer.new("name" => "Kano")
|
564
|
+
project = SpecialProject.create("name" => "Special Project")
|
565
|
+
assert developer.save
|
566
|
+
developer.projects << project
|
567
|
+
developer.update_attribute("name", "Bruza")
|
568
|
+
assert_equal 1, Developer.connection.select_value(<<-end_sql).to_i
|
569
|
+
SELECT count(*) FROM developers_projects
|
570
|
+
WHERE project_id = #{project.id}
|
571
|
+
AND developer_id = #{developer.id}
|
572
|
+
end_sql
|
573
|
+
end
|
574
|
+
|
575
|
+
def test_updating_attributes_on_non_rich_associations
|
576
|
+
welcome = categories(:technology).posts.first
|
577
|
+
welcome.title = "Something else"
|
578
|
+
assert welcome.save!
|
579
|
+
end
|
580
|
+
|
581
|
+
def test_habtm_respects_select
|
582
|
+
categories(:technology).select_testing_posts(true).each do |o|
|
583
|
+
assert_respond_to o, :correctness_marker
|
584
|
+
end
|
585
|
+
assert_respond_to categories(:technology).select_testing_posts.find(:first), :correctness_marker
|
586
|
+
end
|
587
|
+
|
588
|
+
def test_updating_attributes_on_rich_associations
|
589
|
+
david = projects(:action_controller).developers.first
|
590
|
+
david.name = "DHH"
|
591
|
+
assert_raises(ActiveRecord::ReadOnlyRecord) { david.save! }
|
592
|
+
end
|
593
|
+
|
594
|
+
def test_updating_attributes_on_rich_associations_with_limited_find_from_reflection
|
595
|
+
david = projects(:action_controller).selected_developers.first
|
596
|
+
david.name = "DHH"
|
597
|
+
assert_nothing_raised { david.save! }
|
598
|
+
end
|
599
|
+
|
600
|
+
|
601
|
+
def test_updating_attributes_on_rich_associations_with_limited_find
|
602
|
+
david = projects(:action_controller).developers.find(:all, :select => "developers.*").first
|
603
|
+
david.name = "DHH"
|
604
|
+
assert david.save!
|
605
|
+
end
|
606
|
+
|
607
|
+
def test_join_table_alias
|
608
|
+
assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL').size
|
609
|
+
end
|
610
|
+
|
611
|
+
def test_join_with_group
|
612
|
+
group = Developer.columns.inject([]) do |g, c|
|
613
|
+
g << "developers.#{c.name}"
|
614
|
+
g << "developers_projects_2.#{c.name}"
|
615
|
+
end
|
616
|
+
Project.columns.each { |c| group << "projects.#{c.name}" }
|
617
|
+
|
618
|
+
assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL', :group => group.join(",")).size
|
619
|
+
end
|
620
|
+
|
621
|
+
def test_get_ids
|
622
|
+
assert_equal projects(:active_record, :action_controller).map(&:id).sort, developers(:david).project_ids.sort
|
623
|
+
assert_equal [projects(:active_record).id], developers(:jamis).project_ids
|
624
|
+
end
|
625
|
+
|
626
|
+
def test_assign_ids
|
627
|
+
developer = Developer.new("name" => "Joe")
|
628
|
+
developer.project_ids = projects(:active_record, :action_controller).map(&:id)
|
629
|
+
developer.save
|
630
|
+
developer.reload
|
631
|
+
assert_equal 2, developer.projects.length
|
632
|
+
assert_equal projects(:active_record), developer.projects[0]
|
633
|
+
assert_equal projects(:action_controller), developer.projects[1]
|
634
|
+
end
|
635
|
+
|
636
|
+
def test_assign_ids_ignoring_blanks
|
637
|
+
developer = Developer.new("name" => "Joe")
|
638
|
+
developer.project_ids = [projects(:active_record).id, nil, projects(:action_controller).id, '']
|
639
|
+
developer.save
|
640
|
+
developer.reload
|
641
|
+
assert_equal 2, developer.projects.length
|
642
|
+
assert_equal projects(:active_record), developer.projects[0]
|
643
|
+
assert_equal projects(:action_controller), developer.projects[1]
|
644
|
+
end
|
645
|
+
|
646
|
+
def test_select_limited_ids_list
|
647
|
+
# Set timestamps
|
648
|
+
Developer.transaction do
|
649
|
+
Developer.find(:all, :order => 'id').each_with_index do |record, i|
|
650
|
+
record.update_attributes(:created_at => 5.years.ago + (i * 5.minutes))
|
651
|
+
end
|
652
|
+
end
|
653
|
+
|
654
|
+
join_base = ActiveRecord::Associations::ClassMethods::JoinDependency::JoinBase.new(Project)
|
655
|
+
join_dep = ActiveRecord::Associations::ClassMethods::JoinDependency.new(join_base, :developers, nil)
|
656
|
+
projects = Project.send(:select_limited_ids_list, {:order => 'developers.created_at'}, join_dep)
|
657
|
+
assert !projects.include?("'"), projects
|
658
|
+
assert_equal %w(1 2), projects.scan(/\d/).sort
|
659
|
+
end
|
660
|
+
|
661
|
+
def test_scoped_find_on_through_association_doesnt_return_read_only_records
|
662
|
+
tag = Post.find(1).tags.find_by_name("General")
|
663
|
+
|
664
|
+
assert_nothing_raised do
|
665
|
+
tag.save!
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
669
|
+
def test_has_many_through_polymorphic_has_manys_works
|
670
|
+
assert_equal [10, 20].to_set, pirates(:redbeard).treasure_estimates.map(&:price).to_set
|
671
|
+
end
|
672
|
+
|
673
|
+
def test_symbols_as_keys
|
674
|
+
developer = DeveloperWithSymbolsForKeys.new(:name => 'David')
|
675
|
+
project = ProjectWithSymbolsForKeys.new(:name => 'Rails Testing')
|
676
|
+
project.developers << developer
|
677
|
+
project.save!
|
678
|
+
|
679
|
+
assert_equal 1, project.developers.size
|
680
|
+
assert_equal 1, developer.projects.size
|
681
|
+
assert_equal developer, project.developers.find(:first)
|
682
|
+
assert_equal project, developer.projects.find(:first)
|
683
|
+
end
|
684
|
+
end
|