aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test')
-rw-r--r--activerecord/test/cases/adapter_test.rb16
-rw-r--r--activerecord/test/cases/adapters/mysql2/active_schema_test.rb24
-rw-r--r--activerecord/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb28
-rw-r--r--activerecord/test/cases/adapters/postgresql/bytea_test.rb2
-rw-r--r--activerecord/test/cases/adapters/postgresql/datatype_test.rb2
-rw-r--r--activerecord/test/cases/ar_schema_test.rb8
-rw-r--r--activerecord/test/cases/arel/visitors/oracle12_test.rb21
-rw-r--r--activerecord/test/cases/arel/visitors/oracle_test.rb21
-rw-r--r--activerecord/test/cases/associations/eager_load_nested_include_test.rb4
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb16
-rw-r--r--activerecord/test/cases/associations/has_many_through_associations_test.rb16
-rw-r--r--activerecord/test/cases/associations/inverse_associations_test.rb9
-rw-r--r--activerecord/test/cases/callbacks_test.rb4
-rw-r--r--activerecord/test/cases/date_time_precision_test.rb2
-rw-r--r--activerecord/test/cases/invertible_migration_test.rb59
-rw-r--r--activerecord/test/cases/locking_test.rb11
-rw-r--r--activerecord/test/cases/migration/column_attributes_test.rb6
-rw-r--r--activerecord/test/cases/migration/command_recorder_test.rb34
-rw-r--r--activerecord/test/cases/migration/compatibility_test.rb33
-rw-r--r--activerecord/test/cases/migration_test.rb10
-rw-r--r--activerecord/test/cases/relation_test.rb1
-rw-r--r--activerecord/test/cases/time_precision_test.rb2
-rw-r--r--activerecord/test/cases/timestamp_test.rb14
-rw-r--r--activerecord/test/cases/transaction_callbacks_test.rb32
-rw-r--r--activerecord/test/cases/transactions_test.rb101
-rw-r--r--activerecord/test/cases/validations_test.rb12
-rw-r--r--activerecord/test/models/post.rb4
-rw-r--r--activerecord/test/models/section.rb6
-rw-r--r--activerecord/test/models/seminar.rb6
-rw-r--r--activerecord/test/models/session.rb6
-rw-r--r--activerecord/test/schema/schema.rb18
31 files changed, 434 insertions, 94 deletions
diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb
index ba04859bf0..ce2ed06c1d 100644
--- a/activerecord/test/cases/adapter_test.rb
+++ b/activerecord/test/cases/adapter_test.rb
@@ -490,6 +490,8 @@ module ActiveRecord
@connection.truncate("posts")
assert_equal 0, Post.count
+ ensure
+ reset_fixtures("posts")
end
def test_truncate_with_query_cache
@@ -501,6 +503,7 @@ module ActiveRecord
assert_equal 0, Post.count
ensure
+ reset_fixtures("posts")
@connection.disable_query_cache!
end
@@ -514,6 +517,8 @@ module ActiveRecord
assert_equal 0, Post.count
assert_equal 0, Author.count
assert_equal 0, AuthorAddress.count
+ ensure
+ reset_fixtures("posts", "authors", "author_addresses")
end
def test_truncate_tables_with_query_cache
@@ -529,6 +534,7 @@ module ActiveRecord
assert_equal 0, Author.count
assert_equal 0, AuthorAddress.count
ensure
+ reset_fixtures("posts", "authors", "author_addresses")
@connection.disable_query_cache!
end
@@ -551,6 +557,16 @@ module ActiveRecord
assert_nothing_raised { sub.save! }
end
end
+
+ private
+
+ def reset_fixtures(*fixture_names)
+ ActiveRecord::FixtureSet.reset_cache
+
+ fixture_names.each do |fixture_name|
+ ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT, fixture_name)
+ end
+ end
end
end
diff --git a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
index 88c2ac5d0a..c2c357d0c1 100644
--- a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
@@ -10,7 +10,15 @@ class Mysql2ActiveSchemaTest < ActiveRecord::Mysql2TestCase
ActiveRecord::Base.connection.send(:default_row_format)
ActiveRecord::Base.connection.singleton_class.class_eval do
alias_method :execute_without_stub, :execute
- def execute(sql, name = nil) sql end
+ def execute(sql, name = nil)
+ ActiveSupport::Notifications.instrumenter.instrument(
+ "sql.active_record",
+ sql: sql,
+ name: name,
+ connection: self) do
+ sql
+ end
+ end
end
end
@@ -89,17 +97,19 @@ class Mysql2ActiveSchemaTest < ActiveRecord::Mysql2TestCase
%w(SPATIAL FULLTEXT UNIQUE).each do |type|
expected = "ALTER TABLE `people` ADD #{type} INDEX `index_people_on_last_name` (`last_name`)"
- actual = ActiveRecord::Base.connection.change_table(:people, bulk: true) do |t|
- t.index :last_name, type: type
+ assert_sql(expected) do
+ ActiveRecord::Base.connection.change_table(:people, bulk: true) do |t|
+ t.index :last_name, type: type
+ end
end
- assert_equal expected, actual
end
expected = "ALTER TABLE `people` ADD INDEX `index_people_on_last_name` USING btree (`last_name`(10)), ALGORITHM = COPY"
- actual = ActiveRecord::Base.connection.change_table(:people, bulk: true) do |t|
- t.index :last_name, length: 10, using: :btree, algorithm: :copy
+ assert_sql(expected) do
+ ActiveRecord::Base.connection.change_table(:people, bulk: true) do |t|
+ t.index :last_name, length: 10, using: :btree, algorithm: :copy
+ end
end
- assert_equal expected, actual
end
def test_drop_table
diff --git a/activerecord/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb b/activerecord/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb
new file mode 100644
index 0000000000..4d361e405c
--- /dev/null
+++ b/activerecord/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require "cases/helper"
+require "support/connection_helper"
+require "models/author"
+require "models/bulb"
+
+module ActiveRecord
+ class CountDeletedRowsWithLockTest < ActiveRecord::Mysql2TestCase
+ test "delete and create in different threads synchronize correctly" do
+ Bulb.unscoped.delete_all
+ Bulb.create!(name: "Jimmy", color: "blue")
+
+ delete_thread = Thread.new do
+ Bulb.unscoped.delete_all
+ end
+
+ create_thread = Thread.new do
+ Author.create!(name: "Tommy")
+ end
+
+ delete_thread.join
+ create_thread.join
+
+ assert_equal 1, delete_thread.value
+ end
+ end
+end
diff --git a/activerecord/test/cases/adapters/postgresql/bytea_test.rb b/activerecord/test/cases/adapters/postgresql/bytea_test.rb
index 3988c2adca..531e6b2328 100644
--- a/activerecord/test/cases/adapters/postgresql/bytea_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/bytea_test.rb
@@ -35,7 +35,7 @@ class PostgresqlByteaTest < ActiveRecord::PostgreSQLTestCase
def test_binary_columns_are_limitless_the_upper_limit_is_one_GB
assert_equal "bytea", @connection.type_to_sql(:binary, limit: 100_000)
- assert_raise ActiveRecord::ActiveRecordError do
+ assert_raise ArgumentError do
@connection.type_to_sql(:binary, limit: 4294967295)
end
end
diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb
index b7535d5c9a..562cf1f2d1 100644
--- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb
@@ -64,7 +64,7 @@ class PostgresqlDataTypeTest < ActiveRecord::PostgreSQLTestCase
def test_text_columns_are_limitless_the_upper_limit_is_one_GB
assert_equal "text", @connection.type_to_sql(:text, limit: 100_000)
- assert_raise ActiveRecord::ActiveRecordError do
+ assert_raise ArgumentError do
@connection.type_to_sql(:text, limit: 4294967295)
end
end
diff --git a/activerecord/test/cases/ar_schema_test.rb b/activerecord/test/cases/ar_schema_test.rb
index 9027cc582a..7aa6d089c5 100644
--- a/activerecord/test/cases/ar_schema_test.rb
+++ b/activerecord/test/cases/ar_schema_test.rb
@@ -160,7 +160,7 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase
end
if subsecond_precision_supported?
- def test_timestamps_sets_presicion_on_create_table
+ def test_timestamps_sets_precision_on_create_table
ActiveRecord::Schema.define do
create_table :has_timestamps do |t|
t.timestamps
@@ -171,7 +171,7 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase
assert @connection.column_exists?(:has_timestamps, :updated_at, precision: 6, null: false)
end
- def test_timestamps_sets_presicion_on_change_table
+ def test_timestamps_sets_precision_on_change_table
ActiveRecord::Schema.define do
create_table :has_timestamps
@@ -185,7 +185,7 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase
end
if ActiveRecord::Base.connection.supports_bulk_alter?
- def test_timestamps_sets_presicion_on_change_table_with_bulk
+ def test_timestamps_sets_precision_on_change_table_with_bulk
ActiveRecord::Schema.define do
create_table :has_timestamps
@@ -199,7 +199,7 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase
end
end
- def test_timestamps_sets_presicion_on_add_timestamps
+ def test_timestamps_sets_precision_on_add_timestamps
ActiveRecord::Schema.define do
create_table :has_timestamps
add_timestamps :has_timestamps, default: Time.now
diff --git a/activerecord/test/cases/arel/visitors/oracle12_test.rb b/activerecord/test/cases/arel/visitors/oracle12_test.rb
index 4ce5cab4db..ebea12910d 100644
--- a/activerecord/test/cases/arel/visitors/oracle12_test.rb
+++ b/activerecord/test/cases/arel/visitors/oracle12_test.rb
@@ -8,6 +8,7 @@ module Arel
before do
@visitor = Oracle12.new Table.engine.connection
@table = Table.new(:users)
+ @attr = @table[:id]
end
def compile(node)
@@ -95,6 +96,26 @@ module Arel
sql.must_be_like %{ "users"."name" IS NOT NULL }
end
end
+
+ describe "Nodes::In" do
+ it "should know how to visit" do
+ ary = (1 .. 1001).to_a
+ node = @attr.in ary
+ compile(node).must_be_like %{
+ "users"."id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000) OR \"users\".\"id\" IN (1001)
+ }
+ end
+ end
+
+ describe "Nodes::NotIn" do
+ it "should know how to visit" do
+ ary = (1 .. 1001).to_a
+ node = @attr.not_in ary
+ compile(node).must_be_like %{
+ "users"."id" NOT IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000) AND \"users\".\"id\" NOT IN (1001)
+ }
+ end
+ end
end
end
end
diff --git a/activerecord/test/cases/arel/visitors/oracle_test.rb b/activerecord/test/cases/arel/visitors/oracle_test.rb
index 893edc7f74..f69b201855 100644
--- a/activerecord/test/cases/arel/visitors/oracle_test.rb
+++ b/activerecord/test/cases/arel/visitors/oracle_test.rb
@@ -8,6 +8,7 @@ module Arel
before do
@visitor = Oracle.new Table.engine.connection
@table = Table.new(:users)
+ @attr = @table[:id]
end
def compile(node)
@@ -231,6 +232,26 @@ module Arel
sql.must_be_like %{ "users"."name" IS NOT NULL }
end
end
+
+ describe "Nodes::In" do
+ it "should know how to visit" do
+ ary = (1 .. 1001).to_a
+ node = @attr.in ary
+ compile(node).must_be_like %{
+ "users"."id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000) OR \"users\".\"id\" IN (1001)
+ }
+ end
+ end
+
+ describe "Nodes::NotIn" do
+ it "should know how to visit" do
+ ary = (1 .. 1001).to_a
+ node = @attr.not_in ary
+ compile(node).must_be_like %{
+ "users"."id" NOT IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000) AND \"users\".\"id\" NOT IN (1001)
+ }
+ end
+ end
end
end
end
diff --git a/activerecord/test/cases/associations/eager_load_nested_include_test.rb b/activerecord/test/cases/associations/eager_load_nested_include_test.rb
index 525ad3197a..849939de75 100644
--- a/activerecord/test/cases/associations/eager_load_nested_include_test.rb
+++ b/activerecord/test/cases/associations/eager_load_nested_include_test.rb
@@ -110,10 +110,10 @@ class EagerLoadNestedIncludeWithMissingDataTest < ActiveRecord::TestCase
end
teardown do
- @davey_mcdave.destroy
- @first_post.destroy
@first_comment.destroy
@first_categorization.destroy
+ @davey_mcdave.destroy
+ @first_post.destroy
end
def test_missing_data_in_a_nested_include_should_not_cause_errors_when_constructing_objects
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 6a7efe2121..32285f269a 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -2578,22 +2578,22 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
test "association with extend option" do
post = posts(:welcome)
- assert_equal "lifo", post.comments_with_extend.author
- assert_equal "hello", post.comments_with_extend.greeting
+ assert_equal "lifo", post.comments_with_extend.author
+ assert_equal "hello :)", post.comments_with_extend.greeting
end
test "association with extend option with multiple extensions" do
post = posts(:welcome)
- assert_equal "lifo", post.comments_with_extend_2.author
- assert_equal "hullo", post.comments_with_extend_2.greeting
+ assert_equal "lifo", post.comments_with_extend_2.author
+ assert_equal "hullo :)", post.comments_with_extend_2.greeting
end
test "extend option affects per association" do
post = posts(:welcome)
- assert_equal "lifo", post.comments_with_extend.author
- assert_equal "lifo", post.comments_with_extend_2.author
- assert_equal "hello", post.comments_with_extend.greeting
- assert_equal "hullo", post.comments_with_extend_2.greeting
+ assert_equal "lifo", post.comments_with_extend.author
+ assert_equal "lifo", post.comments_with_extend_2.author
+ assert_equal "hello :)", post.comments_with_extend.greeting
+ assert_equal "hullo :)", post.comments_with_extend_2.greeting
end
test "delete record with complex joins" do
diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb
index fa540c9dab..c13789f7ec 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -33,6 +33,9 @@ require "models/organization"
require "models/user"
require "models/family"
require "models/family_tree"
+require "models/section"
+require "models/seminar"
+require "models/session"
class HasManyThroughAssociationsTest < ActiveRecord::TestCase
fixtures :posts, :readers, :people, :comments, :authors, :categories, :taggings, :tags,
@@ -1492,6 +1495,19 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
end
end
+ def test_circular_autosave_association_correctly_saves_multiple_records
+ cs180 = Seminar.new(name: "CS180")
+ fall = Session.new(name: "Fall")
+ sections = [
+ cs180.sections.build(short_name: "A"),
+ cs180.sections.build(short_name: "B"),
+ ]
+ fall.sections << sections
+ fall.save!
+ fall.reload
+ assert_equal sections, fall.sections.sort_by(&:id)
+ end
+
private
def make_model(name)
Class.new(ActiveRecord::Base) { define_singleton_method(:name) { name } }
diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb
index da3a42e2b5..669e176dcb 100644
--- a/activerecord/test/cases/associations/inverse_associations_test.rb
+++ b/activerecord/test/cases/associations/inverse_associations_test.rb
@@ -8,6 +8,7 @@ require "models/zine"
require "models/club"
require "models/sponsor"
require "models/rating"
+require "models/post"
require "models/comment"
require "models/car"
require "models/bulb"
@@ -62,6 +63,14 @@ class AutomaticInverseFindingTests < ActiveRecord::TestCase
assert_equal rating_reflection, comment_reflection.inverse_of, "The Comment reflection's inverse should be the Rating reflection"
end
+ def test_has_many_and_belongs_to_should_find_inverse_automatically_for_extension_block
+ comment_reflection = Comment.reflect_on_association(:post)
+ post_reflection = Post.reflect_on_association(:comments)
+
+ assert_predicate post_reflection, :has_inverse?
+ assert_equal comment_reflection, post_reflection.inverse_of
+ end
+
def test_has_many_and_belongs_to_should_find_inverse_automatically_for_sti
author_reflection = Author.reflect_on_association(:posts)
author_child_reflection = Author.reflect_on_association(:special_posts)
diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb
index 4d6a112af5..b4026078f1 100644
--- a/activerecord/test/cases/callbacks_test.rb
+++ b/activerecord/test/cases/callbacks_test.rb
@@ -458,10 +458,6 @@ class CallbacksTest < ActiveRecord::TestCase
[ :before_validation, :object ],
[ :before_validation, :block ],
[ :before_validation, :throwing_abort ],
- [ :after_rollback, :block ],
- [ :after_rollback, :object ],
- [ :after_rollback, :proc ],
- [ :after_rollback, :method ],
], david.history
end
diff --git a/activerecord/test/cases/date_time_precision_test.rb b/activerecord/test/cases/date_time_precision_test.rb
index 9d1af9362d..79d63949ca 100644
--- a/activerecord/test/cases/date_time_precision_test.rb
+++ b/activerecord/test/cases/date_time_precision_test.rb
@@ -82,7 +82,7 @@ if subsecond_precision_supported?
end
def test_invalid_datetime_precision_raises_error
- assert_raises ActiveRecord::ActiveRecordError do
+ assert_raises ArgumentError do
@connection.create_table(:foos, force: true) do |t|
t.timestamps precision: 7
end
diff --git a/activerecord/test/cases/invertible_migration_test.rb b/activerecord/test/cases/invertible_migration_test.rb
index d68cc40107..7f67b945f0 100644
--- a/activerecord/test/cases/invertible_migration_test.rb
+++ b/activerecord/test/cases/invertible_migration_test.rb
@@ -103,6 +103,32 @@ module ActiveRecord
end
end
+ class ChangeColumnComment1 < SilentMigration
+ def change
+ create_table("horses") do |t|
+ t.column :name, :string, comment: "Sekitoba"
+ end
+ end
+ end
+
+ class ChangeColumnComment2 < SilentMigration
+ def change
+ change_column_comment :horses, :name, from: "Sekitoba", to: "Diomed"
+ end
+ end
+
+ class ChangeTableComment1 < SilentMigration
+ def change
+ create_table("horses", comment: "Sekitoba")
+ end
+ end
+
+ class ChangeTableComment2 < SilentMigration
+ def change
+ change_table_comment :horses, from: "Sekitoba", to: "Diomed"
+ end
+ end
+
class DisableExtension1 < SilentMigration
def change
enable_extension "hstore"
@@ -290,6 +316,7 @@ module ActiveRecord
def test_migrate_revert_change_column_default
migration1 = ChangeColumnDefault1.new
migration1.migrate(:up)
+ Horse.reset_column_information
assert_equal "Sekitoba", Horse.new.name
migration2 = ChangeColumnDefault2.new
@@ -302,6 +329,38 @@ module ActiveRecord
assert_equal "Sekitoba", Horse.new.name
end
+ if ActiveRecord::Base.connection.supports_comments?
+ def test_migrate_revert_change_column_comment
+ migration1 = ChangeColumnComment1.new
+ migration1.migrate(:up)
+ Horse.reset_column_information
+ assert_equal "Sekitoba", Horse.columns_hash["name"].comment
+
+ migration2 = ChangeColumnComment2.new
+ migration2.migrate(:up)
+ Horse.reset_column_information
+ assert_equal "Diomed", Horse.columns_hash["name"].comment
+
+ migration2.migrate(:down)
+ Horse.reset_column_information
+ assert_equal "Sekitoba", Horse.columns_hash["name"].comment
+ end
+
+ def test_migrate_revert_change_table_comment
+ connection = ActiveRecord::Base.connection
+ migration1 = ChangeTableComment1.new
+ migration1.migrate(:up)
+ assert_equal "Sekitoba", connection.table_comment("horses")
+
+ migration2 = ChangeTableComment2.new
+ migration2.migrate(:up)
+ assert_equal "Diomed", connection.table_comment("horses")
+
+ migration2.migrate(:down)
+ assert_equal "Sekitoba", connection.table_comment("horses")
+ end
+ end
+
if current_adapter?(:PostgreSQLAdapter)
def test_migrate_enable_and_disable_extension
migration1 = InvertibleMigration.new
diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb
index 33bd74e114..04f9b26960 100644
--- a/activerecord/test/cases/locking_test.rb
+++ b/activerecord/test/cases/locking_test.rb
@@ -182,7 +182,9 @@ class OptimisticLockingTest < ActiveRecord::TestCase
p1.touch
assert_equal 1, p1.lock_version
- assert_not p1.changed?, "Changes should have been cleared"
+ assert_not_predicate p1, :changed?, "Changes should have been cleared"
+ assert_predicate p1, :saved_changes?
+ assert_equal ["lock_version", "updated_at"], p1.saved_changes.keys.sort
end
def test_touch_stale_object
@@ -193,6 +195,8 @@ class OptimisticLockingTest < ActiveRecord::TestCase
assert_raises(ActiveRecord::StaleObjectError) do
stale_person.touch
end
+
+ assert_not_predicate stale_person, :saved_changes?
end
def test_update_with_dirty_primary_key
@@ -296,6 +300,9 @@ class OptimisticLockingTest < ActiveRecord::TestCase
t1.touch
assert_equal 1, t1.lock_version
+ assert_not_predicate t1, :changed?
+ assert_predicate t1, :saved_changes?
+ assert_equal ["lock_version", "updated_at"], t1.saved_changes.keys.sort
end
def test_touch_stale_object_with_lock_without_default
@@ -307,6 +314,8 @@ class OptimisticLockingTest < ActiveRecord::TestCase
assert_raises(ActiveRecord::StaleObjectError) do
stale_object.touch
end
+
+ assert_not_predicate stale_object, :saved_changes?
end
def test_lock_without_default_should_work_with_null_in_the_database
diff --git a/activerecord/test/cases/migration/column_attributes_test.rb b/activerecord/test/cases/migration/column_attributes_test.rb
index 6f9190c110..b6064500ee 100644
--- a/activerecord/test/cases/migration/column_attributes_test.rb
+++ b/activerecord/test/cases/migration/column_attributes_test.rb
@@ -176,9 +176,9 @@ module ActiveRecord
if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
def test_out_of_range_limit_should_raise
- assert_raise(ActiveRecordError) { add_column :test_models, :integer_too_big, :integer, limit: 10 }
- assert_raise(ActiveRecordError) { add_column :test_models, :text_too_big, :text, limit: 0xfffffffff }
- assert_raise(ActiveRecordError) { add_column :test_models, :binary_too_big, :binary, limit: 0xfffffffff }
+ assert_raise(ArgumentError) { add_column :test_models, :integer_too_big, :integer, limit: 10 }
+ assert_raise(ArgumentError) { add_column :test_models, :text_too_big, :text, limit: 0xfffffffff }
+ assert_raise(ArgumentError) { add_column :test_models, :binary_too_big, :binary, limit: 0xfffffffff }
end
end
end
diff --git a/activerecord/test/cases/migration/command_recorder_test.rb b/activerecord/test/cases/migration/command_recorder_test.rb
index 01f8628fc5..c9f3756b1f 100644
--- a/activerecord/test/cases/migration/command_recorder_test.rb
+++ b/activerecord/test/cases/migration/command_recorder_test.rb
@@ -182,6 +182,40 @@ module ActiveRecord
assert_equal [:change_column_default, [:table, :column, from: false, to: true]], change
end
+ if ActiveRecord::Base.connection.supports_comments?
+ def test_invert_change_column_comment
+ assert_raises(ActiveRecord::IrreversibleMigration) do
+ @recorder.inverse_of :change_column_comment, [:table, :column, "comment"]
+ end
+ end
+
+ def test_invert_change_column_comment_with_from_and_to
+ change = @recorder.inverse_of :change_column_comment, [:table, :column, from: "old_value", to: "new_value"]
+ assert_equal [:change_column_comment, [:table, :column, from: "new_value", to: "old_value"]], change
+ end
+
+ def test_invert_change_column_comment_with_from_and_to_with_nil
+ change = @recorder.inverse_of :change_column_comment, [:table, :column, from: nil, to: "new_value"]
+ assert_equal [:change_column_comment, [:table, :column, from: "new_value", to: nil]], change
+ end
+
+ def test_invert_change_table_comment
+ assert_raises(ActiveRecord::IrreversibleMigration) do
+ @recorder.inverse_of :change_column_comment, [:table, :column, "comment"]
+ end
+ end
+
+ def test_invert_change_table_comment_with_from_and_to
+ change = @recorder.inverse_of :change_table_comment, [:table, from: "old_value", to: "new_value"]
+ assert_equal [:change_table_comment, [:table, from: "new_value", to: "old_value"]], change
+ end
+
+ def test_invert_change_table_comment_with_from_and_to_with_nil
+ change = @recorder.inverse_of :change_table_comment, [:table, from: nil, to: "new_value"]
+ assert_equal [:change_table_comment, [:table, from: "new_value", to: nil]], change
+ end
+ end
+
def test_invert_change_column_null
add = @recorder.inverse_of :change_column_null, [:table, :column, true]
assert_equal [:change_column_null, [:table, :column, false]], add
diff --git a/activerecord/test/cases/migration/compatibility_test.rb b/activerecord/test/cases/migration/compatibility_test.rb
index 5753bd7117..726ccf925e 100644
--- a/activerecord/test/cases/migration/compatibility_test.rb
+++ b/activerecord/test/cases/migration/compatibility_test.rb
@@ -220,6 +220,35 @@ module ActiveRecord
end
end
+ if ActiveRecord::Base.connection.supports_comments?
+ def test_change_column_comment_can_be_reverted
+ migration = Class.new(ActiveRecord::Migration[5.2]) {
+ def migrate(x)
+ revert do
+ change_column_comment(:testings, :foo, "comment")
+ end
+ end
+ }.new
+
+ ActiveRecord::Migrator.new(:up, [migration]).migrate
+ assert connection.column_exists?(:testings, :foo, comment: "comment")
+ end
+
+ def test_change_table_comment_can_be_reverted
+ migration = Class.new(ActiveRecord::Migration[5.2]) {
+ def migrate(x)
+ revert do
+ change_table_comment(:testings, "comment")
+ end
+ end
+ }.new
+
+ ActiveRecord::Migrator.new(:up, [migration]).migrate
+
+ assert_equal "comment", connection.table_comment("testings")
+ end
+ end
+
if current_adapter?(:PostgreSQLAdapter)
class Testing < ActiveRecord::Base
end
@@ -242,9 +271,9 @@ module ActiveRecord
private
def precision_implicit_default
if current_adapter?(:Mysql2Adapter)
- { presicion: 0 }
+ { precision: 0 }
else
- { presicion: nil }
+ { precision: nil }
end
end
end
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index f10c26c308..8e8ed494d9 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -583,7 +583,7 @@ class MigrationTest < ActiveRecord::TestCase
if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
def test_out_of_range_integer_limit_should_raise
- e = assert_raise(ActiveRecord::ActiveRecordError, "integer limit didn't raise") do
+ e = assert_raise(ArgumentError) do
Person.connection.create_table :test_integer_limits, force: true do |t|
t.column :bigone, :integer, limit: 10
end
@@ -595,7 +595,7 @@ class MigrationTest < ActiveRecord::TestCase
end
def test_out_of_range_text_limit_should_raise
- e = assert_raise(ActiveRecord::ActiveRecordError, "text limit didn't raise") do
+ e = assert_raise(ArgumentError) do
Person.connection.create_table :test_text_limits, force: true do |t|
t.text :bigtext, limit: 0xfffffffff
end
@@ -607,15 +607,15 @@ class MigrationTest < ActiveRecord::TestCase
end
def test_out_of_range_binary_limit_should_raise
- e = assert_raise(ActiveRecord::ActiveRecordError) do
- Person.connection.create_table :test_text_limits, force: true do |t|
+ e = assert_raise(ArgumentError) do
+ Person.connection.create_table :test_binary_limits, force: true do |t|
t.binary :bigbinary, limit: 0xfffffffff
end
end
assert_includes e.message, "No binary type has byte size #{0xfffffffff}"
ensure
- Person.connection.drop_table :test_text_limits, if_exists: true
+ Person.connection.drop_table :test_binary_limits, if_exists: true
end
end
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index 90b208092f..3f370e5ede 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -292,6 +292,7 @@ module ActiveRecord
klass.create!(description: "foo")
assert_equal ["foo"], klass.select(:description).from(klass.all).map(&:desc)
+ assert_equal ["foo"], klass.reselect(:description).from(klass.all).map(&:desc)
end
def test_relation_merging_with_merged_joins_as_strings
diff --git a/activerecord/test/cases/time_precision_test.rb b/activerecord/test/cases/time_precision_test.rb
index 2f534ea110..1abd857216 100644
--- a/activerecord/test/cases/time_precision_test.rb
+++ b/activerecord/test/cases/time_precision_test.rb
@@ -75,7 +75,7 @@ if subsecond_precision_supported?
end
def test_invalid_time_precision_raises_error
- assert_raises ActiveRecord::ActiveRecordError do
+ assert_raises ArgumentError do
@connection.create_table(:foos, force: true) do |t|
t.time :start, precision: 7
t.time :finish, precision: 7
diff --git a/activerecord/test/cases/timestamp_test.rb b/activerecord/test/cases/timestamp_test.rb
index 75ecd6fc40..232e018e03 100644
--- a/activerecord/test/cases/timestamp_test.rb
+++ b/activerecord/test/cases/timestamp_test.rb
@@ -40,17 +40,25 @@ class TimestampTest < ActiveRecord::TestCase
assert_not_equal @previously_updated_at, @developer.updated_at
assert_equal previous_salary + 10000, @developer.salary
- assert @developer.salary_changed?, "developer salary should have changed"
- assert @developer.changed?, "developer should be marked as changed"
+ assert_predicate @developer, :salary_changed?, "developer salary should have changed"
+ assert_predicate @developer, :changed?, "developer should be marked as changed"
+ assert_equal ["salary"], @developer.changed
+ assert_predicate @developer, :saved_changes?
+ assert_equal ["updated_at", "updated_on"], @developer.saved_changes.keys.sort
+
@developer.reload
assert_equal previous_salary, @developer.salary
end
def test_touching_a_record_with_default_scope_that_excludes_it_updates_its_timestamp
developer = @developer.becomes(DeveloperCalledJamis)
-
developer.touch
+
assert_not_equal @previously_updated_at, developer.updated_at
+ assert_not_predicate developer, :changed?
+ assert_predicate developer, :saved_changes?
+ assert_equal ["updated_at", "updated_on"], developer.saved_changes.keys.sort
+
developer.reload
assert_not_equal @previously_updated_at, developer.updated_at
end
diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb
index e88d20a453..53fe31e087 100644
--- a/activerecord/test/cases/transaction_callbacks_test.rb
+++ b/activerecord/test/cases/transaction_callbacks_test.rb
@@ -111,6 +111,32 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
assert_equal [:after_commit], @first.history
end
+ def test_dont_call_any_callbacks_after_transaction_commits_for_invalid_record
+ @first.after_commit_block { |r| r.history << :after_commit }
+ @first.after_rollback_block { |r| r.history << :after_rollback }
+
+ def @first.valid?(*)
+ false
+ end
+
+ assert_not @first.save
+ assert_equal [], @first.history
+ end
+
+ def test_dont_call_any_callbacks_after_explicit_transaction_commits_for_invalid_record
+ @first.after_commit_block { |r| r.history << :after_commit }
+ @first.after_rollback_block { |r| r.history << :after_rollback }
+
+ def @first.valid?(*)
+ false
+ end
+
+ @first.transaction do
+ assert_not @first.save
+ end
+ assert_equal [], @first.history
+ end
+
def test_only_call_after_commit_on_save_after_transaction_commits_for_saving_record
record = TopicWithCallbacks.new(title: "New topic", written_on: Date.today)
record.after_commit_block(:save) { |r| r.history << :after_save }
@@ -598,7 +624,7 @@ class TransactionEnrollmentCallbacksTest < ActiveRecord::TestCase
@topic.content = "foo"
@topic.save!
end
- @topic.class.connection.add_transaction_record(@topic)
+ @topic.send(:add_to_transaction)
end
assert_equal [:before_commit, :after_commit], @topic.history
end
@@ -608,7 +634,7 @@ class TransactionEnrollmentCallbacksTest < ActiveRecord::TestCase
@topic.transaction(requires_new: true) do
@topic.content = "foo"
@topic.save!
- @topic.class.connection.add_transaction_record(@topic)
+ @topic.send(:add_to_transaction)
end
end
assert_equal [:before_commit, :after_commit], @topic.history
@@ -629,7 +655,7 @@ class TransactionEnrollmentCallbacksTest < ActiveRecord::TestCase
@topic.content = "foo"
@topic.save!
end
- @topic.class.connection.add_transaction_record(@topic)
+ @topic.send(:add_to_transaction)
raise ActiveRecord::Rollback
end
assert_equal [:rollback], @topic.history
diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb
index 1009dd0f99..7bad3de343 100644
--- a/activerecord/test/cases/transactions_test.rb
+++ b/activerecord/test/cases/transactions_test.rb
@@ -26,28 +26,31 @@ class TransactionTest < ActiveRecord::TestCase
def test_raise_after_destroy
assert_not_predicate @first, :frozen?
- assert_raises(RuntimeError) {
- Topic.transaction do
- @first.destroy
- assert_predicate @first, :frozen?
- raise
+ assert_not_called(@first, :rolledback!) do
+ assert_raises(RuntimeError) do
+ Topic.transaction do
+ @first.destroy
+ assert_predicate @first, :frozen?
+ raise
+ end
end
- }
+ end
- assert @first.reload
assert_not_predicate @first, :frozen?
end
def test_successful
- Topic.transaction do
- @first.approved = true
- @second.approved = false
- @first.save
- @second.save
+ assert_not_called(@first, :committed!) do
+ Topic.transaction do
+ @first.approved = true
+ @second.approved = false
+ @first.save
+ @second.save
+ end
end
- assert Topic.find(1).approved?, "First should have been approved"
- assert_not Topic.find(2).approved?, "Second should have been unapproved"
+ assert_predicate Topic.find(1), :approved?, "First should have been approved"
+ assert_not_predicate Topic.find(2), :approved?, "Second should have been unapproved"
end
def transaction_with_return
@@ -62,7 +65,7 @@ class TransactionTest < ActiveRecord::TestCase
def test_add_to_null_transaction
topic = Topic.new
- topic.add_to_transaction
+ topic.send(:add_to_transaction)
end
def test_successful_with_return
@@ -76,11 +79,13 @@ class TransactionTest < ActiveRecord::TestCase
end
end
- transaction_with_return
+ assert_not_called(@first, :committed!) do
+ transaction_with_return
+ end
assert committed
- assert Topic.find(1).approved?, "First should have been approved"
- assert_not Topic.find(2).approved?, "Second should have been unapproved"
+ assert_predicate Topic.find(1), :approved?, "First should have been approved"
+ assert_not_predicate Topic.find(2), :approved?, "Second should have been unapproved"
ensure
Topic.connection.class_eval do
remove_method :commit_db_transaction
@@ -99,9 +104,11 @@ class TransactionTest < ActiveRecord::TestCase
end
end
- Topic.transaction do
- @first.approved = true
- @first.save!
+ assert_not_called(@first, :committed!) do
+ Topic.transaction do
+ @first.approved = true
+ @first.save!
+ end
end
assert_equal 0, num
@@ -113,19 +120,21 @@ class TransactionTest < ActiveRecord::TestCase
end
def test_successful_with_instance_method
- @first.transaction do
- @first.approved = true
- @second.approved = false
- @first.save
- @second.save
+ assert_not_called(@first, :committed!) do
+ @first.transaction do
+ @first.approved = true
+ @second.approved = false
+ @first.save
+ @second.save
+ end
end
- assert Topic.find(1).approved?, "First should have been approved"
- assert_not Topic.find(2).approved?, "Second should have been unapproved"
+ assert_predicate Topic.find(1), :approved?, "First should have been approved"
+ assert_not_predicate Topic.find(2), :approved?, "Second should have been unapproved"
end
def test_failing_on_exception
- begin
+ assert_not_called(@first, :rolledback!) do
Topic.transaction do
@first.approved = true
@second.approved = false
@@ -137,11 +146,11 @@ class TransactionTest < ActiveRecord::TestCase
# caught it
end
- assert @first.approved?, "First should still be changed in the objects"
- assert_not @second.approved?, "Second should still be changed in the objects"
+ assert_predicate @first, :approved?, "First should still be changed in the objects"
+ assert_not_predicate @second, :approved?, "Second should still be changed in the objects"
- assert_not Topic.find(1).approved?, "First shouldn't have been approved"
- assert Topic.find(2).approved?, "Second should still be approved"
+ assert_not_predicate Topic.find(1), :approved?, "First shouldn't have been approved"
+ assert_predicate Topic.find(2), :approved?, "Second should still be approved"
end
def test_raising_exception_in_callback_rollbacks_in_save
@@ -150,8 +159,10 @@ class TransactionTest < ActiveRecord::TestCase
end
@first.approved = true
- e = assert_raises(RuntimeError) { @first.save }
- assert_equal "Make the transaction rollback", e.message
+ assert_not_called(@first, :rolledback!) do
+ e = assert_raises(RuntimeError) { @first.save }
+ assert_equal "Make the transaction rollback", e.message
+ end
assert_not_predicate Topic.find(1), :approved?
end
@@ -159,13 +170,15 @@ class TransactionTest < ActiveRecord::TestCase
def @first.before_save_for_transaction
raise ActiveRecord::Rollback
end
- assert_not @first.approved
+ assert_not_predicate @first, :approved?
- Topic.transaction do
- @first.approved = true
- @first.save!
+ assert_not_called(@first, :rolledback!) do
+ Topic.transaction do
+ @first.approved = true
+ @first.save!
+ end
end
- assert_not Topic.find(@first.id).approved?, "Should not commit the approved flag"
+ assert_not_predicate Topic.find(@first.id), :approved?, "Should not commit the approved flag"
end
def test_raising_exception_in_nested_transaction_restore_state_in_save
@@ -175,11 +188,13 @@ class TransactionTest < ActiveRecord::TestCase
raise "Make the transaction rollback"
end
- assert_raises(RuntimeError) do
- Topic.transaction { topic.save }
+ assert_not_called(topic, :rolledback!) do
+ assert_raises(RuntimeError) do
+ Topic.transaction { topic.save }
+ end
end
- assert topic.new_record?, "#{topic.inspect} should be new record"
+ assert_predicate topic, :new_record?, "#{topic.inspect} should be new record"
end
def test_transaction_state_is_cleared_when_record_is_persisted
diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb
index 9a70934b7e..4f98a6b7fc 100644
--- a/activerecord/test/cases/validations_test.rb
+++ b/activerecord/test/cases/validations_test.rb
@@ -145,15 +145,17 @@ class ValidationsTest < ActiveRecord::TestCase
end
def test_validates_acceptance_of_with_undefined_attribute_methods
- Topic.validates_acceptance_of(:approved)
- topic = Topic.new(approved: true)
- Topic.undefine_attribute_methods
+ klass = Class.new(Topic)
+ klass.validates_acceptance_of(:approved)
+ topic = klass.new(approved: true)
+ klass.undefine_attribute_methods
assert topic.approved
end
def test_validates_acceptance_of_as_database_column
- Topic.validates_acceptance_of(:approved)
- topic = Topic.create("approved" => true)
+ klass = Class.new(Topic)
+ klass.validates_acceptance_of(:approved)
+ topic = klass.create("approved" => true)
assert topic["approved"]
end
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index 395b534c63..c34968590f 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -11,6 +11,10 @@ class Post < ActiveRecord::Base
def author
"lifo"
end
+
+ def greeting
+ super + " :)"
+ end
end
module NamedExtension2
diff --git a/activerecord/test/models/section.rb b/activerecord/test/models/section.rb
new file mode 100644
index 0000000000..f8b4cc7936
--- /dev/null
+++ b/activerecord/test/models/section.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+class Section < ActiveRecord::Base
+ belongs_to :session, inverse_of: :sections, autosave: true
+ belongs_to :seminar, inverse_of: :sections, autosave: true
+end
diff --git a/activerecord/test/models/seminar.rb b/activerecord/test/models/seminar.rb
new file mode 100644
index 0000000000..c18aa86433
--- /dev/null
+++ b/activerecord/test/models/seminar.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+class Seminar < ActiveRecord::Base
+ has_many :sections, inverse_of: :seminar, autosave: true, dependent: :destroy
+ has_many :sessions, through: :sections
+end
diff --git a/activerecord/test/models/session.rb b/activerecord/test/models/session.rb
new file mode 100644
index 0000000000..db66b5297e
--- /dev/null
+++ b/activerecord/test/models/session.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+class Session < ActiveRecord::Base
+ has_many :sections, inverse_of: :session, autosave: true, dependent: :destroy
+ has_many :seminars, through: :sections
+end
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 548671045b..7d9b8afeb6 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -792,6 +792,24 @@ ActiveRecord::Schema.define do
t.integer :lock_version, default: 0
end
+ disable_referential_integrity do
+ create_table :seminars, force: :cascade do |t|
+ t.string :name
+ end
+
+ create_table :sessions, force: :cascade do |t|
+ t.date :start_date
+ t.date :end_date
+ t.string :name
+ end
+
+ create_table :sections, force: :cascade do |t|
+ t.string :short_name
+ t.belongs_to :session, foreign_key: true
+ t.belongs_to :seminar, foreign_key: true
+ end
+ end
+
create_table :shape_expressions, force: true do |t|
t.string :paint_type
t.integer :paint_id