activerecord 2.3.5 → 2.3.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG +33 -0
- data/Rakefile +1 -1
- data/examples/performance.sql +85 -0
- data/lib/active_record.rb +1 -2
- data/lib/active_record/association_preload.rb +9 -2
- data/lib/active_record/associations.rb +48 -38
- data/lib/active_record/associations/association_collection.rb +15 -11
- data/lib/active_record/associations/association_proxy.rb +16 -6
- data/lib/active_record/associations/belongs_to_association.rb +11 -1
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +34 -10
- data/lib/active_record/associations/has_many_association.rb +5 -0
- data/lib/active_record/associations/has_many_through_association.rb +5 -5
- data/lib/active_record/associations/has_one_association.rb +10 -1
- data/lib/active_record/attribute_methods.rb +5 -1
- data/lib/active_record/autosave_association.rb +66 -35
- data/lib/active_record/base.rb +77 -36
- data/lib/active_record/batches.rb +13 -9
- data/lib/active_record/calculations.rb +6 -3
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +57 -0
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/quoting.rb +3 -7
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +64 -10
- data/lib/active_record/connection_adapters/abstract_adapter.rb +2 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +31 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +31 -66
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +2 -2
- data/lib/active_record/dirty.rb +2 -2
- data/lib/active_record/fixtures.rb +1 -0
- data/lib/active_record/locking/optimistic.rb +34 -1
- data/lib/active_record/migration.rb +5 -0
- data/lib/active_record/nested_attributes.rb +64 -52
- data/lib/active_record/reflection.rb +66 -1
- data/lib/active_record/schema.rb +5 -1
- data/lib/active_record/schema_dumper.rb +3 -0
- data/lib/active_record/serializers/json_serializer.rb +1 -1
- data/lib/active_record/validations.rb +13 -1
- data/lib/active_record/version.rb +1 -1
- data/test/cases/active_schema_test_mysql.rb +22 -0
- data/test/cases/associations/belongs_to_associations_test.rb +13 -0
- data/test/cases/associations/eager_load_nested_include_test.rb +8 -7
- data/test/cases/associations/eager_test.rb +7 -1
- data/test/cases/associations/has_many_associations_test.rb +26 -0
- data/test/cases/associations/inverse_associations_test.rb +566 -0
- data/test/cases/associations_test.rb +10 -0
- data/test/cases/autosave_association_test.rb +86 -10
- data/test/cases/base_test.rb +29 -0
- data/test/cases/batches_test.rb +20 -0
- data/test/cases/calculations_test.rb +2 -3
- data/test/cases/encoding_test.rb +6 -0
- data/test/cases/finder_test.rb +19 -3
- data/test/cases/fixtures_test.rb +5 -0
- data/test/cases/json_serialization_test.rb +14 -0
- data/test/cases/locking_test.rb +48 -3
- data/test/cases/migration_test.rb +115 -0
- data/test/cases/modules_test.rb +28 -0
- data/test/cases/named_scope_test.rb +1 -1
- data/test/cases/nested_attributes_test.rb +239 -7
- data/test/cases/query_cache_test.rb +7 -1
- data/test/cases/reflection_test.rb +47 -7
- data/test/cases/schema_test_postgresql.rb +2 -2
- data/test/cases/validations_i18n_test.rb +6 -36
- data/test/cases/validations_test.rb +33 -1
- data/test/cases/yaml_serialization_test.rb +11 -0
- data/test/fixtures/faces.yml +11 -0
- data/test/fixtures/fixture_database.sqlite +0 -0
- data/test/fixtures/fixture_database.sqlite3 +0 -0
- data/test/fixtures/fixture_database_2.sqlite +0 -0
- data/test/fixtures/fixture_database_2.sqlite3 +0 -0
- data/test/fixtures/interests.yml +33 -0
- data/test/fixtures/men.yml +5 -0
- data/test/fixtures/zines.yml +5 -0
- data/test/models/author.rb +3 -0
- data/test/models/bird.rb +6 -0
- data/test/models/company_in_module.rb +17 -0
- data/test/models/event_author.rb +5 -0
- data/test/models/face.rb +7 -0
- data/test/models/interest.rb +5 -0
- data/test/models/invoice.rb +4 -0
- data/test/models/line_item.rb +3 -0
- data/test/models/man.rb +9 -0
- data/test/models/parrot.rb +6 -0
- data/test/models/pirate.rb +10 -0
- data/test/models/ship.rb +10 -1
- data/test/models/ship_part.rb +3 -1
- data/test/models/zine.rb +3 -0
- data/test/schema/schema.rb +41 -0
- metadata +37 -11
- data/lib/active_record/i18n_interpolation_deprecation.rb +0 -26
@@ -137,11 +137,11 @@ class SchemaTest < ActiveRecord::TestCase
|
|
137
137
|
|
138
138
|
def test_with_uppercase_index_name
|
139
139
|
ActiveRecord::Base.connection.execute "CREATE INDEX \"things_Index\" ON #{SCHEMA_NAME}.things (name)"
|
140
|
-
assert_nothing_raised { ActiveRecord::Base.connection.remove_index
|
140
|
+
assert_nothing_raised { ActiveRecord::Base.connection.remove_index! "things", "#{SCHEMA_NAME}.things_Index"}
|
141
141
|
|
142
142
|
ActiveRecord::Base.connection.execute "CREATE INDEX \"things_Index\" ON #{SCHEMA_NAME}.things (name)"
|
143
143
|
ActiveRecord::Base.connection.schema_search_path = SCHEMA_NAME
|
144
|
-
assert_nothing_raised { ActiveRecord::Base.connection.remove_index
|
144
|
+
assert_nothing_raised { ActiveRecord::Base.connection.remove_index! "things", "things_Index"}
|
145
145
|
ActiveRecord::Base.connection.schema_search_path = "public"
|
146
146
|
end
|
147
147
|
|
@@ -27,42 +27,6 @@ module ActiveRecordValidationsI18nTestHelper
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
# DEPRECATIONS
|
31
|
-
|
32
|
-
class ActiveRecordValidationsI18nDeprecationsTests < ActiveSupport::TestCase
|
33
|
-
test "default_error_messages is deprecated and can be removed in Rails 3 / ActiveModel" do
|
34
|
-
assert_deprecated('ActiveRecord::Errors.default_error_messages') do
|
35
|
-
ActiveRecord::Errors.default_error_messages
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
test "%s interpolation syntax in error messages still works" do
|
40
|
-
ActiveSupport::Deprecation.silence do
|
41
|
-
result = I18n.t :does_not_exist, :default => "%s interpolation syntax is deprecated", :value => 'this'
|
42
|
-
assert_equal result, "this interpolation syntax is deprecated"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
test "%s interpolation syntax in error messages is deprecated" do
|
47
|
-
assert_deprecated('using %s in messages') do
|
48
|
-
I18n.t :does_not_exist, :default => "%s interpolation syntax is deprected", :value => 'this'
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
test "%d interpolation syntax in error messages still works" do
|
53
|
-
ActiveSupport::Deprecation.silence do
|
54
|
-
result = I18n.t :does_not_exist, :default => "%d interpolation syntaxes are deprecated", :count => 2
|
55
|
-
assert_equal result, "2 interpolation syntaxes are deprecated"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
test "%d interpolation syntax in error messages is deprecated" do
|
60
|
-
assert_deprecated('using %d in messages') do
|
61
|
-
I18n.t :does_not_exist, :default => "%d interpolation syntaxes are deprected", :count => 2
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
30
|
|
67
31
|
# ACTIVERECORD VALIDATIONS
|
68
32
|
#
|
@@ -521,6 +485,12 @@ class ActiveRecordErrorI18nTests < ActiveSupport::TestCase
|
|
521
485
|
assert_equal message, ActiveRecord::Error.new(@reply, *args).full_message
|
522
486
|
end
|
523
487
|
|
488
|
+
test ":default is only given to message if a symbol is supplied" do
|
489
|
+
store_translations(:errors => { :messages => { :"foo bar" => "You fooed: {{value}}." } })
|
490
|
+
@reply.errors.add(:title, :inexistent, :default => "foo bar")
|
491
|
+
assert_equal "foo bar", @reply.errors[:title]
|
492
|
+
end
|
493
|
+
|
524
494
|
test "#generate_message passes the model attribute value for interpolation" do
|
525
495
|
store_translations(:errors => { :messages => { :foo => "You fooed: {{value}}." } })
|
526
496
|
@reply.title = "da title"
|
@@ -9,6 +9,8 @@ require 'models/guid'
|
|
9
9
|
require 'models/owner'
|
10
10
|
require 'models/pet'
|
11
11
|
require 'models/event'
|
12
|
+
require 'models/man'
|
13
|
+
require 'models/interest'
|
12
14
|
|
13
15
|
# The following methods in Topic are used in test_conditional_validation_*
|
14
16
|
class Topic
|
@@ -186,7 +188,7 @@ class ValidationsTest < ActiveRecord::TestCase
|
|
186
188
|
end
|
187
189
|
end
|
188
190
|
|
189
|
-
def
|
191
|
+
def test_single_error_string_per_attr_iteration
|
190
192
|
r = Reply.new
|
191
193
|
r.save
|
192
194
|
|
@@ -197,6 +199,17 @@ class ValidationsTest < ActiveRecord::TestCase
|
|
197
199
|
assert errors.include?(["content", "Empty"])
|
198
200
|
end
|
199
201
|
|
202
|
+
def test_single_error_object_per_attr_iteration
|
203
|
+
r = Reply.new
|
204
|
+
r.save
|
205
|
+
|
206
|
+
errors = []
|
207
|
+
r.errors.each_error { |attr, error| errors << [attr, error.attribute] }
|
208
|
+
|
209
|
+
assert errors.include?(["title", "title"])
|
210
|
+
assert errors.include?(["content", "content"])
|
211
|
+
end
|
212
|
+
|
200
213
|
def test_multiple_errors_per_attr_iteration_with_full_error_composition
|
201
214
|
r = Reply.new
|
202
215
|
r.title = "Wrong Create"
|
@@ -356,6 +369,25 @@ class ValidationsTest < ActiveRecord::TestCase
|
|
356
369
|
assert t.save
|
357
370
|
end
|
358
371
|
|
372
|
+
def test_validates_presence_of_belongs_to_association__parent_is_new_record
|
373
|
+
repair_validations(Interest) do
|
374
|
+
# Note that Interest and Man have the :inverse_of option set
|
375
|
+
Interest.validates_presence_of(:man)
|
376
|
+
man = Man.new(:name => 'John')
|
377
|
+
interest = man.interests.build(:topic => 'Airplanes')
|
378
|
+
assert interest.valid?, "Expected interest to be valid, but was not. Interest should have a man object associated"
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
def test_validates_presence_of_belongs_to_association__existing_parent
|
383
|
+
repair_validations(Interest) do
|
384
|
+
Interest.validates_presence_of(:man)
|
385
|
+
man = Man.create!(:name => 'John')
|
386
|
+
interest = man.interests.build(:topic => 'Airplanes')
|
387
|
+
assert interest.valid?, "Expected interest to be valid, but was not. Interest should have a man object associated"
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
359
391
|
def test_validate_uniqueness
|
360
392
|
Topic.validates_uniqueness_of(:title)
|
361
393
|
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/topic'
|
3
|
+
|
4
|
+
class YamlSerializationTest < ActiveRecord::TestCase
|
5
|
+
def test_to_yaml_with_time_with_zone_should_not_raise_exception
|
6
|
+
Time.zone = ActiveSupport::TimeZone["Pacific Time (US & Canada)"]
|
7
|
+
ActiveRecord::Base.time_zone_aware_attributes = true
|
8
|
+
topic = Topic.new(:written_on => DateTime.now)
|
9
|
+
assert_nothing_raised { topic.to_yaml }
|
10
|
+
end
|
11
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,33 @@
|
|
1
|
+
trainspotting:
|
2
|
+
topic: Trainspotting
|
3
|
+
zine: staying_in
|
4
|
+
man: gordon
|
5
|
+
|
6
|
+
birdwatching:
|
7
|
+
topic: Birdwatching
|
8
|
+
zine: staying_in
|
9
|
+
man: gordon
|
10
|
+
|
11
|
+
stamp_collecting:
|
12
|
+
topic: Stamp Collecting
|
13
|
+
zine: staying_in
|
14
|
+
man: gordon
|
15
|
+
|
16
|
+
hunting:
|
17
|
+
topic: Hunting
|
18
|
+
zine: going_out
|
19
|
+
man: steve
|
20
|
+
|
21
|
+
woodsmanship:
|
22
|
+
topic: Woodsmanship
|
23
|
+
zine: going_out
|
24
|
+
man: steve
|
25
|
+
|
26
|
+
survival:
|
27
|
+
topic: Survival
|
28
|
+
zine: going_out
|
29
|
+
man: steve
|
30
|
+
|
31
|
+
llama_wrangling:
|
32
|
+
topic: Llama Wrangling
|
33
|
+
polymorphic_man: gordon (Man)
|
data/test/models/author.rb
CHANGED
@@ -88,6 +88,9 @@ class Author < ActiveRecord::Base
|
|
88
88
|
has_many :tags, :through => :posts # through has_many :through
|
89
89
|
has_many :post_categories, :through => :posts, :source => :categories
|
90
90
|
|
91
|
+
has_many :event_authors
|
92
|
+
has_many :events, :through => :event_authors
|
93
|
+
|
91
94
|
has_one :essay, :primary_key => :name, :as => :writer
|
92
95
|
|
93
96
|
belongs_to :author_address, :dependent => :destroy
|
data/test/models/bird.rb
CHANGED
@@ -30,6 +30,23 @@ module MyApplication
|
|
30
30
|
has_and_belongs_to_many :developers
|
31
31
|
end
|
32
32
|
|
33
|
+
module Prefixed
|
34
|
+
def self.table_name_prefix
|
35
|
+
'prefixed_'
|
36
|
+
end
|
37
|
+
|
38
|
+
class Company < ActiveRecord::Base
|
39
|
+
end
|
40
|
+
|
41
|
+
class Firm < Company
|
42
|
+
self.table_name = 'companies'
|
43
|
+
end
|
44
|
+
|
45
|
+
module Nested
|
46
|
+
class Company < ActiveRecord::Base
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
33
50
|
end
|
34
51
|
|
35
52
|
module Billing
|
data/test/models/face.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
class Face < ActiveRecord::Base
|
2
|
+
belongs_to :man, :inverse_of => :face
|
3
|
+
belongs_to :polymorphic_man, :polymorphic => true, :inverse_of => :polymorphic_face
|
4
|
+
# These is a "broken" inverse_of for the purposes of testing
|
5
|
+
belongs_to :horrible_man, :class_name => 'Man', :inverse_of => :horrible_face
|
6
|
+
belongs_to :horrible_polymorphic_man, :polymorphic => true, :inverse_of => :horrible_polymorphic_face
|
7
|
+
end
|
data/test/models/man.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
class Man < ActiveRecord::Base
|
2
|
+
has_one :face, :inverse_of => :man
|
3
|
+
has_one :polymorphic_face, :class_name => 'Face', :as => :polymorphic_man, :inverse_of => :polymorphic_man
|
4
|
+
has_many :interests, :inverse_of => :man
|
5
|
+
has_many :polymorphic_interests, :class_name => 'Interest', :as => :polymorphic_man, :inverse_of => :polymorphic_man
|
6
|
+
# These are "broken" inverse_of associations for the purposes of testing
|
7
|
+
has_one :dirty_face, :class_name => 'Face', :inverse_of => :dirty_man
|
8
|
+
has_many :secret_interests, :class_name => 'Interest', :inverse_of => :secret_man
|
9
|
+
end
|
data/test/models/parrot.rb
CHANGED
@@ -6,6 +6,12 @@ class Parrot < ActiveRecord::Base
|
|
6
6
|
alias_attribute :title, :name
|
7
7
|
|
8
8
|
validates_presence_of :name
|
9
|
+
|
10
|
+
attr_accessor :cancel_save_from_callback
|
11
|
+
before_save :cancel_save_callback_method, :if => :cancel_save_from_callback
|
12
|
+
def cancel_save_callback_method
|
13
|
+
false
|
14
|
+
end
|
9
15
|
end
|
10
16
|
|
11
17
|
class LiveParrot < Parrot
|
data/test/models/pirate.rb
CHANGED
@@ -19,6 +19,7 @@ class Pirate < ActiveRecord::Base
|
|
19
19
|
|
20
20
|
# These both have :autosave enabled because accepts_nested_attributes_for is used on them.
|
21
21
|
has_one :ship
|
22
|
+
has_one :update_only_ship, :class_name => 'Ship'
|
22
23
|
has_one :non_validated_ship, :class_name => 'Ship'
|
23
24
|
has_many :birds
|
24
25
|
has_many :birds_with_method_callbacks, :class_name => "Bird",
|
@@ -31,11 +32,14 @@ class Pirate < ActiveRecord::Base
|
|
31
32
|
:after_add => proc {|p,b| p.ship_log << "after_adding_proc_bird_#{b.id || '<new>'}"},
|
32
33
|
:before_remove => proc {|p,b| p.ship_log << "before_removing_proc_bird_#{b.id}"},
|
33
34
|
:after_remove => proc {|p,b| p.ship_log << "after_removing_proc_bird_#{b.id}"}
|
35
|
+
has_many :birds_with_reject_all_blank, :class_name => "Bird"
|
34
36
|
|
35
37
|
accepts_nested_attributes_for :parrots, :birds, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
|
36
38
|
accepts_nested_attributes_for :ship, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
|
39
|
+
accepts_nested_attributes_for :update_only_ship, :update_only => true
|
37
40
|
accepts_nested_attributes_for :parrots_with_method_callbacks, :parrots_with_proc_callbacks,
|
38
41
|
:birds_with_method_callbacks, :birds_with_proc_callbacks, :allow_destroy => true
|
42
|
+
accepts_nested_attributes_for :birds_with_reject_all_blank, :reject_if => :all_blank
|
39
43
|
|
40
44
|
validates_presence_of :catchphrase
|
41
45
|
|
@@ -47,6 +51,12 @@ class Pirate < ActiveRecord::Base
|
|
47
51
|
attributes.delete('_reject_me_if_new').present? && new_record?
|
48
52
|
end
|
49
53
|
|
54
|
+
attr_accessor :cancel_save_from_callback
|
55
|
+
before_save :cancel_save_callback_method, :if => :cancel_save_from_callback
|
56
|
+
def cancel_save_callback_method
|
57
|
+
false
|
58
|
+
end
|
59
|
+
|
50
60
|
private
|
51
61
|
def log_before_add(record)
|
52
62
|
log(record, "before_adding_method")
|
data/test/models/ship.rb
CHANGED
@@ -2,9 +2,18 @@ class Ship < ActiveRecord::Base
|
|
2
2
|
self.record_timestamps = false
|
3
3
|
|
4
4
|
belongs_to :pirate
|
5
|
-
|
5
|
+
belongs_to :update_only_pirate, :class_name => 'Pirate'
|
6
|
+
has_many :parts, :class_name => 'ShipPart'
|
6
7
|
|
8
|
+
accepts_nested_attributes_for :parts, :allow_destroy => true
|
7
9
|
accepts_nested_attributes_for :pirate, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
|
10
|
+
accepts_nested_attributes_for :update_only_pirate, :update_only => true
|
8
11
|
|
9
12
|
validates_presence_of :name
|
13
|
+
|
14
|
+
attr_accessor :cancel_save_from_callback
|
15
|
+
before_save :cancel_save_callback_method, :if => :cancel_save_from_callback
|
16
|
+
def cancel_save_callback_method
|
17
|
+
false
|
18
|
+
end
|
10
19
|
end
|
data/test/models/ship_part.rb
CHANGED
data/test/models/zine.rb
ADDED
data/test/schema/schema.rb
CHANGED
@@ -58,6 +58,7 @@ ActiveRecord::Schema.define do
|
|
58
58
|
|
59
59
|
create_table :birds, :force => true do |t|
|
60
60
|
t.string :name
|
61
|
+
t.string :color
|
61
62
|
t.integer :pirate_id
|
62
63
|
end
|
63
64
|
|
@@ -174,6 +175,12 @@ ActiveRecord::Schema.define do
|
|
174
175
|
|
175
176
|
create_table :events, :force => true do |t|
|
176
177
|
t.string :title, :limit => 5
|
178
|
+
t.datetime :ends_on
|
179
|
+
end
|
180
|
+
|
181
|
+
create_table :event_authors, :force => true do |t|
|
182
|
+
t.integer :event_id
|
183
|
+
t.integer :author_id
|
177
184
|
end
|
178
185
|
|
179
186
|
create_table :funny_jokes, :force => true do |t|
|
@@ -185,6 +192,11 @@ ActiveRecord::Schema.define do
|
|
185
192
|
t.string :info
|
186
193
|
end
|
187
194
|
|
195
|
+
create_table :invoices, :force => true do |t|
|
196
|
+
t.integer :balance
|
197
|
+
t.datetime :updated_at
|
198
|
+
end
|
199
|
+
|
188
200
|
create_table :items, :force => true do |t|
|
189
201
|
t.column :name, :integer
|
190
202
|
end
|
@@ -210,6 +222,11 @@ ActiveRecord::Schema.define do
|
|
210
222
|
t.integer :version, :null => false, :default => 0
|
211
223
|
end
|
212
224
|
|
225
|
+
create_table :line_items, :force => true do |t|
|
226
|
+
t.integer :invoice_id
|
227
|
+
t.integer :amount
|
228
|
+
end
|
229
|
+
|
213
230
|
create_table :lock_without_defaults, :force => true do |t|
|
214
231
|
t.column :lock_version, :integer
|
215
232
|
end
|
@@ -479,6 +496,30 @@ ActiveRecord::Schema.define do
|
|
479
496
|
end
|
480
497
|
end
|
481
498
|
|
499
|
+
# NOTE - the following 4 tables are used by models that have :inverse_of options on the associations
|
500
|
+
create_table :men, :force => true do |t|
|
501
|
+
t.string :name
|
502
|
+
end
|
503
|
+
|
504
|
+
create_table :faces, :force => true do |t|
|
505
|
+
t.string :description
|
506
|
+
t.integer :man_id
|
507
|
+
t.integer :polymorphic_man_id
|
508
|
+
t.string :polymorphic_man_type
|
509
|
+
end
|
510
|
+
|
511
|
+
create_table :interests, :force => true do |t|
|
512
|
+
t.string :topic
|
513
|
+
t.integer :man_id
|
514
|
+
t.integer :polymorphic_man_id
|
515
|
+
t.string :polymorphic_man_type
|
516
|
+
t.integer :zine_id
|
517
|
+
end
|
518
|
+
|
519
|
+
create_table :zines, :force => true do |t|
|
520
|
+
t.string :title
|
521
|
+
end
|
522
|
+
|
482
523
|
except 'SQLite' do
|
483
524
|
# fk_test_has_fk should be before fk_test_has_pk
|
484
525
|
create_table :fk_test_has_fk, :force => true do |t|
|