activerecord 1.15.6 → 2.0.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.

Files changed (185) hide show
  1. data/CHANGELOG +2454 -34
  2. data/README +1 -1
  3. data/RUNNING_UNIT_TESTS +3 -34
  4. data/Rakefile +98 -77
  5. data/install.rb +1 -1
  6. data/lib/active_record.rb +13 -22
  7. data/lib/active_record/aggregations.rb +38 -49
  8. data/lib/active_record/associations.rb +452 -333
  9. data/lib/active_record/associations/association_collection.rb +66 -20
  10. data/lib/active_record/associations/association_proxy.rb +9 -8
  11. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +46 -51
  12. data/lib/active_record/associations/has_many_association.rb +21 -57
  13. data/lib/active_record/associations/has_many_through_association.rb +38 -18
  14. data/lib/active_record/associations/has_one_association.rb +30 -14
  15. data/lib/active_record/attribute_methods.rb +253 -0
  16. data/lib/active_record/base.rb +719 -494
  17. data/lib/active_record/calculations.rb +62 -63
  18. data/lib/active_record/callbacks.rb +57 -83
  19. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +38 -9
  20. data/lib/active_record/connection_adapters/abstract/database_statements.rb +56 -15
  21. data/lib/active_record/connection_adapters/abstract/query_cache.rb +87 -0
  22. data/lib/active_record/connection_adapters/abstract/quoting.rb +23 -12
  23. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +191 -62
  24. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +37 -34
  25. data/lib/active_record/connection_adapters/abstract_adapter.rb +28 -17
  26. data/lib/active_record/connection_adapters/mysql_adapter.rb +119 -37
  27. data/lib/active_record/connection_adapters/postgresql_adapter.rb +473 -210
  28. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -0
  29. data/lib/active_record/connection_adapters/sqlite_adapter.rb +91 -107
  30. data/lib/active_record/fixtures.rb +503 -113
  31. data/lib/active_record/locking/optimistic.rb +72 -34
  32. data/lib/active_record/migration.rb +80 -57
  33. data/lib/active_record/observer.rb +13 -10
  34. data/lib/active_record/query_cache.rb +16 -57
  35. data/lib/active_record/reflection.rb +35 -38
  36. data/lib/active_record/schema.rb +5 -5
  37. data/lib/active_record/schema_dumper.rb +35 -13
  38. data/lib/active_record/serialization.rb +98 -0
  39. data/lib/active_record/serializers/json_serializer.rb +71 -0
  40. data/lib/active_record/{xml_serialization.rb → serializers/xml_serializer.rb} +90 -83
  41. data/lib/active_record/timestamp.rb +20 -21
  42. data/lib/active_record/transactions.rb +39 -43
  43. data/lib/active_record/validations.rb +256 -107
  44. data/lib/active_record/version.rb +3 -3
  45. data/lib/activerecord.rb +1 -0
  46. data/test/aaa_create_tables_test.rb +15 -2
  47. data/test/abstract_unit.rb +24 -17
  48. data/test/active_schema_test_mysql.rb +20 -8
  49. data/test/adapter_test.rb +23 -5
  50. data/test/adapter_test_sqlserver.rb +15 -1
  51. data/test/aggregations_test.rb +16 -1
  52. data/test/all.sh +2 -2
  53. data/test/associations/ar_joins_test.rb +0 -0
  54. data/test/associations/callbacks_test.rb +51 -30
  55. data/test/associations/cascaded_eager_loading_test.rb +1 -29
  56. data/test/associations/eager_singularization_test.rb +145 -0
  57. data/test/associations/eager_test.rb +42 -6
  58. data/test/associations/extension_test.rb +6 -1
  59. data/test/associations/inner_join_association_test.rb +88 -0
  60. data/test/associations/join_model_test.rb +47 -16
  61. data/test/associations_test.rb +449 -226
  62. data/test/attribute_methods_test.rb +97 -0
  63. data/test/base_test.rb +251 -105
  64. data/test/binary_test.rb +22 -27
  65. data/test/calculations_test.rb +37 -5
  66. data/test/callbacks_test.rb +23 -0
  67. data/test/connection_test_firebird.rb +2 -2
  68. data/test/connection_test_mysql.rb +30 -0
  69. data/test/connections/native_mysql/connection.rb +3 -0
  70. data/test/connections/native_sqlite/connection.rb +5 -14
  71. data/test/connections/native_sqlite3/connection.rb +5 -14
  72. data/test/connections/native_sqlite3/in_memory_connection.rb +1 -1
  73. data/test/{copy_table_sqlite.rb → copy_table_test_sqlite.rb} +8 -3
  74. data/test/datatype_test_postgresql.rb +178 -27
  75. data/test/{empty_date_time_test.rb → date_time_test.rb} +13 -1
  76. data/test/defaults_test.rb +8 -1
  77. data/test/deprecated_finder_test.rb +7 -128
  78. data/test/finder_test.rb +192 -54
  79. data/test/fixtures/all/developers.yml +0 -0
  80. data/test/fixtures/all/people.csv +0 -0
  81. data/test/fixtures/all/tasks.yml +0 -0
  82. data/test/fixtures/author.rb +12 -5
  83. data/test/fixtures/binaries.yml +130 -435
  84. data/test/fixtures/category.rb +6 -0
  85. data/test/fixtures/company.rb +8 -1
  86. data/test/fixtures/computer.rb +1 -0
  87. data/test/fixtures/contact.rb +16 -0
  88. data/test/fixtures/customer.rb +2 -2
  89. data/test/fixtures/db_definitions/db2.drop.sql +1 -0
  90. data/test/fixtures/db_definitions/db2.sql +4 -0
  91. data/test/fixtures/db_definitions/firebird.drop.sql +3 -1
  92. data/test/fixtures/db_definitions/firebird.sql +6 -0
  93. data/test/fixtures/db_definitions/frontbase.drop.sql +1 -0
  94. data/test/fixtures/db_definitions/frontbase.sql +5 -0
  95. data/test/fixtures/db_definitions/openbase.sql +41 -25
  96. data/test/fixtures/db_definitions/oracle.drop.sql +2 -0
  97. data/test/fixtures/db_definitions/oracle.sql +5 -0
  98. data/test/fixtures/db_definitions/postgresql.drop.sql +7 -0
  99. data/test/fixtures/db_definitions/postgresql.sql +87 -58
  100. data/test/fixtures/db_definitions/postgresql2.sql +1 -2
  101. data/test/fixtures/db_definitions/schema.rb +280 -0
  102. data/test/fixtures/db_definitions/schema2.rb +11 -0
  103. data/test/fixtures/db_definitions/sqlite.drop.sql +1 -0
  104. data/test/fixtures/db_definitions/sqlite.sql +4 -0
  105. data/test/fixtures/db_definitions/sybase.drop.sql +1 -0
  106. data/test/fixtures/db_definitions/sybase.sql +4 -0
  107. data/test/fixtures/developer.rb +10 -0
  108. data/test/fixtures/example.log +1 -0
  109. data/test/fixtures/flowers.jpg +0 -0
  110. data/test/fixtures/item.rb +7 -0
  111. data/test/fixtures/items.yml +4 -0
  112. data/test/fixtures/joke.rb +0 -3
  113. data/test/fixtures/matey.rb +4 -0
  114. data/test/fixtures/mateys.yml +4 -0
  115. data/test/fixtures/minimalistic.rb +2 -0
  116. data/test/fixtures/minimalistics.yml +2 -0
  117. data/test/fixtures/mixins.yml +2 -100
  118. data/test/fixtures/parrot.rb +13 -0
  119. data/test/fixtures/parrots.yml +27 -0
  120. data/test/fixtures/parrots_pirates.yml +7 -0
  121. data/test/fixtures/pirate.rb +5 -0
  122. data/test/fixtures/pirates.yml +9 -0
  123. data/test/fixtures/post.rb +1 -0
  124. data/test/fixtures/project.rb +3 -2
  125. data/test/fixtures/reserved_words/distinct.yml +5 -0
  126. data/test/fixtures/reserved_words/distincts_selects.yml +11 -0
  127. data/test/fixtures/reserved_words/group.yml +14 -0
  128. data/test/fixtures/reserved_words/select.yml +8 -0
  129. data/test/fixtures/reserved_words/values.yml +7 -0
  130. data/test/fixtures/ship.rb +3 -0
  131. data/test/fixtures/ships.yml +5 -0
  132. data/test/fixtures/tagging.rb +4 -0
  133. data/test/fixtures/taggings.yml +8 -1
  134. data/test/fixtures/topic.rb +13 -1
  135. data/test/fixtures/treasure.rb +4 -0
  136. data/test/fixtures/treasures.yml +10 -0
  137. data/test/fixtures_test.rb +205 -24
  138. data/test/inheritance_test.rb +7 -1
  139. data/test/json_serialization_test.rb +180 -0
  140. data/test/lifecycle_test.rb +1 -1
  141. data/test/locking_test.rb +85 -2
  142. data/test/migration_test.rb +206 -40
  143. data/test/mixin_test.rb +13 -515
  144. data/test/pk_test.rb +3 -6
  145. data/test/query_cache_test.rb +104 -0
  146. data/test/reflection_test.rb +16 -0
  147. data/test/reserved_word_test_mysql.rb +177 -0
  148. data/test/schema_dumper_test.rb +38 -3
  149. data/test/serialization_test.rb +47 -0
  150. data/test/transactions_test.rb +74 -23
  151. data/test/unconnected_test.rb +1 -1
  152. data/test/validations_test.rb +322 -32
  153. data/test/xml_serialization_test.rb +121 -44
  154. metadata +48 -41
  155. data/examples/associations.rb +0 -87
  156. data/examples/shared_setup.rb +0 -15
  157. data/examples/validation.rb +0 -85
  158. data/lib/active_record/acts/list.rb +0 -256
  159. data/lib/active_record/acts/nested_set.rb +0 -211
  160. data/lib/active_record/acts/tree.rb +0 -96
  161. data/lib/active_record/connection_adapters/db2_adapter.rb +0 -228
  162. data/lib/active_record/connection_adapters/firebird_adapter.rb +0 -728
  163. data/lib/active_record/connection_adapters/frontbase_adapter.rb +0 -861
  164. data/lib/active_record/connection_adapters/openbase_adapter.rb +0 -350
  165. data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -690
  166. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +0 -591
  167. data/lib/active_record/connection_adapters/sybase_adapter.rb +0 -662
  168. data/lib/active_record/deprecated_associations.rb +0 -104
  169. data/lib/active_record/deprecated_finders.rb +0 -44
  170. data/lib/active_record/vendor/simple.rb +0 -693
  171. data/lib/active_record/wrappers/yaml_wrapper.rb +0 -15
  172. data/lib/active_record/wrappings.rb +0 -58
  173. data/test/connections/native_sqlserver/connection.rb +0 -23
  174. data/test/connections/native_sqlserver_odbc/connection.rb +0 -25
  175. data/test/deprecated_associations_test.rb +0 -396
  176. data/test/fixtures/db_definitions/mysql.drop.sql +0 -32
  177. data/test/fixtures/db_definitions/mysql.sql +0 -234
  178. data/test/fixtures/db_definitions/mysql2.drop.sql +0 -2
  179. data/test/fixtures/db_definitions/mysql2.sql +0 -5
  180. data/test/fixtures/db_definitions/sqlserver.drop.sql +0 -34
  181. data/test/fixtures/db_definitions/sqlserver.sql +0 -243
  182. data/test/fixtures/db_definitions/sqlserver2.drop.sql +0 -2
  183. data/test/fixtures/db_definitions/sqlserver2.sql +0 -5
  184. data/test/fixtures/mixin.rb +0 -63
  185. data/test/mixin_nested_set_test.rb +0 -196
@@ -1,8 +1,8 @@
1
1
  module ActiveRecord
2
2
  module VERSION #:nodoc:
3
- MAJOR = 1
4
- MINOR = 15
5
- TINY = 6
3
+ MAJOR = 2
4
+ MINOR = 0
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -0,0 +1 @@
1
+ require 'active_record'
@@ -9,7 +9,7 @@ class AAACreateTablesTest < Test::Unit::TestCase
9
9
  end
10
10
 
11
11
  def test_drop_and_create_main_tables
12
- recreate ActiveRecord::Base
12
+ recreate ActiveRecord::Base unless use_migrations?
13
13
  assert true
14
14
  end
15
15
 
@@ -23,11 +23,24 @@ class AAACreateTablesTest < Test::Unit::TestCase
23
23
  end
24
24
 
25
25
  def test_drop_and_create_courses_table
26
- recreate Course, '2'
26
+ if Course.connection.supports_migrations?
27
+ eval(File.read("#{File.dirname(__FILE__)}/fixtures/db_definitions/schema2.rb"))
28
+ end
29
+ recreate Course, '2' unless use_migrations_for_courses?
27
30
  assert true
28
31
  end
29
32
 
30
33
  private
34
+ def use_migrations?
35
+ unittest_sql_filename = ActiveRecord::Base.connection.adapter_name.downcase + ".sql"
36
+ not File.exists? "#{@base_path}/#{unittest_sql_filename}"
37
+ end
38
+
39
+ def use_migrations_for_courses?
40
+ unittest2_sql_filename = ActiveRecord::Base.connection.adapter_name.downcase + "2.sql"
41
+ not File.exists? "#{@base_path}/#{unittest2_sql_filename}"
42
+ end
43
+
31
44
  def recreate(base, suffix = nil)
32
45
  connection = base.connection
33
46
  adapter_name = connection.adapter_name.downcase + suffix.to_s
@@ -4,8 +4,7 @@ $:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib')
4
4
  require 'test/unit'
5
5
  require 'active_record'
6
6
  require 'active_record/fixtures'
7
- require 'active_support/binding_of_caller'
8
- require 'active_support/breakpoint'
7
+ require 'active_support/test_case'
9
8
  require 'connection'
10
9
 
11
10
  # Show backtraces for deprecated behavior for quicker cleanup.
@@ -36,16 +35,10 @@ class Test::Unit::TestCase #:nodoc:
36
35
  end
37
36
 
38
37
  def assert_queries(num = 1)
39
- ActiveRecord::Base.connection.class.class_eval do
40
- self.query_count = 0
41
- alias_method :execute, :execute_with_query_counting
42
- end
38
+ $query_count = 0
43
39
  yield
44
40
  ensure
45
- ActiveRecord::Base.connection.class.class_eval do
46
- alias_method :execute, :execute_without_query_counting
47
- end
48
- assert_equal num, ActiveRecord::Base.connection.query_count, "#{ActiveRecord::Base.connection.query_count} instead of #{num} queries were executed."
41
+ assert_equal num, $query_count, "#{$query_count} instead of #{num} queries were executed."
49
42
  end
50
43
 
51
44
  def assert_no_queries(&block)
@@ -60,18 +53,32 @@ def current_adapter?(*types)
60
53
  end
61
54
  end
62
55
 
56
+ def uses_mocha(test_name)
57
+ require 'rubygems'
58
+ require 'mocha'
59
+ yield
60
+ rescue LoadError
61
+ $stderr.puts "Skipping #{test_name} tests. `gem install mocha` and try again."
62
+ end
63
+
63
64
  ActiveRecord::Base.connection.class.class_eval do
64
- cattr_accessor :query_count
65
+ unless defined? IGNORED_SQL
66
+ IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/]
65
67
 
66
- # Array of regexes of queries that are not counted against query_count
67
- @@ignore_list = [/^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/]
68
+ def execute_with_counting(sql, name = nil, &block)
69
+ $query_count ||= 0
70
+ $query_count += 1 unless IGNORED_SQL.any? { |r| sql =~ r }
71
+ execute_without_counting(sql, name, &block)
72
+ end
68
73
 
69
- alias_method :execute_without_query_counting, :execute
70
- def execute_with_query_counting(sql, name = nil, &block)
71
- self.query_count += 1 unless @@ignore_list.any? { |r| sql =~ r }
72
- execute_without_query_counting(sql, name, &block)
74
+ alias_method_chain :execute, :counting
73
75
  end
74
76
  end
75
77
 
78
+ # Make with_scope public for tests
79
+ class << ActiveRecord::Base
80
+ public :with_scope, :with_exclusive_scope
81
+ end
82
+
76
83
  #ActiveRecord::Base.logger = Logger.new(STDOUT)
77
84
  #ActiveRecord::Base.colorize_logging = false
@@ -5,27 +5,39 @@ class ActiveSchemaTest < Test::Unit::TestCase
5
5
  ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do
6
6
  alias_method :real_execute, :execute
7
7
  def execute(sql, name = nil) return sql end
8
- end
8
+ end
9
9
  end
10
-
10
+
11
11
  def teardown
12
12
  ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:alias_method, :execute, :real_execute)
13
13
  end
14
14
 
15
15
  def test_drop_table
16
- assert_equal "DROP TABLE people", drop_table(:people)
16
+ assert_equal "DROP TABLE `people`", drop_table(:people)
17
17
  end
18
-
18
+
19
+ if current_adapter?(:MysqlAdapter)
20
+ def test_create_mysql_database_with_encoding
21
+ assert_equal "CREATE DATABASE `matt` DEFAULT CHARACTER SET `utf8`", create_database(:matt)
22
+ assert_equal "CREATE DATABASE `aimonetti` DEFAULT CHARACTER SET `latin1`", create_database(:aimonetti, {:charset => 'latin1'})
23
+ assert_equal "CREATE DATABASE `matt_aimonetti` DEFAULT CHARACTER SET `big5` COLLATE `big5_chinese_ci`", create_database(:matt_aimonetti, {:charset => :big5, :collation => :big5_chinese_ci})
24
+ end
25
+ end
26
+
19
27
  def test_add_column
20
- assert_equal "ALTER TABLE people ADD `last_name` varchar(255)", add_column(:people, :last_name, :string)
28
+ assert_equal "ALTER TABLE `people` ADD `last_name` varchar(255)", add_column(:people, :last_name, :string)
21
29
  end
22
-
30
+
23
31
  def test_add_column_with_limit
24
- assert_equal "ALTER TABLE people ADD `key` varchar(32)", add_column(:people, :key, :string, :limit => 32)
32
+ assert_equal "ALTER TABLE `people` ADD `key` varchar(32)", add_column(:people, :key, :string, :limit => 32)
33
+ end
34
+
35
+ def test_drop_table_with_specific_database
36
+ assert_equal "DROP TABLE `otherdb`.`people`", drop_table('otherdb.people')
25
37
  end
26
38
 
27
39
  private
28
40
  def method_missing(method_symbol, *arguments)
29
41
  ActiveRecord::Base.connection.send(method_symbol, *arguments)
30
42
  end
31
- end
43
+ end
@@ -19,7 +19,7 @@ class AdapterTest < Test::Unit::TestCase
19
19
 
20
20
  def test_indexes
21
21
  idx_name = "accounts_idx"
22
-
22
+
23
23
  if @connection.respond_to?(:indexes)
24
24
  indexes = @connection.indexes("accounts")
25
25
  assert indexes.empty?
@@ -39,24 +39,42 @@ class AdapterTest < Test::Unit::TestCase
39
39
  ensure
40
40
  @connection.remove_index(:accounts, :name => idx_name) rescue nil
41
41
  end
42
-
42
+
43
43
  def test_current_database
44
44
  if @connection.respond_to?(:current_database)
45
45
  assert_equal ENV['ARUNIT_DB_NAME'] || "activerecord_unittest", @connection.current_database
46
46
  end
47
47
  end
48
48
 
49
+ if current_adapter?(:MysqlAdapter)
50
+ def test_charset
51
+ assert_not_nil @connection.charset
52
+ assert_not_equal 'character_set_database', @connection.charset
53
+ assert_equal @connection.show_variable('character_set_database'), @connection.charset
54
+ end
55
+
56
+ def test_collation
57
+ assert_not_nil @connection.collation
58
+ assert_not_equal 'collation_database', @connection.collation
59
+ assert_equal @connection.show_variable('collation_database'), @connection.collation
60
+ end
61
+
62
+ def test_show_nonexistent_variable_returns_nil
63
+ assert_nil @connection.show_variable('foo_bar_baz')
64
+ end
65
+ end
66
+
49
67
  def test_table_alias
50
68
  def @connection.test_table_alias_length() 10; end
51
69
  class << @connection
52
70
  alias_method :old_table_alias_length, :table_alias_length
53
71
  alias_method :table_alias_length, :test_table_alias_length
54
72
  end
55
-
73
+
56
74
  assert_equal 'posts', @connection.table_alias_for('posts')
57
75
  assert_equal 'posts_comm', @connection.table_alias_for('posts_comments')
58
76
  assert_equal 'dbo_posts', @connection.table_alias_for('dbo.posts')
59
-
77
+
60
78
  class << @connection
61
79
  alias_method :table_alias_length, :old_table_alias_length
62
80
  end
@@ -66,7 +84,7 @@ class AdapterTest < Test::Unit::TestCase
66
84
  if ActiveRecord::Base.connection.respond_to?(:reset_pk_sequence!)
67
85
  require 'fixtures/movie'
68
86
  require 'fixtures/subscriber'
69
-
87
+
70
88
  def test_reset_empty_table_with_custom_pk
71
89
  Movie.delete_all
72
90
  Movie.connection.reset_pk_sequence! 'movies'
@@ -4,6 +4,8 @@ require 'fixtures/post'
4
4
  require 'fixtures/task'
5
5
 
6
6
  class SqlServerAdapterTest < Test::Unit::TestCase
7
+ class TableWithRealColumn < ActiveRecord::Base; end
8
+
7
9
  fixtures :posts, :tasks
8
10
 
9
11
  def setup
@@ -11,7 +13,11 @@ class SqlServerAdapterTest < Test::Unit::TestCase
11
13
  end
12
14
 
13
15
  def teardown
14
- @connection.execute("SET LANGUAGE us_english")
16
+ @connection.execute("SET LANGUAGE us_english") rescue nil
17
+ end
18
+
19
+ def test_real_column_has_float_type
20
+ assert_equal :float, TableWithRealColumn.columns_hash["real_number"].type
15
21
  end
16
22
 
17
23
  # SQL Server 2000 has a bug where some unambiguous date formats are not
@@ -24,6 +30,14 @@ class SqlServerAdapterTest < Test::Unit::TestCase
24
30
  end
25
31
  end
26
32
 
33
+ def test_indexes_with_descending_order
34
+ # Make sure we have an index with descending order
35
+ @connection.execute "CREATE INDEX idx_credit_limit ON accounts (credit_limit DESC)" rescue nil
36
+ assert_equal ["credit_limit"], @connection.indexes('accounts').first.columns
37
+ ensure
38
+ @connection.execute "DROP INDEX accounts.idx_credit_limit"
39
+ end
40
+
27
41
  def test_execute_without_block_closes_statement
28
42
  assert_all_statements_used_are_closed do
29
43
  @connection.execute("SELECT 1")
@@ -20,7 +20,7 @@ class AggregationsTest < Test::Unit::TestCase
20
20
  def test_change_single_value_object
21
21
  customers(:david).balance = Money.new(100)
22
22
  customers(:david).save
23
- assert_equal 100, Customer.find(1).balance.amount
23
+ assert_equal 100, customers(:david).reload.balance.amount
24
24
  end
25
25
 
26
26
  def test_immutable_value_objects
@@ -92,6 +92,21 @@ class AggregationsTest < Test::Unit::TestCase
92
92
  def test_nil_raises_error_when_allow_nil_is_false
93
93
  assert_raises(NoMethodError) { customers(:david).balance = nil }
94
94
  end
95
+
96
+ def test_allow_nil_address_loaded_when_only_some_attributes_are_nil
97
+ customers(:zaphod).address_street = nil
98
+ customers(:zaphod).save
99
+ customers(:zaphod).reload
100
+ assert_kind_of Address, customers(:zaphod).address
101
+ assert customers(:zaphod).address.street.nil?
102
+ end
103
+
104
+ def test_nil_assignment_results_in_nil
105
+ customers(:david).gps_location = GpsLocation.new('39x111')
106
+ assert_not_equal nil, customers(:david).gps_location
107
+ customers(:david).gps_location = nil
108
+ assert_equal nil, customers(:david).gps_location
109
+ end
95
110
  end
96
111
 
97
112
  class OverridingAggregationsTest < Test::Unit::TestCase
@@ -1,8 +1,8 @@
1
1
  #!/bin/sh
2
2
 
3
3
  if [ -z "$1" ]; then
4
- echo "Usage: $0 connections/<db_library>" 1>&2
4
+ echo "Usage: $0 <database>" 1>&2
5
5
  exit 1
6
6
  fi
7
7
 
8
- ruby -I $1 -e 'Dir.foreach(".") { |file| require file if file =~ /_test.rb$/ }'
8
+ ruby -I connections/native_$1 -e 'Dir["**/*_test.rb"].each { |path| require path }'
File without changes
@@ -15,29 +15,29 @@ class AssociationCallbacksTest < Test::Unit::TestCase
15
15
  @authorless = posts(:authorless)
16
16
  assert @david.post_log.empty?
17
17
  end
18
-
18
+
19
19
  def test_adding_macro_callbacks
20
20
  @david.posts_with_callbacks << @thinking
21
21
  assert_equal ["before_adding#{@thinking.id}", "after_adding#{@thinking.id}"], @david.post_log
22
22
  @david.posts_with_callbacks << @thinking
23
- assert_equal ["before_adding#{@thinking.id}", "after_adding#{@thinking.id}", "before_adding#{@thinking.id}",
23
+ assert_equal ["before_adding#{@thinking.id}", "after_adding#{@thinking.id}", "before_adding#{@thinking.id}",
24
24
  "after_adding#{@thinking.id}"], @david.post_log
25
25
  end
26
-
26
+
27
27
  def test_adding_with_proc_callbacks
28
28
  @david.posts_with_proc_callbacks << @thinking
29
29
  assert_equal ["before_adding#{@thinking.id}", "after_adding#{@thinking.id}"], @david.post_log
30
30
  @david.posts_with_proc_callbacks << @thinking
31
- assert_equal ["before_adding#{@thinking.id}", "after_adding#{@thinking.id}", "before_adding#{@thinking.id}",
31
+ assert_equal ["before_adding#{@thinking.id}", "after_adding#{@thinking.id}", "before_adding#{@thinking.id}",
32
32
  "after_adding#{@thinking.id}"], @david.post_log
33
33
  end
34
-
34
+
35
35
  def test_removing_with_macro_callbacks
36
36
  first_post, second_post = @david.posts_with_callbacks[0, 2]
37
37
  @david.posts_with_callbacks.delete(first_post)
38
38
  assert_equal ["before_removing#{first_post.id}", "after_removing#{first_post.id}"], @david.post_log
39
39
  @david.posts_with_callbacks.delete(second_post)
40
- assert_equal ["before_removing#{first_post.id}", "after_removing#{first_post.id}", "before_removing#{second_post.id}",
40
+ assert_equal ["before_removing#{first_post.id}", "after_removing#{first_post.id}", "before_removing#{second_post.id}",
41
41
  "after_removing#{second_post.id}"], @david.post_log
42
42
  end
43
43
 
@@ -46,20 +46,43 @@ class AssociationCallbacksTest < Test::Unit::TestCase
46
46
  @david.posts_with_proc_callbacks.delete(first_post)
47
47
  assert_equal ["before_removing#{first_post.id}", "after_removing#{first_post.id}"], @david.post_log
48
48
  @david.posts_with_proc_callbacks.delete(second_post)
49
- assert_equal ["before_removing#{first_post.id}", "after_removing#{first_post.id}", "before_removing#{second_post.id}",
49
+ assert_equal ["before_removing#{first_post.id}", "after_removing#{first_post.id}", "before_removing#{second_post.id}",
50
50
  "after_removing#{second_post.id}"], @david.post_log
51
51
  end
52
-
52
+
53
53
  def test_multiple_callbacks
54
54
  @david.posts_with_multiple_callbacks << @thinking
55
- assert_equal ["before_adding#{@thinking.id}", "before_adding_proc#{@thinking.id}", "after_adding#{@thinking.id}",
55
+ assert_equal ["before_adding#{@thinking.id}", "before_adding_proc#{@thinking.id}", "after_adding#{@thinking.id}",
56
56
  "after_adding_proc#{@thinking.id}"], @david.post_log
57
57
  @david.posts_with_multiple_callbacks << @thinking
58
- assert_equal ["before_adding#{@thinking.id}", "before_adding_proc#{@thinking.id}", "after_adding#{@thinking.id}",
59
- "after_adding_proc#{@thinking.id}", "before_adding#{@thinking.id}", "before_adding_proc#{@thinking.id}",
58
+ assert_equal ["before_adding#{@thinking.id}", "before_adding_proc#{@thinking.id}", "after_adding#{@thinking.id}",
59
+ "after_adding_proc#{@thinking.id}", "before_adding#{@thinking.id}", "before_adding_proc#{@thinking.id}",
60
60
  "after_adding#{@thinking.id}", "after_adding_proc#{@thinking.id}"], @david.post_log
61
61
  end
62
-
62
+
63
+ def test_has_many_callbacks_with_create
64
+ morten = Author.create :name => "Morten"
65
+ post = morten.posts_with_proc_callbacks.create! :title => "Hello", :body => "How are you doing?"
66
+ assert_equal ["before_adding<new>", "after_adding#{post.id}"], morten.post_log
67
+ end
68
+
69
+ def test_has_many_callbacks_with_create!
70
+ morten = Author.create! :name => "Morten"
71
+ post = morten.posts_with_proc_callbacks.create :title => "Hello", :body => "How are you doing?"
72
+ assert_equal ["before_adding<new>", "after_adding#{post.id}"], morten.post_log
73
+ end
74
+
75
+ def test_has_many_callbacks_for_save_on_parent
76
+ jack = Author.new :name => "Jack"
77
+ post = jack.posts_with_callbacks.build :title => "Call me back!", :body => "Before you wake up and after you sleep"
78
+
79
+ callback_log = ["before_adding<new>", "after_adding#{jack.posts_with_callbacks.first.id}"]
80
+ assert_equal callback_log, jack.post_log
81
+ assert jack.save
82
+ assert_equal 1, jack.posts_with_callbacks.count
83
+ assert_equal callback_log, jack.post_log
84
+ end
85
+
63
86
  def test_has_and_belongs_to_many_add_callback
64
87
  david = developers(:david)
65
88
  ar = projects(:active_record)
@@ -67,10 +90,10 @@ class AssociationCallbacksTest < Test::Unit::TestCase
67
90
  ar.developers_with_callbacks << david
68
91
  assert_equal ["before_adding#{david.id}", "after_adding#{david.id}"], ar.developers_log
69
92
  ar.developers_with_callbacks << david
70
- assert_equal ["before_adding#{david.id}", "after_adding#{david.id}", "before_adding#{david.id}",
93
+ assert_equal ["before_adding#{david.id}", "after_adding#{david.id}", "before_adding#{david.id}",
71
94
  "after_adding#{david.id}"], ar.developers_log
72
95
  end
73
-
96
+
74
97
  def test_has_and_belongs_to_many_remove_callback
75
98
  david = developers(:david)
76
99
  jamis = developers(:jamis)
@@ -78,9 +101,9 @@ class AssociationCallbacksTest < Test::Unit::TestCase
78
101
  assert activerecord.developers_log.empty?
79
102
  activerecord.developers_with_callbacks.delete(david)
80
103
  assert_equal ["before_removing#{david.id}", "after_removing#{david.id}"], activerecord.developers_log
81
-
104
+
82
105
  activerecord.developers_with_callbacks.delete(jamis)
83
- assert_equal ["before_removing#{david.id}", "after_removing#{david.id}", "before_removing#{jamis.id}",
106
+ assert_equal ["before_removing#{david.id}", "after_removing#{david.id}", "before_removing#{jamis.id}",
84
107
  "after_removing#{jamis.id}"], activerecord.developers_log
85
108
  end
86
109
 
@@ -97,7 +120,18 @@ class AssociationCallbacksTest < Test::Unit::TestCase
97
120
  assert activerecord.developers_with_callbacks.clear
98
121
  assert_equal log_array, activerecord.developers_log.sort
99
122
  end
100
-
123
+
124
+ def test_has_many_and_belongs_to_many_callbacks_for_save_on_parent
125
+ project = Project.new :name => "Callbacks"
126
+ project.developers_with_callbacks.build :name => "Jack", :salary => 95000
127
+
128
+ callback_log = ["before_adding<new>", "after_adding<new>"]
129
+ assert_equal callback_log, project.developers_log
130
+ assert project.save
131
+ assert_equal 1, project.developers_with_callbacks.count
132
+ assert_equal callback_log, project.developers_log
133
+ end
134
+
101
135
  def test_dont_add_if_before_callback_raises_exception
102
136
  assert !@david.unchangable_posts.include?(@authorless)
103
137
  begin
@@ -109,18 +143,5 @@ class AssociationCallbacksTest < Test::Unit::TestCase
109
143
  @david.reload
110
144
  assert !@david.unchangable_posts.include?(@authorless)
111
145
  end
112
-
113
- def test_push_with_attributes
114
- assert_deprecated 'push_with_attributes' do
115
- david = developers(:david)
116
- activerecord = projects(:active_record)
117
- assert activerecord.developers_log.empty?
118
- activerecord.developers_with_callbacks.push_with_attributes(david, {})
119
- assert_equal ["before_adding#{david.id}", "after_adding#{david.id}"], activerecord.developers_log
120
- activerecord.developers_with_callbacks.push_with_attributes(david, {})
121
- assert_equal ["before_adding#{david.id}", "after_adding#{david.id}", "before_adding#{david.id}",
122
- "after_adding#{david.id}"], activerecord.developers_log
123
- end
124
- end
125
146
  end
126
147