activerecord 1.14.4 → 1.15.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG +400 -1
- data/README +2 -2
- data/RUNNING_UNIT_TESTS +21 -3
- data/Rakefile +55 -10
- data/lib/active_record.rb +10 -4
- data/lib/active_record/acts/list.rb +15 -4
- data/lib/active_record/acts/nested_set.rb +11 -12
- data/lib/active_record/acts/tree.rb +13 -14
- data/lib/active_record/aggregations.rb +46 -22
- data/lib/active_record/associations.rb +213 -162
- data/lib/active_record/associations/association_collection.rb +45 -15
- data/lib/active_record/associations/association_proxy.rb +32 -13
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +18 -18
- data/lib/active_record/associations/has_many_association.rb +37 -17
- data/lib/active_record/associations/has_many_through_association.rb +120 -30
- data/lib/active_record/associations/has_one_association.rb +1 -1
- data/lib/active_record/attribute_methods.rb +75 -0
- data/lib/active_record/base.rb +282 -203
- data/lib/active_record/calculations.rb +95 -54
- data/lib/active_record/callbacks.rb +13 -24
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +12 -1
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb.rej +21 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +30 -4
- data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -9
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +121 -37
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +55 -23
- data/lib/active_record/connection_adapters/abstract_adapter.rb +8 -0
- data/lib/active_record/connection_adapters/db2_adapter.rb +1 -11
- data/lib/active_record/connection_adapters/firebird_adapter.rb +364 -50
- data/lib/active_record/connection_adapters/frontbase_adapter.rb +861 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +86 -33
- data/lib/active_record/connection_adapters/openbase_adapter.rb +4 -3
- data/lib/active_record/connection_adapters/oracle_adapter.rb +151 -127
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +125 -48
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +38 -10
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +183 -155
- data/lib/active_record/connection_adapters/sybase_adapter.rb +190 -212
- data/lib/active_record/deprecated_associations.rb +24 -10
- data/lib/active_record/deprecated_finders.rb +4 -1
- data/lib/active_record/fixtures.rb +37 -23
- data/lib/active_record/locking/optimistic.rb +106 -0
- data/lib/active_record/locking/pessimistic.rb +77 -0
- data/lib/active_record/migration.rb +8 -5
- data/lib/active_record/observer.rb +73 -34
- data/lib/active_record/reflection.rb +21 -7
- data/lib/active_record/schema_dumper.rb +33 -5
- data/lib/active_record/timestamp.rb +23 -34
- data/lib/active_record/transactions.rb +37 -30
- data/lib/active_record/validations.rb +46 -30
- data/lib/active_record/vendor/mysql.rb +20 -5
- data/lib/active_record/version.rb +2 -2
- data/lib/active_record/wrappings.rb +1 -2
- data/lib/active_record/xml_serialization.rb +308 -0
- data/test/aaa_create_tables_test.rb +5 -1
- data/test/abstract_unit.rb +18 -8
- data/test/{active_schema_mysql.rb → active_schema_test_mysql.rb} +2 -2
- data/test/adapter_test.rb +9 -7
- data/test/adapter_test_sqlserver.rb +81 -0
- data/test/aggregations_test.rb +29 -0
- data/test/{association_callbacks_test.rb → associations/callbacks_test.rb} +10 -8
- data/test/{associations_cascaded_eager_loading_test.rb → associations/cascaded_eager_loading_test.rb} +35 -3
- data/test/{associations_go_eager_test.rb → associations/eager_test.rb} +36 -2
- data/test/{associations_extensions_test.rb → associations/extension_test.rb} +5 -0
- data/test/{associations_join_model_test.rb → associations/join_model_test.rb} +118 -8
- data/test/associations_test.rb +339 -45
- data/test/attribute_methods_test.rb +49 -0
- data/test/base_test.rb +321 -67
- data/test/calculations_test.rb +48 -10
- data/test/callbacks_test.rb +13 -0
- data/test/connection_test_firebird.rb +8 -0
- data/test/connections/native_db2/connection.rb +18 -17
- data/test/connections/native_firebird/connection.rb +19 -17
- data/test/connections/native_frontbase/connection.rb +27 -0
- data/test/connections/native_mysql/connection.rb +18 -15
- data/test/connections/native_openbase/connection.rb +14 -15
- data/test/connections/native_oracle/connection.rb +16 -12
- data/test/connections/native_postgresql/connection.rb +16 -17
- data/test/connections/native_sqlite/connection.rb +3 -6
- data/test/connections/native_sqlite3/connection.rb +3 -6
- data/test/connections/native_sqlserver/connection.rb +16 -17
- data/test/connections/native_sqlserver_odbc/connection.rb +18 -19
- data/test/connections/native_sybase/connection.rb +16 -17
- data/test/datatype_test_postgresql.rb +52 -0
- data/test/defaults_test.rb +52 -10
- data/test/deprecated_associations_test.rb +151 -107
- data/test/deprecated_finder_test.rb +83 -66
- data/test/empty_date_time_test.rb +25 -0
- data/test/finder_test.rb +118 -11
- data/test/fixtures/accounts.yml +6 -1
- data/test/fixtures/author.rb +27 -4
- data/test/fixtures/categorizations.yml +8 -2
- data/test/fixtures/category.rb +1 -2
- data/test/fixtures/comments.yml +0 -6
- data/test/fixtures/companies.yml +6 -1
- data/test/fixtures/company.rb +23 -1
- data/test/fixtures/company_in_module.rb +8 -10
- data/test/fixtures/customer.rb +2 -2
- data/test/fixtures/customers.yml +9 -0
- data/test/fixtures/db_definitions/db2.drop.sql +1 -0
- data/test/fixtures/db_definitions/db2.sql +9 -0
- data/test/fixtures/db_definitions/firebird.drop.sql +3 -0
- data/test/fixtures/db_definitions/firebird.sql +13 -1
- data/test/fixtures/db_definitions/frontbase.drop.sql +31 -0
- data/test/fixtures/db_definitions/frontbase.sql +262 -0
- data/test/fixtures/db_definitions/frontbase2.drop.sql +1 -0
- data/test/fixtures/db_definitions/frontbase2.sql +4 -0
- data/test/fixtures/db_definitions/mysql.drop.sql +1 -0
- data/test/fixtures/db_definitions/mysql.sql +23 -14
- data/test/fixtures/db_definitions/openbase.sql +13 -1
- data/test/fixtures/db_definitions/oracle.drop.sql +2 -0
- data/test/fixtures/db_definitions/oracle.sql +29 -2
- data/test/fixtures/db_definitions/postgresql.drop.sql +3 -1
- data/test/fixtures/db_definitions/postgresql.sql +13 -3
- data/test/fixtures/db_definitions/schema.rb +29 -1
- data/test/fixtures/db_definitions/sqlite.drop.sql +1 -0
- data/test/fixtures/db_definitions/sqlite.sql +12 -3
- data/test/fixtures/db_definitions/sqlserver.drop.sql +3 -0
- data/test/fixtures/db_definitions/sqlserver.sql +35 -0
- data/test/fixtures/db_definitions/sybase.drop.sql +2 -0
- data/test/fixtures/db_definitions/sybase.sql +13 -4
- data/test/fixtures/developer.rb +12 -0
- data/test/fixtures/edge.rb +5 -0
- data/test/fixtures/edges.yml +6 -0
- data/test/fixtures/funny_jokes.yml +3 -7
- data/test/fixtures/migrations_with_decimal/1_give_me_big_numbers.rb +15 -0
- data/test/fixtures/migrations_with_missing_versions/1000_people_have_middle_names.rb +9 -0
- data/test/fixtures/migrations_with_missing_versions/1_people_have_last_names.rb +9 -0
- data/test/fixtures/migrations_with_missing_versions/3_we_need_reminders.rb +12 -0
- data/test/fixtures/migrations_with_missing_versions/4_innocent_jointable.rb +12 -0
- data/test/fixtures/mixin.rb +15 -0
- data/test/fixtures/mixins.yml +38 -0
- data/test/fixtures/post.rb +3 -2
- data/test/fixtures/project.rb +3 -1
- data/test/fixtures/topic.rb +6 -1
- data/test/fixtures/topics.yml +4 -4
- data/test/fixtures/vertex.rb +9 -0
- data/test/fixtures/vertices.yml +4 -0
- data/test/fixtures_test.rb +45 -0
- data/test/inheritance_test.rb +67 -6
- data/test/lifecycle_test.rb +40 -19
- data/test/locking_test.rb +170 -26
- data/test/method_scoping_test.rb +2 -2
- data/test/migration_test.rb +387 -110
- data/test/migration_test_firebird.rb +124 -0
- data/test/mixin_nested_set_test.rb +14 -2
- data/test/mixin_test.rb +56 -18
- data/test/modules_test.rb +8 -2
- data/test/multiple_db_test.rb +2 -2
- data/test/pk_test.rb +1 -0
- data/test/reflection_test.rb +8 -2
- data/test/schema_authorization_test_postgresql.rb +75 -0
- data/test/schema_dumper_test.rb +40 -4
- data/test/table_name_test_sqlserver.rb +23 -0
- data/test/threaded_connections_test.rb +19 -16
- data/test/transactions_test.rb +86 -72
- data/test/validations_test.rb +126 -56
- data/test/xml_serialization_test.rb +125 -0
- metadata +45 -11
- data/lib/active_record/locking.rb +0 -79
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
require 'fixtures/course'
|
3
|
+
|
4
|
+
class FirebirdMigrationTest < Test::Unit::TestCase
|
5
|
+
self.use_transactional_fixtures = false
|
6
|
+
|
7
|
+
def setup
|
8
|
+
# using Course connection for tests -- need a db that doesn't already have a BOOLEAN domain
|
9
|
+
@connection = Course.connection
|
10
|
+
@fireruby_connection = @connection.instance_variable_get(:@connection)
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown
|
14
|
+
@connection.drop_table :foo rescue nil
|
15
|
+
@connection.execute("DROP DOMAIN D_BOOLEAN") rescue nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_create_table_with_custom_sequence_name
|
19
|
+
assert_nothing_raised do
|
20
|
+
@connection.create_table(:foo, :sequence => 'foo_custom_seq') do |f|
|
21
|
+
f.column :bar, :string
|
22
|
+
end
|
23
|
+
end
|
24
|
+
assert !sequence_exists?('foo_seq')
|
25
|
+
assert sequence_exists?('foo_custom_seq')
|
26
|
+
|
27
|
+
assert_nothing_raised { @connection.drop_table(:foo, :sequence => 'foo_custom_seq') }
|
28
|
+
assert !sequence_exists?('foo_custom_seq')
|
29
|
+
ensure
|
30
|
+
FireRuby::Generator.new('foo_custom_seq', @fireruby_connection).drop rescue nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_create_table_without_sequence
|
34
|
+
assert_nothing_raised do
|
35
|
+
@connection.create_table(:foo, :sequence => false) do |f|
|
36
|
+
f.column :bar, :string
|
37
|
+
end
|
38
|
+
end
|
39
|
+
assert !sequence_exists?('foo_seq')
|
40
|
+
assert_nothing_raised { @connection.drop_table :foo }
|
41
|
+
|
42
|
+
assert_nothing_raised do
|
43
|
+
@connection.create_table(:foo, :id => false) do |f|
|
44
|
+
f.column :bar, :string
|
45
|
+
end
|
46
|
+
end
|
47
|
+
assert !sequence_exists?('foo_seq')
|
48
|
+
assert_nothing_raised { @connection.drop_table :foo }
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_create_table_with_boolean_column
|
52
|
+
assert !boolean_domain_exists?
|
53
|
+
assert_nothing_raised do
|
54
|
+
@connection.create_table :foo do |f|
|
55
|
+
f.column :bar, :string
|
56
|
+
f.column :baz, :boolean
|
57
|
+
end
|
58
|
+
end
|
59
|
+
assert boolean_domain_exists?
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_add_boolean_column
|
63
|
+
assert !boolean_domain_exists?
|
64
|
+
@connection.create_table :foo do |f|
|
65
|
+
f.column :bar, :string
|
66
|
+
end
|
67
|
+
|
68
|
+
assert_nothing_raised { @connection.add_column :foo, :baz, :boolean }
|
69
|
+
assert boolean_domain_exists?
|
70
|
+
assert_equal :boolean, @connection.columns(:foo).find { |c| c.name == "baz" }.type
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_change_column_to_boolean
|
74
|
+
assert !boolean_domain_exists?
|
75
|
+
# Manually create table with a SMALLINT column, which can be changed to a BOOLEAN
|
76
|
+
@connection.execute "CREATE TABLE foo (bar SMALLINT)"
|
77
|
+
assert_equal :integer, @connection.columns(:foo).find { |c| c.name == "bar" }.type
|
78
|
+
|
79
|
+
assert_nothing_raised { @connection.change_column :foo, :bar, :boolean }
|
80
|
+
assert boolean_domain_exists?
|
81
|
+
assert_equal :boolean, @connection.columns(:foo).find { |c| c.name == "bar" }.type
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_rename_table_with_data_and_index
|
85
|
+
@connection.create_table :foo do |f|
|
86
|
+
f.column :baz, :string, :limit => 50
|
87
|
+
end
|
88
|
+
100.times { |i| @connection.execute "INSERT INTO foo VALUES (GEN_ID(foo_seq, 1), 'record #{i+1}')" }
|
89
|
+
@connection.add_index :foo, :baz
|
90
|
+
|
91
|
+
assert_nothing_raised { @connection.rename_table :foo, :bar }
|
92
|
+
assert !@connection.tables.include?("foo")
|
93
|
+
assert @connection.tables.include?("bar")
|
94
|
+
assert_equal "index_bar_on_baz", @connection.indexes("bar").first.name
|
95
|
+
assert_equal 100, FireRuby::Generator.new("bar_seq", @fireruby_connection).last
|
96
|
+
assert_equal 100, @connection.select_one("SELECT COUNT(*) FROM bar")["count"]
|
97
|
+
ensure
|
98
|
+
@connection.drop_table :bar rescue nil
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_renaming_table_with_fk_constraint_raises_error
|
102
|
+
@connection.create_table :parent do |p|
|
103
|
+
p.column :name, :string
|
104
|
+
end
|
105
|
+
@connection.create_table :child do |c|
|
106
|
+
c.column :parent_id, :integer
|
107
|
+
end
|
108
|
+
@connection.execute "ALTER TABLE child ADD CONSTRAINT fk_child_parent FOREIGN KEY(parent_id) REFERENCES parent(id)"
|
109
|
+
assert_raise(ActiveRecord::ActiveRecordError) { @connection.rename_table :child, :descendant }
|
110
|
+
ensure
|
111
|
+
@connection.drop_table :child rescue nil
|
112
|
+
@connection.drop_table :descendant rescue nil
|
113
|
+
@connection.drop_table :parent rescue nil
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
def boolean_domain_exists?
|
118
|
+
!@connection.select_one("SELECT 1 FROM rdb$fields WHERE rdb$field_name = 'D_BOOLEAN'").nil?
|
119
|
+
end
|
120
|
+
|
121
|
+
def sequence_exists?(sequence_name)
|
122
|
+
FireRuby::Generator.exists?(sequence_name, @fireruby_connection)
|
123
|
+
end
|
124
|
+
end
|
@@ -178,7 +178,19 @@ class MixinNestedSetTest < Test::Unit::TestCase
|
|
178
178
|
mixins(:set_1).add_child mixins(:set_4)
|
179
179
|
|
180
180
|
assert_equal( 3, mixins(:set_1).all_children.length )
|
181
|
-
|
182
|
-
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_inheritance
|
184
|
+
parent = mixins(:sti_set_3100)
|
185
|
+
child = mixins(:sti_set_3101)
|
186
|
+
grandchild = mixins(:sti_set_3102)
|
187
|
+
assert_equal 5, parent.full_set.size
|
188
|
+
assert_equal 2, child.full_set.size
|
189
|
+
assert_equal 4, parent.all_children.size
|
190
|
+
assert_equal 1, child.all_children.size
|
191
|
+
assert_equal 2, parent.direct_children.size
|
192
|
+
assert_equal 1, child.direct_children.size
|
193
|
+
child.destroy
|
194
|
+
assert_equal 3, parent.full_set.size
|
183
195
|
end
|
184
196
|
end
|
data/test/mixin_test.rb
CHANGED
@@ -4,6 +4,23 @@ require 'active_record/acts/list'
|
|
4
4
|
require 'active_record/acts/nested_set'
|
5
5
|
require 'fixtures/mixin'
|
6
6
|
|
7
|
+
# Let us control what Time.now returns for the TouchTest suite
|
8
|
+
class Time
|
9
|
+
@@forced_now_time = nil
|
10
|
+
cattr_accessor :forced_now_time
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def now_with_forcing
|
14
|
+
if @@forced_now_time
|
15
|
+
@@forced_now_time
|
16
|
+
else
|
17
|
+
now_without_forcing
|
18
|
+
end
|
19
|
+
end
|
20
|
+
alias_method_chain :now, :forcing
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
7
24
|
class ListTest < Test::Unit::TestCase
|
8
25
|
fixtures :mixins
|
9
26
|
|
@@ -200,10 +217,12 @@ class TreeTest < Test::Unit::TestCase
|
|
200
217
|
fixtures :mixins
|
201
218
|
|
202
219
|
def test_has_child
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
220
|
+
assert_deprecated 'has_children?' do
|
221
|
+
assert_equal true, mixins(:tree_1).has_children?
|
222
|
+
assert_equal true, mixins(:tree_2).has_children?
|
223
|
+
assert_equal false, mixins(:tree_3).has_children?
|
224
|
+
assert_equal false, mixins(:tree_4).has_children?
|
225
|
+
end
|
207
226
|
end
|
208
227
|
|
209
228
|
def test_children
|
@@ -214,10 +233,12 @@ class TreeTest < Test::Unit::TestCase
|
|
214
233
|
end
|
215
234
|
|
216
235
|
def test_has_parent
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
236
|
+
assert_deprecated 'has_parent?' do
|
237
|
+
assert_equal false, mixins(:tree_1).has_parent?
|
238
|
+
assert_equal true, mixins(:tree_2).has_parent?
|
239
|
+
assert_equal true, mixins(:tree_3).has_parent?
|
240
|
+
assert_equal true, mixins(:tree_4).has_parent?
|
241
|
+
end
|
221
242
|
end
|
222
243
|
|
223
244
|
def test_parent
|
@@ -304,6 +325,23 @@ end
|
|
304
325
|
|
305
326
|
class TouchTest < Test::Unit::TestCase
|
306
327
|
fixtures :mixins
|
328
|
+
|
329
|
+
def setup
|
330
|
+
Time.forced_now_time = Time.now
|
331
|
+
end
|
332
|
+
|
333
|
+
def teardown
|
334
|
+
Time.forced_now_time = nil
|
335
|
+
end
|
336
|
+
|
337
|
+
def test_time_mocking
|
338
|
+
five_minutes_ago = 5.minutes.ago
|
339
|
+
Time.forced_now_time = five_minutes_ago
|
340
|
+
assert_equal five_minutes_ago, Time.now
|
341
|
+
|
342
|
+
Time.forced_now_time = nil
|
343
|
+
assert_not_equal five_minutes_ago, Time.now
|
344
|
+
end
|
307
345
|
|
308
346
|
def test_update
|
309
347
|
stamped = Mixin.new
|
@@ -311,14 +349,14 @@ class TouchTest < Test::Unit::TestCase
|
|
311
349
|
assert_nil stamped.updated_at
|
312
350
|
assert_nil stamped.created_at
|
313
351
|
stamped.save
|
314
|
-
|
315
|
-
|
352
|
+
assert_equal Time.now, stamped.updated_at
|
353
|
+
assert_equal Time.now, stamped.created_at
|
316
354
|
end
|
317
355
|
|
318
356
|
def test_create
|
319
|
-
|
320
|
-
|
321
|
-
|
357
|
+
obj = Mixin.create
|
358
|
+
assert_equal Time.now, obj.updated_at
|
359
|
+
assert_equal Time.now, obj.created_at
|
322
360
|
end
|
323
361
|
|
324
362
|
def test_many_updates
|
@@ -327,16 +365,16 @@ class TouchTest < Test::Unit::TestCase
|
|
327
365
|
assert_nil stamped.updated_at
|
328
366
|
assert_nil stamped.created_at
|
329
367
|
stamped.save
|
330
|
-
|
331
|
-
|
368
|
+
assert_equal Time.now, stamped.created_at
|
369
|
+
assert_equal Time.now, stamped.updated_at
|
332
370
|
|
333
371
|
old_updated_at = stamped.updated_at
|
334
372
|
|
335
|
-
|
373
|
+
Time.forced_now_time = 5.minutes.from_now
|
336
374
|
stamped.save
|
337
|
-
assert_not_equal stamped.created_at, stamped.updated_at
|
338
|
-
assert_not_equal old_updated_at, stamped.updated_at
|
339
375
|
|
376
|
+
assert_equal Time.now, stamped.updated_at
|
377
|
+
assert_equal old_updated_at, stamped.created_at
|
340
378
|
end
|
341
379
|
|
342
380
|
def test_create_turned_off
|
data/test/modules_test.rb
CHANGED
@@ -5,10 +5,9 @@ class ModulesTest < Test::Unit::TestCase
|
|
5
5
|
fixtures :accounts, :companies, :projects, :developers
|
6
6
|
|
7
7
|
def test_module_spanning_associations
|
8
|
-
assert MyApplication::Business::Firm.find(:first).has_clients?, "Firm should have clients"
|
9
8
|
firm = MyApplication::Business::Firm.find(:first)
|
9
|
+
assert !firm.clients.empty?, "Firm should have clients"
|
10
10
|
assert_nil firm.class.table_name.match('::'), "Firm shouldn't have the module appear in its table name"
|
11
|
-
assert_equal 2, firm.clients_count, "Firm should have two clients"
|
12
11
|
end
|
13
12
|
|
14
13
|
def test_module_spanning_has_and_belongs_to_many_associations
|
@@ -25,4 +24,11 @@ class ModulesTest < Test::Unit::TestCase
|
|
25
24
|
assert_kind_of MyApplication::Billing::Nested::Firm, account.nested_qualified_billing_firm
|
26
25
|
assert_kind_of MyApplication::Billing::Nested::Firm, account.nested_unqualified_billing_firm
|
27
26
|
end
|
27
|
+
|
28
|
+
def test_find_account_and_include_company
|
29
|
+
account = MyApplication::Billing::Account.find(1, :include => :firm)
|
30
|
+
assert_kind_of MyApplication::Business::Firm, account.instance_variable_get('@firm')
|
31
|
+
assert_kind_of MyApplication::Business::Firm, account.firm
|
32
|
+
end
|
33
|
+
|
28
34
|
end
|
data/test/multiple_db_test.rb
CHANGED
@@ -39,11 +39,11 @@ class MultipleDbTest < Test::Unit::TestCase
|
|
39
39
|
|
40
40
|
def test_associations
|
41
41
|
c1 = Course.find(1)
|
42
|
-
assert_equal 2, c1.
|
42
|
+
assert_equal 2, c1.entrants.count
|
43
43
|
e1 = Entrant.find(1)
|
44
44
|
assert_equal e1.course.id, c1.id
|
45
45
|
c2 = Course.find(2)
|
46
|
-
assert_equal 1, c2.
|
46
|
+
assert_equal 1, c2.entrants.count
|
47
47
|
e3 = Entrant.find(3)
|
48
48
|
assert_equal e3.course.id, c2.id
|
49
49
|
end
|
data/test/pk_test.rb
CHANGED
data/test/reflection_test.rb
CHANGED
@@ -45,6 +45,12 @@ class ReflectionTest < Test::Unit::TestCase
|
|
45
45
|
assert_equal :string, @first.column_for_attribute("title").type
|
46
46
|
assert_equal 255, @first.column_for_attribute("title").limit
|
47
47
|
end
|
48
|
+
|
49
|
+
def test_column_null_not_null
|
50
|
+
subscriber = Subscriber.find(:first)
|
51
|
+
assert subscriber.column_for_attribute("name").null
|
52
|
+
assert !subscriber.column_for_attribute("nick").null
|
53
|
+
end
|
48
54
|
|
49
55
|
def test_human_name_for_column
|
50
56
|
assert_equal "Author name", @first.column_for_attribute("author_name").human_name
|
@@ -137,8 +143,8 @@ class ReflectionTest < Test::Unit::TestCase
|
|
137
143
|
end
|
138
144
|
|
139
145
|
def test_reflection_of_all_associations
|
140
|
-
assert_equal
|
141
|
-
assert_equal
|
146
|
+
assert_equal 17, Firm.reflect_on_all_associations.size
|
147
|
+
assert_equal 15, Firm.reflect_on_all_associations(:has_many).size
|
142
148
|
assert_equal 2, Firm.reflect_on_all_associations(:has_one).size
|
143
149
|
assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size
|
144
150
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
|
3
|
+
class SchemaThing < ActiveRecord::Base
|
4
|
+
end
|
5
|
+
|
6
|
+
class SchemaAuthorizationTest < Test::Unit::TestCase
|
7
|
+
self.use_transactional_fixtures = false
|
8
|
+
|
9
|
+
TABLE_NAME = 'schema_things'
|
10
|
+
COLUMNS = [
|
11
|
+
'id serial primary key',
|
12
|
+
'name character varying(50)'
|
13
|
+
]
|
14
|
+
USERS = ['rails_pg_schema_user1', 'rails_pg_schema_user2']
|
15
|
+
|
16
|
+
def setup
|
17
|
+
@connection = ActiveRecord::Base.connection
|
18
|
+
@connection.execute "SET search_path TO '$user',public"
|
19
|
+
set_session_auth
|
20
|
+
USERS.each do |u|
|
21
|
+
@connection.execute "CREATE ROLE #{u}"
|
22
|
+
@connection.execute "CREATE SCHEMA AUTHORIZATION #{u}"
|
23
|
+
set_session_auth u
|
24
|
+
@connection.execute "CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})"
|
25
|
+
@connection.execute "INSERT INTO #{TABLE_NAME} (name) VALUES ('#{u}')"
|
26
|
+
set_session_auth
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def teardown
|
31
|
+
set_session_auth
|
32
|
+
@connection.execute "RESET search_path"
|
33
|
+
USERS.each do |u|
|
34
|
+
@connection.execute "DROP SCHEMA #{u} CASCADE"
|
35
|
+
@connection.execute "DROP ROLE #{u}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_schema_invisible
|
40
|
+
assert_raise(ActiveRecord::StatementInvalid) do
|
41
|
+
set_session_auth
|
42
|
+
@connection.execute "SELECT * FROM #{TABLE_NAME}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_schema_uniqueness
|
47
|
+
assert_nothing_raised do
|
48
|
+
set_session_auth
|
49
|
+
USERS.each do |u|
|
50
|
+
set_session_auth u
|
51
|
+
assert_equal u, @connection.select_value("SELECT name FROM #{TABLE_NAME} WHERE id = 1")
|
52
|
+
set_session_auth
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_sequence_schema_caching
|
58
|
+
assert_nothing_raised do
|
59
|
+
USERS.each do |u|
|
60
|
+
set_session_auth u
|
61
|
+
st = SchemaThing.new :name => 'TEST1'
|
62
|
+
st.save!
|
63
|
+
st = SchemaThing.new :id => 5, :name => 'TEST2'
|
64
|
+
st.save!
|
65
|
+
set_session_auth
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
def set_session_auth auth = nil
|
72
|
+
@connection.execute "SET SESSION AUTHORIZATION #{auth || 'default'}"
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
data/test/schema_dumper_test.rb
CHANGED
@@ -5,20 +5,48 @@ require 'stringio'
|
|
5
5
|
if ActiveRecord::Base.connection.respond_to?(:tables)
|
6
6
|
|
7
7
|
class SchemaDumperTest < Test::Unit::TestCase
|
8
|
-
def
|
8
|
+
def standard_dump
|
9
9
|
stream = StringIO.new
|
10
|
+
ActiveRecord::SchemaDumper.ignore_tables = []
|
10
11
|
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
11
|
-
|
12
|
-
|
12
|
+
stream.string
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_schema_dump
|
16
|
+
output = standard_dump
|
13
17
|
assert_match %r{create_table "accounts"}, output
|
14
18
|
assert_match %r{create_table "authors"}, output
|
15
19
|
assert_no_match %r{create_table "schema_info"}, output
|
16
20
|
end
|
17
21
|
|
22
|
+
def assert_line_up(lines, pattern, required = false)
|
23
|
+
return assert(true) if lines.empty?
|
24
|
+
matches = lines.map { |line| line.match(pattern) }
|
25
|
+
assert matches.all? if required
|
26
|
+
matches.compact!
|
27
|
+
return assert(true) if matches.empty?
|
28
|
+
assert_equal 1, matches.map{ |match| match.offset(0).first }.uniq.length
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_arguments_line_up
|
32
|
+
output = standard_dump
|
33
|
+
output.scan(/^( *)create_table.*?\n(.*?)^\1end/m).map{ |m| m.last.split(/\n/) }.each do |column_set|
|
34
|
+
assert_line_up(column_set, /:(?:integer|decimal|float|datetime|timestamp|time|date|text|binary|string|boolean)/, true)
|
35
|
+
assert_line_up(column_set, /:default => /)
|
36
|
+
assert_line_up(column_set, /:limit => /)
|
37
|
+
assert_line_up(column_set, /:null => /)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_no_dump_errors
|
42
|
+
output = standard_dump
|
43
|
+
assert_no_match %r{\# Could not dump table}, output
|
44
|
+
end
|
45
|
+
|
18
46
|
def test_schema_dump_includes_not_null_columns
|
19
47
|
stream = StringIO.new
|
20
48
|
|
21
|
-
ActiveRecord::SchemaDumper.ignore_tables = [/^[^
|
49
|
+
ActiveRecord::SchemaDumper.ignore_tables = [/^[^r]/]
|
22
50
|
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
23
51
|
output = stream.string
|
24
52
|
assert_match %r{:null => false}, output
|
@@ -55,6 +83,14 @@ if ActiveRecord::Base.connection.respond_to?(:tables)
|
|
55
83
|
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
56
84
|
end
|
57
85
|
end
|
86
|
+
|
87
|
+
def test_schema_dump_includes_decimal_options
|
88
|
+
stream = StringIO.new
|
89
|
+
ActiveRecord::SchemaDumper.ignore_tables = [/^[^n]/]
|
90
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
91
|
+
output = stream.string
|
92
|
+
assert_match %r{:precision => 3,[[:space:]]+:scale => 2,[[:space:]]+:default => 2.78}, output
|
93
|
+
end
|
58
94
|
end
|
59
95
|
|
60
96
|
end
|