activerecord 1.12.2 → 1.13.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 (66) hide show
  1. data/CHANGELOG +92 -0
  2. data/README +9 -9
  3. data/lib/active_record/acts/list.rb +1 -1
  4. data/lib/active_record/acts/nested_set.rb +13 -13
  5. data/lib/active_record/acts/tree.rb +7 -6
  6. data/lib/active_record/aggregations.rb +4 -4
  7. data/lib/active_record/associations.rb +82 -21
  8. data/lib/active_record/associations/association_collection.rb +0 -8
  9. data/lib/active_record/associations/association_proxy.rb +5 -2
  10. data/lib/active_record/associations/belongs_to_association.rb +6 -2
  11. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +11 -1
  12. data/lib/active_record/associations/has_many_association.rb +34 -5
  13. data/lib/active_record/associations/has_one_association.rb +1 -1
  14. data/lib/active_record/base.rb +144 -59
  15. data/lib/active_record/callbacks.rb +6 -6
  16. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -2
  17. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +4 -4
  18. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +10 -8
  19. data/lib/active_record/connection_adapters/abstract_adapter.rb +1 -1
  20. data/lib/active_record/connection_adapters/db2_adapter.rb +17 -1
  21. data/lib/active_record/connection_adapters/oci_adapter.rb +322 -185
  22. data/lib/active_record/connection_adapters/sqlite_adapter.rb +9 -8
  23. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +107 -14
  24. data/lib/active_record/fixtures.rb +10 -8
  25. data/lib/active_record/migration.rb +20 -6
  26. data/lib/active_record/observer.rb +4 -3
  27. data/lib/active_record/reflection.rb +5 -5
  28. data/lib/active_record/transactions.rb +2 -2
  29. data/lib/active_record/validations.rb +70 -40
  30. data/lib/active_record/vendor/mysql411.rb +9 -13
  31. data/lib/active_record/version.rb +2 -2
  32. data/rakefile +1 -1
  33. data/test/abstract_unit.rb +5 -0
  34. data/test/ar_schema_test.rb +1 -1
  35. data/test/associations_extensions_test.rb +37 -0
  36. data/test/associations_go_eager_test.rb +25 -0
  37. data/test/associations_test.rb +14 -6
  38. data/test/base_test.rb +63 -45
  39. data/test/connections/native_sqlite/connection.rb +2 -2
  40. data/test/connections/native_sqlite3/connection.rb +2 -2
  41. data/test/connections/native_sqlite3/in_memory_connection.rb +1 -1
  42. data/test/debug.log +2857 -0
  43. data/test/deprecated_finder_test.rb +3 -9
  44. data/test/finder_test.rb +27 -13
  45. data/test/fixtures/author.rb +4 -0
  46. data/test/fixtures/comment.rb +4 -8
  47. data/test/fixtures/db_definitions/create_oracle_db.bat +0 -5
  48. data/test/fixtures/db_definitions/create_oracle_db.sh +0 -5
  49. data/test/fixtures/db_definitions/db2.drop.sql +0 -1
  50. data/test/fixtures/db_definitions/oci.sql +2 -0
  51. data/test/fixtures/db_definitions/sqlserver.drop.sql +1 -1
  52. data/test/fixtures/developer.rb +18 -1
  53. data/test/fixtures/fixture_database.sqlite +0 -0
  54. data/test/fixtures/fixture_database_2.sqlite +0 -0
  55. data/test/fixtures/migrations_with_duplicate/1_people_have_last_names.rb +9 -0
  56. data/test/fixtures/migrations_with_duplicate/2_we_need_reminders.rb +12 -0
  57. data/test/fixtures/migrations_with_duplicate/3_foo.rb +7 -0
  58. data/test/fixtures/migrations_with_duplicate/3_innocent_jointable.rb +12 -0
  59. data/test/fixtures/post.rb +18 -4
  60. data/test/fixtures/reply.rb +3 -1
  61. data/test/inheritance_test.rb +3 -2
  62. data/test/{conditions_scoping_test.rb → method_scoping_test.rb} +55 -10
  63. data/test/migration_test.rb +68 -31
  64. data/test/readonly_test.rb +65 -5
  65. data/test/validations_test.rb +10 -2
  66. metadata +13 -4
@@ -15,16 +15,10 @@ class DeprecatedFinderTest < Test::Unit::TestCase
15
15
  end
16
16
 
17
17
  def test_find_all_with_prepared_limit_and_offset
18
- if ActiveRecord::ConnectionAdapters.const_defined? :OracleAdapter
19
- if ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::OracleAdapter)
20
- assert_raises(ArgumentError) { Entrant.find_all nil, "id ASC", [2, 1] }
21
- end
22
- else
23
- entrants = Entrant.find_all nil, "id ASC", [2, 1]
18
+ entrants = Entrant.find_all nil, "id ASC", [2, 1]
24
19
 
25
- assert_equal(2, entrants.size)
26
- assert_equal(entrants(:second).name, entrants.first.name)
27
- end
20
+ assert_equal(2, entrants.size)
21
+ assert_equal(entrants(:second).name, entrants.first.name)
28
22
  end
29
23
 
30
24
  def test_find_first
@@ -47,20 +47,20 @@ class FinderTest < Test::Unit::TestCase
47
47
  end
48
48
 
49
49
  def test_find_all_with_prepared_limit_and_offset
50
- if ActiveRecord::ConnectionAdapters.const_defined? :OracleAdapter
51
- if ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::OracleAdapter)
52
- assert_raises(ArgumentError) { Entrant.find(:all, :order => 'id ASC', :limit => 2, :offset => 1) }
53
- end
54
- else
55
- entrants = Entrant.find(:all, :order => "id ASC", :limit => 2, :offset => 1)
50
+ entrants = Entrant.find(:all, :order => "id ASC", :limit => 2, :offset => 1)
56
51
 
57
- assert_equal(2, entrants.size)
58
- assert_equal(entrants(:second).name, entrants.first.name)
52
+ assert_equal(2, entrants.size)
53
+ assert_equal(entrants(:second).name, entrants.first.name)
59
54
 
60
- entrants = Entrant.find(:all, :order => "id ASC", :limit => 2, :offset => 2)
61
- assert_equal(1, entrants.size)
62
- assert_equal(entrants(:third).name, entrants.first.name)
63
- end
55
+ entrants = Entrant.find(:all, :order => "id ASC", :limit => 2, :offset => 2)
56
+ assert_equal(1, entrants.size)
57
+ assert_equal(entrants(:third).name, entrants.first.name)
58
+ end
59
+
60
+ def test_find_with_limit_and_condition
61
+ developers = Developer.find(:all, :order => "id DESC", :conditions => "salary = 100000", :limit => 3, :offset =>7)
62
+ assert_equal(1, developers.size)
63
+ assert_equal("fixture_3", developers.first.name)
64
64
  end
65
65
 
66
66
  def test_find_with_entire_select_statement
@@ -278,6 +278,20 @@ class FinderTest < Test::Unit::TestCase
278
278
  assert_equal "Mary", topics[0].author_name
279
279
  end
280
280
 
281
+ def test_find_or_create_from_one_attribute
282
+ number_of_companies = Company.count
283
+ sig38 = Company.find_or_create_by_name("38signals")
284
+ assert_equal number_of_companies + 1, Company.count
285
+ assert_equal sig38, Company.find_or_create_by_name("38signals")
286
+ end
287
+
288
+ def test_find_or_create_from_two_attributes
289
+ number_of_companies = Company.count
290
+ sig38 = Company.find_or_create_by_name("38signals")
291
+ assert_equal number_of_companies + 1, Company.count
292
+ assert_equal sig38, Company.find_or_create_by_name("38signals")
293
+ end
294
+
281
295
  def test_find_with_bad_sql
282
296
  assert_raises(ActiveRecord::StatementInvalid) { Topic.find_by_sql "select 1 from badtable" }
283
297
  end
@@ -339,7 +353,7 @@ class FinderTest < Test::Unit::TestCase
339
353
  end
340
354
 
341
355
  def test_select_values
342
- assert_equal ["1","2","3","4","5","6","7","8"], Company.connection.select_values("SELECT id FROM companies ORDER BY id")
356
+ assert_equal ["1","2","3","4","5","6","7","8"], Company.connection.select_values("SELECT id FROM companies ORDER BY id").map! { |i| i.to_s }
343
357
  assert_equal ["37signals","Summit","Microsoft", "Flamboyant Software", "Ex Nihilo", "RailsCore", "Leetsoft", "Jadedpixel"], Company.connection.select_values("SELECT name FROM companies ORDER BY id")
344
358
  end
345
359
 
@@ -1,5 +1,9 @@
1
1
  class Author < ActiveRecord::Base
2
2
  has_many :posts
3
+ has_many :posts_with_comments, :include => :comments, :class_name => "Post"
4
+ has_many :posts_with_categories, :include => :categories, :class_name => "Post"
5
+ has_many :posts_with_comments_and_categories, :include => [ :comments, :categories ], :class_name => "Post"
6
+
3
7
  has_many :posts_with_callbacks, :class_name => "Post", :before_add => :log_before_adding,
4
8
  :after_add => :log_after_adding, :before_remove => :log_before_removing,
5
9
  :after_remove => :log_after_removing
@@ -10,18 +10,14 @@ class Comment < ActiveRecord::Base
10
10
  end
11
11
  end
12
12
 
13
- class SpecialComment < Comment;
14
-
13
+ class SpecialComment < Comment
15
14
  def self.what_are_you
16
15
  'a special comment...'
17
16
  end
18
-
19
- end;
17
+ end
20
18
 
21
- class VerySpecialComment < Comment;
22
-
19
+ class VerySpecialComment < Comment
23
20
  def self.what_are_you
24
21
  'a very special comment...'
25
22
  end
26
-
27
- end;
23
+ end
@@ -1,5 +0,0 @@
1
- sqlplus arunit/arunit @ drop_oracle_tables
2
- sqlplus arunit/arunit @ oracle
3
- sqlplus arunit2/arunit2 @ drop_oracle_tables2
4
- sqlplus arunit2/arunit2 @ oracle2
5
-
@@ -1,5 +0,0 @@
1
- sqlplus arunit/arunit @ drop_oracle_tables
2
- sqlplus arunit/arunit @ oracle
3
- sqlplus arunit2/arunit2 @ drop_oracle_tables2
4
- sqlplus arunit2/arunit2 @ oracle2
5
-
@@ -6,7 +6,6 @@ DROP TABLE projects;
6
6
  DROP TABLE developers_projects;
7
7
  DROP TABLE orders;
8
8
  DROP TABLE customers;
9
- DROP TABLE orders;
10
9
  DROP TABLE movies;
11
10
  DROP TABLE subscribers;
12
11
  DROP TABLE booleantests;
@@ -259,3 +259,5 @@ create table keyboards (
259
259
  key_number integer not null,
260
260
  name varchar(50) default null
261
261
  );
262
+ create sequence keyboards_seq minvalue 10000;
263
+
@@ -22,6 +22,6 @@ DROP TABLE authors;
22
22
  DROP TABLE tasks;
23
23
  DROP TABLE categories;
24
24
  DROP TABLE categories_posts;
25
- DROP TABLE fk_test_has_pd;
26
25
  DROP TABLE fk_test_has_fk;
26
+ DROP TABLE fk_test_has_pk;
27
27
  DROP TABLE keyboards;
@@ -1,5 +1,22 @@
1
+ module DeveloperProjectsAssociationExtension
2
+ def find_most_recent
3
+ find(:first, :order => "id DESC")
4
+ end
5
+ end
6
+
1
7
  class Developer < ActiveRecord::Base
2
- has_and_belongs_to_many :projects
8
+ has_and_belongs_to_many :projects do
9
+ def find_most_recent
10
+ find(:first, :order => "id DESC")
11
+ end
12
+ end
13
+
14
+ has_and_belongs_to_many :projects_extended_by_name,
15
+ :class_name => "Project",
16
+ :join_table => "developers_projects",
17
+ :association_foreign_key => "project_id",
18
+ :extend => DeveloperProjectsAssociationExtension
19
+
3
20
  has_and_belongs_to_many :special_projects, :join_table => 'developers_projects', :association_foreign_key => 'project_id'
4
21
 
5
22
  validates_inclusion_of :salary, :in => 50000..200000
@@ -0,0 +1,9 @@
1
+ class PeopleHaveLastNames < ActiveRecord::Migration
2
+ def self.up
3
+ add_column "people", "last_name", :string
4
+ end
5
+
6
+ def self.down
7
+ remove_column "people", "last_name"
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ class WeNeedReminders < ActiveRecord::Migration
2
+ def self.up
3
+ create_table("reminders") do |t|
4
+ t.column :content, :text
5
+ t.column :remind_at, :datetime
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ drop_table "reminders"
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ class Foo < ActiveRecord::Migration
2
+ def self.up
3
+ end
4
+
5
+ def self.down
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ class InnocentJointable < ActiveRecord::Migration
2
+ def self.up
3
+ create_table("people_reminders", :id => false) do |t|
4
+ t.column :reminder_id, :integer
5
+ t.column :person_id, :integer
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ drop_table "people_reminders"
11
+ end
12
+ end
@@ -1,8 +1,22 @@
1
1
  class Post < ActiveRecord::Base
2
- belongs_to :author
3
- has_many :comments, :order => "body"
4
- has_one :very_special_comment, :class_name => "VerySpecialComment"
5
- has_many :special_comments, :class_name => "SpecialComment"
2
+ belongs_to :author do
3
+ def greeting
4
+ "hello"
5
+ end
6
+ end
7
+
8
+ belongs_to :author_with_posts, :class_name => "Author", :include => :posts
9
+
10
+ has_many :comments, :order => "body" do
11
+ def find_most_recent
12
+ find(:first, :order => "id DESC")
13
+ end
14
+ end
15
+
16
+ has_one :very_special_comment
17
+ has_one :very_special_comment_with_post, :class_name => "VerySpecialComment", :include => :post
18
+ has_many :special_comments
19
+
6
20
  has_and_belongs_to_many :categories
7
21
  has_and_belongs_to_many :special_categories, :join_table => "categories_posts"
8
22
 
@@ -1,3 +1,5 @@
1
+ require 'fixtures/topic'
2
+
1
3
  class Reply < Topic
2
4
  belongs_to :topic, :foreign_key => "parent_id", :counter_cache => true
3
5
  has_many :silly_replies, :dependent => true, :foreign_key => "parent_id"
@@ -31,4 +33,4 @@ class Reply < Topic
31
33
  end
32
34
 
33
35
  class SillyReply < Reply
34
- end
36
+ end
@@ -8,12 +8,13 @@ class InheritanceTest < Test::Unit::TestCase
8
8
 
9
9
  def test_a_bad_type_column
10
10
  #SQLServer need to turn Identity Insert On before manually inserting into the Identity column
11
- if ActiveRecord::ConnectionAdapters.const_defined? :SQLServerAdapter and ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::SQLServerAdapter)
11
+ if current_adapter?(:SQLServerAdapter)
12
12
  Company.connection.execute "SET IDENTITY_INSERT companies ON"
13
13
  end
14
14
  Company.connection.insert "INSERT INTO companies (id, type, name) VALUES(100, 'bad_class!', 'Not happening')"
15
+
15
16
  #We then need to turn it back Off before continuing.
16
- if ActiveRecord::ConnectionAdapters.const_defined? :SQLServerAdapter and ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::SQLServerAdapter)
17
+ if current_adapter?(:SQLServerAdapter)
17
18
  Company.connection.execute "SET IDENTITY_INSERT companies OFF"
18
19
  end
19
20
  assert_raises(ActiveRecord::SubclassNotFound) { Company.find(100) }
@@ -4,43 +4,78 @@ require 'fixtures/comment'
4
4
  require 'fixtures/post'
5
5
  require 'fixtures/category'
6
6
 
7
- class ConditionsScopingTest < Test::Unit::TestCase
8
- fixtures :developers
7
+ class MethodScopingTest < Test::Unit::TestCase
8
+ fixtures :developers, :comments, :posts
9
9
 
10
10
  def test_set_conditions
11
- Developer.constrain(:conditions => 'just a test...') do
12
- assert_equal 'just a test...', Thread.current[:constraints][Developer][:conditions]
11
+ Developer.with_scope(:find => { :conditions => 'just a test...' }) do
12
+ assert_equal 'just a test...', Thread.current[:scoped_methods][Developer][:find][:conditions]
13
13
  end
14
14
  end
15
15
 
16
16
  def test_scoped_find
17
- Developer.constrain(:conditions => "name = 'David'") do
17
+ Developer.with_scope(:find => { :conditions => "name = 'David'" }) do
18
18
  assert_nothing_raised { Developer.find(1) }
19
19
  end
20
20
  end
21
21
 
22
22
  def test_scoped_find_first
23
- Developer.constrain(:conditions => "salary = 100000") do
23
+ Developer.with_scope(:find => { :conditions => "salary = 100000" }) do
24
24
  assert_equal Developer.find(10), Developer.find(:first, :order => 'name')
25
25
  end
26
26
  end
27
27
 
28
28
  def test_scoped_find_all
29
- Developer.constrain(:conditions => "name = 'David'") do
29
+ Developer.with_scope(:find => { :conditions => "name = 'David'" }) do
30
30
  assert_equal [Developer.find(1)], Developer.find(:all)
31
31
  end
32
32
  end
33
33
 
34
34
  def test_scoped_count
35
- Developer.constrain(:conditions => "name = 'David'") do
35
+ Developer.with_scope(:find => { :conditions => "name = 'David'" }) do
36
36
  assert_equal 1, Developer.count
37
37
  end
38
38
 
39
- Developer.constrain(:conditions => 'salary = 100000') do
39
+ Developer.with_scope(:find => { :conditions => 'salary = 100000' }) do
40
40
  assert_equal 8, Developer.count
41
41
  assert_equal 1, Developer.count("name LIKE 'fixture_1%'")
42
42
  end
43
43
  end
44
+
45
+ def test_scoped_create
46
+ new_comment = nil
47
+
48
+ VerySpecialComment.with_scope(:create => { :post_id => 1 }) do
49
+ assert_equal({ :post_id => 1 }, Thread.current[:scoped_methods][VerySpecialComment][:create])
50
+ new_comment = VerySpecialComment.create :body => "Wonderful world"
51
+ end
52
+
53
+ assert Post.find(1).comments.include?(new_comment)
54
+ end
55
+
56
+ def test_immutable_scope
57
+ options = { :conditions => "name = 'David'" }
58
+ Developer.with_scope(:find => options) do
59
+ assert_equal %w(David), Developer.find(:all).map { |d| d.name }
60
+ options[:conditions] = "name != 'David'"
61
+ assert_equal %w(David), Developer.find(:all).map { |d| d.name }
62
+ end
63
+
64
+ scope = { :find => { :conditions => "name = 'David'" }}
65
+ Developer.with_scope(scope) do
66
+ assert_equal %w(David), Developer.find(:all).map { |d| d.name }
67
+ scope[:find][:conditions] = "name != 'David'"
68
+ assert_equal %w(David), Developer.find(:all).map { |d| d.name }
69
+ end
70
+ end
71
+
72
+ def test_raise_on_nested_scope
73
+ Developer.with_scope(:find => { :conditions => '1=1' }) do
74
+ assert_raise(ArgumentError) do
75
+ Developer.with_scope(:find => { :conditions => '2=2' }) { }
76
+ end
77
+ end
78
+ end
44
79
  end
45
80
 
46
81
  class HasManyScopingTest< Test::Unit::TestCase
@@ -64,7 +99,12 @@ class HasManyScopingTest< Test::Unit::TestCase
64
99
  assert_equal 4, Comment.find_all_by_type('Comment').size
65
100
  assert_equal 2, @welcome.comments.find_all_by_type('Comment').size
66
101
  end
67
-
102
+
103
+ def test_raise_on_nested_scope
104
+ Comment.with_scope(:find => { :conditions => '1=1' }) do
105
+ assert_raise(ArgumentError) { @welcome.comments.what_are_you }
106
+ end
107
+ end
68
108
  end
69
109
 
70
110
 
@@ -86,6 +126,11 @@ class HasAndBelongsToManyScopingTest< Test::Unit::TestCase
86
126
  assert_equal 2, @welcome.categories.find_all_by_type('Category').size
87
127
  end
88
128
 
129
+ def test_raise_on_nested_scope
130
+ Category.with_scope(:find => { :conditions => '1=1' }) do
131
+ assert_raise(ArgumentError) { @welcome.categories.what_are_you }
132
+ end
133
+ end
89
134
  end
90
135
 
91
136
 
@@ -4,7 +4,6 @@ require File.dirname(__FILE__) + '/fixtures/migrations/1_people_have_last_names'
4
4
  require File.dirname(__FILE__) + '/fixtures/migrations/2_we_need_reminders'
5
5
 
6
6
  if ActiveRecord::Base.connection.supports_migrations?
7
-
8
7
  class Reminder < ActiveRecord::Base; end
9
8
 
10
9
  class MigrationTest < Test::Unit::TestCase
@@ -19,6 +18,7 @@ if ActiveRecord::Base.connection.supports_migrations?
19
18
 
20
19
  Reminder.connection.drop_table("reminders") rescue nil
21
20
  Reminder.connection.drop_table("people_reminders") rescue nil
21
+ Reminder.connection.drop_table("prefix_reminders_suffix") rescue nil
22
22
  Reminder.reset_column_information
23
23
 
24
24
  Person.connection.remove_column("people", "last_name") rescue nil
@@ -84,19 +84,43 @@ if ActiveRecord::Base.connection.supports_migrations?
84
84
  four = columns.detect { |c| c.name == "four" }
85
85
 
86
86
  assert_equal "hello", one.default
87
- assert_equal true, two.default
88
- assert_equal false, three.default
87
+ if current_adapter?(:OCIAdapter)
88
+ # Oracle doesn't support native booleans
89
+ assert_equal true, two.default == 1
90
+ assert_equal false, three.default != 0
91
+ else
92
+ assert_equal true, two.default
93
+ assert_equal false, three.default
94
+ end
89
95
  assert_equal 1, four.default
90
96
 
91
97
  ensure
92
98
  Person.connection.drop_table :testings rescue nil
93
99
  end
94
100
 
95
- def test_add_column_not_null
101
+ # SQL Server will not allow you to add a NOT NULL column
102
+ # to a table without specifying a default value, so the
103
+ # following test must be skipped
104
+ unless current_adapter?(:SQLServerAdapter)
105
+ def test_add_column_not_null_without_default
106
+ Person.connection.create_table :testings do |t|
107
+ t.column :foo, :string
108
+ end
109
+ Person.connection.add_column :testings, :bar, :string, :null => false
110
+
111
+ assert_raises(ActiveRecord::StatementInvalid) do
112
+ Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)"
113
+ end
114
+ ensure
115
+ Person.connection.drop_table :testings rescue nil
116
+ end
117
+ end
118
+
119
+ def test_add_column_not_null_with_default
96
120
  Person.connection.create_table :testings do |t|
97
121
  t.column :foo, :string
98
122
  end
99
- Person.connection.add_column :testings, :bar, :string, :null => false
123
+ Person.connection.add_column :testings, :bar, :string, :null => false, :default => "default"
100
124
 
101
125
  assert_raises(ActiveRecord::StatementInvalid) do
102
126
  Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)"
@@ -128,7 +152,14 @@ if ActiveRecord::Base.connection.supports_migrations?
128
152
  assert_equal String, bob.bio.class
129
153
  assert_equal Fixnum, bob.age.class
130
154
  assert_equal Time, bob.birthday.class
131
- assert_equal Date, bob.favorite_day.class
155
+
156
+ if current_adapter?(:SQLServerAdapter) or current_adapter?(:OCIAdapter)
157
+ # SQL Server and Oracle don't differentiate between date/time
158
+ assert_equal Time, bob.favorite_day.class
159
+ else
160
+ assert_equal Date, bob.favorite_day.class
161
+ end
162
+
132
163
  assert_equal TrueClass, bob.male?.class
133
164
  end
134
165
 
@@ -162,11 +193,11 @@ if ActiveRecord::Base.connection.supports_migrations?
162
193
 
163
194
  def test_add_rename
164
195
  Person.delete_all
165
-
166
- Person.connection.add_column "people", "girlfriend", :string
167
- Person.create :girlfriend => 'bobette'
168
-
196
+
169
197
  begin
198
+ Person.connection.add_column "people", "girlfriend", :string
199
+ Person.create :girlfriend => 'bobette'
200
+
170
201
  Person.connection.rename_column "people", "girlfriend", "exgirlfriend"
171
202
 
172
203
  Person.reset_column_information
@@ -206,21 +237,26 @@ if ActiveRecord::Base.connection.supports_migrations?
206
237
  begin
207
238
  ActiveRecord::Base.connection.create_table :octopuses do |t|
208
239
  t.column :url, :string
209
- end
240
+ end
210
241
  ActiveRecord::Base.connection.rename_table :octopuses, :octopi
211
-
242
+
212
243
  assert_nothing_raised do
213
- ActiveRecord::Base.connection.execute "INSERT INTO octopi (url) VALUES ('http://www.foreverflying.com/octopus-black7.jpg')"
244
+ if current_adapter?(:OCIAdapter)
245
+ # Oracle requires the explicit sequence for the pk
246
+ ActiveRecord::Base.connection.execute "INSERT INTO octopi (id, url) VALUES (octopi_seq.nextval, 'http://www.foreverflying.com/octopus-black7.jpg')"
247
+ else
248
+ ActiveRecord::Base.connection.execute "INSERT INTO octopi (url) VALUES ('http://www.foreverflying.com/octopus-black7.jpg')"
249
+ end
214
250
  end
215
251
 
216
252
  assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
217
-
253
+
218
254
  ensure
219
255
  ActiveRecord::Base.connection.drop_table :octopuses rescue nil
220
256
  ActiveRecord::Base.connection.drop_table :octopi rescue nil
221
257
  end
222
258
  end
223
-
259
+
224
260
  def test_change_column
225
261
  Person.connection.add_column "people", "bio", :string
226
262
  assert_nothing_raised { Person.connection.change_column "people", "bio", :text }
@@ -237,8 +273,8 @@ if ActiveRecord::Base.connection.supports_migrations?
237
273
  end
238
274
 
239
275
  def test_add_table
240
- assert_raises(ActiveRecord::StatementInvalid) { Reminder.column_methods_hash }
241
-
276
+ assert !Reminder.table_exists?
277
+
242
278
  WeNeedReminders.up
243
279
 
244
280
  assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
@@ -250,7 +286,7 @@ if ActiveRecord::Base.connection.supports_migrations?
250
286
 
251
287
  def test_migrator
252
288
  assert !Person.column_methods_hash.include?(:last_name)
253
- assert_raises(ActiveRecord::StatementInvalid) { Reminder.column_methods_hash }
289
+ assert !Reminder.table_exists?
254
290
 
255
291
  ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/')
256
292
 
@@ -270,14 +306,13 @@ if ActiveRecord::Base.connection.supports_migrations?
270
306
 
271
307
  def test_migrator_one_up
272
308
  assert !Person.column_methods_hash.include?(:last_name)
273
- assert_raises(ActiveRecord::StatementInvalid) { Reminder.column_methods_hash }
274
-
309
+ assert !Reminder.table_exists?
310
+
275
311
  ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
276
312
 
277
313
  Person.reset_column_information
278
314
  assert Person.column_methods_hash.include?(:last_name)
279
- assert_raises(ActiveRecord::StatementInvalid) { Reminder.column_methods_hash }
280
-
315
+ assert !Reminder.table_exists?
281
316
 
282
317
  ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 2)
283
318
 
@@ -292,7 +327,7 @@ if ActiveRecord::Base.connection.supports_migrations?
292
327
 
293
328
  Person.reset_column_information
294
329
  assert Person.column_methods_hash.include?(:last_name)
295
- assert_raises(ActiveRecord::StatementInvalid) { Reminder.column_methods_hash }
330
+ assert !Reminder.table_exists?
296
331
  end
297
332
 
298
333
  def test_migrator_one_up_one_down
@@ -300,7 +335,7 @@ if ActiveRecord::Base.connection.supports_migrations?
300
335
  ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0)
301
336
 
302
337
  assert !Person.column_methods_hash.include?(:last_name)
303
- assert_raises(ActiveRecord::StatementInvalid) { Reminder.column_methods_hash }
338
+ assert !Reminder.table_exists?
304
339
  end
305
340
 
306
341
  def test_migrator_going_down_due_to_version_target
@@ -308,7 +343,7 @@ if ActiveRecord::Base.connection.supports_migrations?
308
343
  ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations/', 0)
309
344
 
310
345
  assert !Person.column_methods_hash.include?(:last_name)
311
- assert_raises(ActiveRecord::StatementInvalid) { Reminder.column_methods_hash }
346
+ assert !Reminder.table_exists?
312
347
 
313
348
  ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations/')
314
349
 
@@ -359,13 +394,11 @@ if ActiveRecord::Base.connection.supports_migrations?
359
394
  end
360
395
 
361
396
  def test_add_drop_table_with_prefix_and_suffix
362
- assert_raises(ActiveRecord::StatementInvalid) { Reminder.column_methods_hash }
363
-
397
+ assert !Reminder.table_exists?
364
398
  ActiveRecord::Base.table_name_prefix = 'prefix_'
365
399
  ActiveRecord::Base.table_name_suffix = '_suffix'
366
400
  Reminder.reset_table_name
367
401
  WeNeedReminders.up
368
-
369
402
  assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
370
403
  assert_equal "hello world", Reminder.find(:first).content
371
404
 
@@ -375,7 +408,11 @@ if ActiveRecord::Base.connection.supports_migrations?
375
408
  ActiveRecord::Base.table_name_suffix = ''
376
409
  Reminder.reset_table_name
377
410
  end
378
-
379
- end
380
-
411
+
412
+ def test_migrator_with_duplicates
413
+ assert_raises(ActiveRecord::DuplicateMigrationVersionError) do
414
+ ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations_with_duplicate/', nil)
415
+ end
416
+ end
417
+ end
381
418
  end