activerecord-oracle_enhanced-adapter 1.4.1 → 1.4.2.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. data/Gemfile +1 -0
  2. data/History.md +16 -1
  3. data/README.md +60 -35
  4. data/Rakefile +14 -1
  5. data/VERSION +1 -1
  6. data/activerecord-oracle_enhanced-adapter.gemspec +2 -2
  7. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +27 -9
  8. data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +13 -1
  9. data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +7 -2
  10. data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +31 -0
  11. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +6 -1
  12. data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +17 -5
  13. data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +2 -1
  14. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +29 -11
  15. data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +9 -4
  16. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +31 -7
  17. data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +5 -1
  18. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +34 -5
  19. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +22 -0
  20. data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +1 -0
  21. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +52 -6
  22. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +20 -0
  23. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +6 -2
  24. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +79 -21
  25. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +203 -35
  26. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +17 -1
  27. data/spec/spec_helper.rb +3 -1
  28. metadata +74 -51
@@ -7,6 +7,8 @@ if ActiveRecord::Base.method_defined?(:changed?)
7
7
  before(:all) do
8
8
  ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
9
9
  @conn = ActiveRecord::Base.connection
10
+ @conn.execute "DROP TABLE test_employees" rescue nil
11
+ @conn.execute "DROP SEQUENCE test_employees_seq" rescue nil
10
12
  @conn.execute <<-SQL
11
13
  CREATE TABLE test_employees (
12
14
  id NUMBER PRIMARY KEY,
@@ -116,6 +118,24 @@ if ActiveRecord::Base.method_defined?(:changed?)
116
118
  @employee.should_not be_changed
117
119
  end
118
120
 
121
+ it "should not update unchanged CLOBs" do
122
+ @employee = TestEmployee.create!(
123
+ :comments => "initial"
124
+ )
125
+ @employee.save!.should be_true
126
+ @employee.reload
127
+ @employee.comments.should == 'initial'
128
+
129
+ oci_conn = @conn.instance_variable_get('@connection')
130
+ class << oci_conn
131
+ def write_lob(lob, value, is_binary = false); raise "don't do this'"; end
132
+ end
133
+ @employee.save!.should_not raise_exception(RuntimeError, "don't do this'")
134
+ class << oci_conn
135
+ remove_method :write_lob
136
+ end
137
+ end
138
+
119
139
  end
120
140
 
121
141
  end
@@ -107,8 +107,12 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
107
107
 
108
108
  before(:each) do
109
109
  class ::TestEmployee < ActiveRecord::Base
110
- set_primary_key :employee_id
111
-
110
+ if self.respond_to?(:primary_key=)
111
+ self.primary_key = :employee_id
112
+ else
113
+ set_primary_key :employee_id
114
+ end
115
+
112
116
  validates_presence_of :first_name, :last_name, :hire_date
113
117
 
114
118
  # should return ID of new record
@@ -34,7 +34,7 @@ describe "OracleEnhancedAdapter schema dump" do
34
34
  rescue
35
35
  nil
36
36
  end
37
-
37
+
38
38
  describe "tables" do
39
39
  after(:each) do
40
40
  drop_test_posts_table
@@ -161,7 +161,7 @@ describe "OracleEnhancedAdapter schema dump" do
161
161
  end
162
162
  end
163
163
  end
164
-
164
+
165
165
  after(:each) do
166
166
  schema_define do
167
167
  remove_foreign_key :test_comments, :test_posts rescue nil
@@ -228,15 +228,15 @@ describe "OracleEnhancedAdapter schema dump" do
228
228
  schema_define do
229
229
  add_column :test_posts, :baz_id, :integer
230
230
  add_column :test_posts, :fooz_id, :integer
231
-
231
+
232
232
  execute <<-SQL
233
- ALTER TABLE TEST_POSTS
233
+ ALTER TABLE TEST_POSTS
234
234
  ADD CONSTRAINT UK_FOOZ_BAZ UNIQUE (BAZ_ID,FOOZ_ID)
235
235
  SQL
236
-
236
+
237
237
  add_column :test_comments, :baz_id, :integer
238
238
  add_column :test_comments, :fooz_id, :integer
239
-
239
+
240
240
  add_foreign_key :test_comments, :test_posts, :columns => ["baz_id", "fooz_id"], :name => 'comments_posts_baz_fooz_fk'
241
241
  end
242
242
  standard_dump.should =~ /add_foreign_key "test_comments", "test_posts", :columns => \["baz_id", "fooz_id"\], :name => "comments_posts_baz_fooz_fk"/
@@ -300,7 +300,7 @@ describe "OracleEnhancedAdapter schema dump" do
300
300
  after(:each) do
301
301
  drop_test_posts_table
302
302
  end
303
-
303
+
304
304
  it "should include temporary options" do
305
305
  create_test_posts_table(:temporary => true)
306
306
  standard_dump.should =~ /create_table "test_posts", :temporary => true/
@@ -347,34 +347,92 @@ describe "OracleEnhancedAdapter schema dump" do
347
347
 
348
348
  describe 'virtual columns' do
349
349
  before(:all) do
350
- oracle11g = @oracle11g
351
- schema_define do
352
- create_table :test_names, :force => true do |t|
353
- t.string :first_name
354
- t.string :last_name
355
- t.virtual :full_name, :default=>"first_name || ', ' || last_name" if oracle11g
350
+ if @oracle11g
351
+ schema_define do
352
+ create_table :test_names, :force => true do |t|
353
+ t.string :first_name
354
+ t.string :last_name
355
+ t.virtual :full_name, :as => "first_name || ', ' || last_name"
356
+ t.virtual :short_name, :as => "COALESCE(first_name, last_name)", :type => :string, :limit => 300
357
+ t.virtual :abbrev_name, :as => "SUBSTR(first_name,1,50) || ' ' || SUBSTR(last_name,1,1) || '.'", :type => "VARCHAR(100)"
358
+ t.column :full_name_length, :virtual, :as => "length(first_name || ', ' || last_name)", :type => :integer
359
+ t.virtual :field_with_leading_space, :as => "' ' || first_name || ' '", :limit => 300, :type => :string
360
+ end
356
361
  end
362
+ else
363
+ pending "Not supported in this database version"
357
364
  end
358
365
  end
366
+
359
367
  before(:each) do
360
- class ::TestName < ActiveRecord::Base
361
- set_table_name "test_names"
368
+ if @oracle11g
369
+ class ::TestName < ActiveRecord::Base
370
+ if self.respond_to?(:table_name=)
371
+ self.table_name = "test_names"
372
+ else
373
+ set_table_name "test_names"
374
+ end
375
+ end
362
376
  end
363
377
  end
364
378
 
365
379
  after(:all) do
366
- schema_define do
367
- drop_table :test_names
380
+ if @oracle11g
381
+ schema_define do
382
+ drop_table :test_names
383
+ end
368
384
  end
369
385
  end
370
386
 
371
387
  it 'should dump correctly' do
372
- pending "Not supported in this database version" unless @oracle11g
373
- standard_dump.should =~ /t.virtual "full_name",(\s*):limit => 512,(\s*):default => "/
388
+ standard_dump.should =~ /t\.virtual "full_name",(\s*):limit => 512,(\s*):as => "\\"FIRST_NAME\\"\|\|', '\|\|\\"LAST_NAME\\"",(\s*):type => :string/
389
+ standard_dump.should =~ /t\.virtual "short_name",(\s*):limit => 300,(\s*):as =>(.*),(\s*):type => :string/
390
+ standard_dump.should =~ /t\.virtual "full_name_length",(\s*):precision => 38,(\s*):scale => 0,(\s*):as =>(.*),(\s*):type => :integer/
391
+ standard_dump.should =~ /t\.virtual "abbrev_name",(\s*):limit => 100,(\s*):as =>(.*),(\s*):type => :string/
392
+ standard_dump.should =~ /t\.virtual "field_with_leading_space",(\s*):limit => 300,(\s*):as => "' '\|\|\\"FIRST_NAME\\"\|\|' '",(\s*):type => :string/
374
393
  end
375
394
 
376
- end
395
+ context 'with column cache' do
396
+ before(:all) do
397
+ @old_cache = ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns
398
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = true
399
+ end
400
+ after(:all) do
401
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = @old_cache
402
+ end
403
+ it 'should not change column defaults after several dumps' do
404
+ col = TestName.columns.detect{|c| c.name == 'full_name'}
405
+ col.should_not be_nil
406
+ col.virtual_column_data_default.should_not =~ /:as/
377
407
 
408
+ standard_dump
409
+ col.virtual_column_data_default.should_not =~ /:as/
378
410
 
379
- end
411
+ standard_dump
412
+ col.virtual_column_data_default.should_not =~ /:as/
413
+ end
414
+ end
380
415
 
416
+ context "with index on virtual column" do
417
+ before(:all) do
418
+ if @oracle11g
419
+ schema_define do
420
+ add_index 'test_names', 'field_with_leading_space', :name => "index_on_virtual_col"
421
+ end
422
+ end
423
+ end
424
+ after(:all) do
425
+ if @oracle11g
426
+ schema_define do
427
+ remove_index 'test_names', :name => 'index_on_virtual_col'
428
+ end
429
+ end
430
+ end
431
+ it 'should dump correctly' do
432
+ standard_dump.should_not =~ /add_index "test_names".+FIRST_NAME.+$/
433
+ standard_dump.should =~ /add_index "test_names".+field_with_leading_space.+$/
434
+ end
435
+ end
436
+ end
437
+
438
+ end
@@ -22,7 +22,11 @@ describe "OracleEnhancedAdapter schema definition" do
22
22
  end
23
23
  end
24
24
  class ::Keyboard < ActiveRecord::Base
25
- set_primary_key :key_number
25
+ if self.respond_to?(:primary_key=)
26
+ self.primary_key = :key_number
27
+ else
28
+ set_primary_key :key_number
29
+ end
26
30
  end
27
31
  class ::IdKeyboard < ActiveRecord::Base
28
32
  end
@@ -207,7 +211,7 @@ describe "OracleEnhancedAdapter schema definition" do
207
211
  insert_id = @conn.insert("INSERT INTO test_employees (first_name) VALUES ('Raimonds')", nil, "id")
208
212
  @conn.select_value("SELECT test_employees_seq.currval FROM dual").should == insert_id
209
213
  end
210
-
214
+
211
215
  it "should create new record for model" do
212
216
  e = TestEmployee.create!(:first_name => 'Raimonds')
213
217
  @conn.select_value("SELECT test_employees_seq.currval FROM dual").should == e.id
@@ -222,7 +226,11 @@ describe "OracleEnhancedAdapter schema definition" do
222
226
  @sequence_name = "test_employees_s"
223
227
  create_table_with_trigger(:primary_key => @primary_key, :sequence_name => @sequence_name)
224
228
  class ::TestEmployee < ActiveRecord::Base
225
- set_primary_key "employee_id"
229
+ if self.respond_to?(:primary_key=)
230
+ self.primary_key = "employee_id"
231
+ else
232
+ set_primary_key "employee_id"
233
+ end
226
234
  end
227
235
  end
228
236
 
@@ -254,7 +262,11 @@ describe "OracleEnhancedAdapter schema definition" do
254
262
  @sequence_name = "test_employees_s"
255
263
  create_table_with_trigger(:sequence_name => @sequence_name, :trigger_name => "test_employees_t1")
256
264
  class ::TestEmployee < ActiveRecord::Base
257
- set_sequence_name :autogenerated
265
+ if self.respond_to?(:sequence_name=)
266
+ self.sequence_name = :autogenerated
267
+ else
268
+ set_sequence_name :autogenerated
269
+ end
258
270
  end
259
271
  end
260
272
 
@@ -542,7 +554,7 @@ end
542
554
  belongs_to :test_post
543
555
  end
544
556
  end
545
-
557
+
546
558
  after(:each) do
547
559
  Object.send(:remove_const, "TestPost")
548
560
  Object.send(:remove_const, "TestComment")
@@ -618,26 +630,26 @@ end
618
630
  TestPost.delete(p.id)
619
631
  TestComment.find_by_id(c.id).test_post_id.should be_nil
620
632
  end
621
-
633
+
622
634
  it "should add a composite foreign key" do
623
635
  schema_define do
624
636
  add_column :test_posts, :baz_id, :integer
625
637
  add_column :test_posts, :fooz_id, :integer
626
-
638
+
627
639
  execute <<-SQL
628
- ALTER TABLE TEST_POSTS
640
+ ALTER TABLE TEST_POSTS
629
641
  ADD CONSTRAINT UK_FOOZ_BAZ UNIQUE (BAZ_ID,FOOZ_ID)
630
642
  SQL
631
-
643
+
632
644
  add_column :test_comments, :baz_id, :integer
633
645
  add_column :test_comments, :fooz_id, :integer
634
-
646
+
635
647
  add_foreign_key :test_comments, :test_posts, :columns => ["baz_id", "fooz_id"]
636
648
  end
637
-
649
+
638
650
  lambda do
639
651
  TestComment.create(:body => "test", :fooz_id => 1, :baz_id => 1)
640
- end.should raise_error() {|e| e.message.should =~
652
+ end.should raise_error() {|e| e.message.should =~
641
653
  /ORA-02291.*\.TES_COM_BAZ_ID_FOO_ID_FK/}
642
654
  end
643
655
 
@@ -645,18 +657,18 @@ end
645
657
  schema_define do
646
658
  add_column :test_posts, :baz_id, :integer
647
659
  add_column :test_posts, :fooz_id, :integer
648
-
660
+
649
661
  execute <<-SQL
650
- ALTER TABLE TEST_POSTS
662
+ ALTER TABLE TEST_POSTS
651
663
  ADD CONSTRAINT UK_FOOZ_BAZ UNIQUE (BAZ_ID,FOOZ_ID)
652
664
  SQL
653
-
665
+
654
666
  add_column :test_comments, :baz_id, :integer
655
667
  add_column :test_comments, :fooz_id, :integer
656
-
668
+
657
669
  add_foreign_key :test_comments, :test_posts, :columns => ["baz_id", "fooz_id"], :name => 'comments_posts_baz_fooz_fk'
658
670
  end
659
-
671
+
660
672
  lambda do
661
673
  TestComment.create(:body => "test", :baz_id => 1, :fooz_id => 1)
662
674
  end.should raise_error() {|e| e.message.should =~ /ORA-02291.*\.COMMENTS_POSTS_BAZ_FOOZ_FK/}
@@ -708,7 +720,7 @@ end
708
720
  belongs_to :test_post
709
721
  end
710
722
  end
711
-
723
+
712
724
  after(:each) do
713
725
  Object.send(:remove_const, "TestPost")
714
726
  Object.send(:remove_const, "TestComment")
@@ -862,7 +874,11 @@ end
862
874
 
863
875
  before(:each) do
864
876
  class ::TestPost < ActiveRecord::Base
865
- set_table_name "synonym_to_posts"
877
+ if self.respond_to?(:table_name=)
878
+ self.table_name = "synonym_to_posts"
879
+ else
880
+ set_table_name "synonym_to_posts"
881
+ end
866
882
  end
867
883
  end
868
884
 
@@ -918,6 +934,7 @@ end
918
934
  schema_define do
919
935
  create_table :test_posts, :force => true do |t|
920
936
  t.string :title, :null => false
937
+ t.string :content
921
938
  end
922
939
  end
923
940
  class ::TestPost < ActiveRecord::Base; end
@@ -979,46 +996,197 @@ end
979
996
  TestPost.columns_hash['title'].should be_nil
980
997
  end
981
998
 
999
+ it "should remove column when using change_table" do
1000
+ schema_define do
1001
+ change_table :test_posts do |t|
1002
+ t.remove :title
1003
+ end
1004
+ end
1005
+ TestPost.reset_column_information
1006
+ TestPost.columns_hash['title'].should be_nil
1007
+ end
1008
+
1009
+ it "should remove multiple columns when using change_table" do
1010
+ schema_define do
1011
+ change_table :test_posts do |t|
1012
+ t.remove :title, :content
1013
+ end
1014
+ end
1015
+ TestPost.reset_column_information
1016
+ TestPost.columns_hash['title'].should be_nil
1017
+ TestPost.columns_hash['content'].should be_nil
1018
+ end
1019
+ end
1020
+
1021
+ describe 'virtual columns in create_table' do
1022
+ before(:each) do
1023
+ pending "Not supported in this database version" unless @oracle11g
1024
+ end
1025
+
1026
+ it 'should create virtual column with old syntax' do
1027
+ schema_define do
1028
+ create_table :test_fractions, :force => true do |t|
1029
+ t.integer :field1
1030
+ t.virtual :field2, :default => 'field1 + 1'
1031
+ end
1032
+ end
1033
+ class ::TestFraction < ActiveRecord::Base
1034
+ if self.respond_to?(:table_name=)
1035
+ self.table_name = "test_fractions"
1036
+ else
1037
+ set_table_name "test_fractions"
1038
+ end
1039
+ end
1040
+
1041
+ TestFraction.reset_column_information
1042
+ tf = TestFraction.columns.detect { |c| c.virtual? }
1043
+ tf.should_not be nil
1044
+ tf.name.should == "field2"
1045
+ tf.virtual?.should be true
1046
+ lambda do
1047
+ tf = TestFraction.new(:field1=>10)
1048
+ tf.field2.should be nil # not whatever is in DATA_DEFAULT column
1049
+ tf.save!
1050
+ tf.reload
1051
+ end.should_not raise_error
1052
+ tf.field2.to_i.should == 11
1053
+
1054
+ schema_define do
1055
+ drop_table :test_fractions
1056
+ end
1057
+ end
1058
+
1059
+ it 'should raise error if column expression is not provided' do
1060
+ lambda {
1061
+ schema_define do
1062
+ create_table :test_fractions do |t|
1063
+ t.integer :field1
1064
+ t.virtual :field2
1065
+ end
1066
+ end
1067
+ }.should raise_error
1068
+ end
982
1069
  end
983
1070
 
984
1071
  describe 'virtual columns' do
985
- before(:all) do
986
- oracle11g = @oracle11g
1072
+ before(:each) do
1073
+ pending "Not supported in this database version" unless @oracle11g
1074
+ expr = "( numerator/NULLIF(denominator,0) )*100"
987
1075
  schema_define do
988
- expr = "( numerator/NULLIF(denominator,0) )*100"
989
1076
  create_table :test_fractions, :force => true do |t|
990
1077
  t.integer :numerator, :default=>0
991
1078
  t.integer :denominator, :default=>0
992
- t.virtual :percent, :default=>expr if oracle11g
1079
+ t.virtual :percent, :as => expr
993
1080
  end
994
1081
  end
995
- end
996
- before(:each) do
997
1082
  class ::TestFraction < ActiveRecord::Base
998
- set_table_name "test_fractions"
1083
+ if self.respond_to?(:table_name=)
1084
+ self.table_name = "test_fractions"
1085
+ else
1086
+ set_table_name "test_fractions"
1087
+ end
999
1088
  end
1089
+ TestFraction.reset_column_information
1000
1090
  end
1001
1091
 
1002
- after(:all) do
1003
- schema_define do
1004
- drop_table :test_fractions
1092
+ after(:each) do
1093
+ if @oracle11g
1094
+ schema_define do
1095
+ drop_table :test_fractions
1096
+ end
1005
1097
  end
1006
1098
  end
1007
1099
 
1008
1100
  it 'should include virtual columns and not try to update them' do
1009
- pending "Not supported in this database version" unless @oracle11g
1010
1101
  tf = TestFraction.columns.detect { |c| c.virtual? }
1011
1102
  tf.should_not be nil
1012
1103
  tf.name.should == "percent"
1013
1104
  tf.virtual?.should be true
1014
1105
  lambda do
1015
1106
  tf = TestFraction.new(:numerator=>20, :denominator=>100)
1016
- tf.percent.should==0 # not whatever is in DATA_DEFAULT column
1107
+ tf.percent.should be nil # not whatever is in DATA_DEFAULT column
1017
1108
  tf.save!
1018
1109
  tf.reload
1019
1110
  end.should_not raise_error
1020
1111
  tf.percent.to_i.should == 20
1021
1112
  end
1113
+
1114
+ it 'should add virtual column' do
1115
+ schema_define do
1116
+ add_column :test_fractions, :rem, :virtual, :as => 'remainder(numerator, NULLIF(denominator,0))'
1117
+ end
1118
+ TestFraction.reset_column_information
1119
+ tf = TestFraction.columns.detect { |c| c.name == 'rem' }
1120
+ tf.should_not be nil
1121
+ tf.virtual?.should be true
1122
+ lambda do
1123
+ tf = TestFraction.new(:numerator=>7, :denominator=>5)
1124
+ tf.rem.should be nil
1125
+ tf.save!
1126
+ tf.reload
1127
+ end.should_not raise_error
1128
+ tf.rem.to_i.should == 2
1129
+ end
1130
+
1131
+ it 'should add virtual column with explicit type' do
1132
+ schema_define do
1133
+ add_column :test_fractions, :expression, :virtual, :as => "TO_CHAR(numerator) || '/' || TO_CHAR(denominator)", :type => :string, :limit => 100
1134
+ end
1135
+ TestFraction.reset_column_information
1136
+ tf = TestFraction.columns.detect { |c| c.name == 'expression' }
1137
+ tf.should_not be nil
1138
+ tf.virtual?.should be true
1139
+ tf.type.should be :string
1140
+ tf.limit.should be 100
1141
+ lambda do
1142
+ tf = TestFraction.new(:numerator=>7, :denominator=>5)
1143
+ tf.expression.should be nil
1144
+ tf.save!
1145
+ tf.reload
1146
+ end.should_not raise_error
1147
+ tf.expression.should == '7/5'
1148
+ end
1149
+
1150
+ it 'should change virtual column definition' do
1151
+ schema_define do
1152
+ change_column :test_fractions, :percent, :virtual,
1153
+ :as => "ROUND((numerator/NULLIF(denominator,0))*100, 2)", :type => :decimal, :precision => 15, :scale => 2
1154
+ end
1155
+ TestFraction.reset_column_information
1156
+ tf = TestFraction.columns.detect { |c| c.name == 'percent' }
1157
+ tf.should_not be nil
1158
+ tf.virtual?.should be true
1159
+ tf.type.should be :decimal
1160
+ tf.precision.should be 15
1161
+ tf.scale.should be 2
1162
+ lambda do
1163
+ tf = TestFraction.new(:numerator=>11, :denominator=>17)
1164
+ tf.percent.should be nil
1165
+ tf.save!
1166
+ tf.reload
1167
+ end.should_not raise_error
1168
+ tf.percent.should == '64.71'.to_d
1169
+ end
1170
+
1171
+ it 'should change virtual column type' do
1172
+ schema_define do
1173
+ change_column :test_fractions, :percent, :virtual, :type => :decimal, :precision => 12, :scale => 5
1174
+ end
1175
+ TestFraction.reset_column_information
1176
+ tf = TestFraction.columns.detect { |c| c.name == 'percent' }
1177
+ tf.should_not be nil
1178
+ tf.virtual?.should be true
1179
+ tf.type.should be :decimal
1180
+ tf.precision.should be 12
1181
+ tf.scale.should be 5
1182
+ lambda do
1183
+ tf = TestFraction.new(:numerator=>11, :denominator=>17)
1184
+ tf.percent.should be nil
1185
+ tf.save!
1186
+ tf.reload
1187
+ end.should_not raise_error
1188
+ tf.percent.should == '64.70588'.to_d
1189
+ end
1022
1190
  end
1023
1191
 
1024
1192
  describe "miscellaneous options" do
@@ -1040,7 +1208,7 @@ end
1040
1208
  end
1041
1209
  @conn.instance_eval{ remove_instance_variable :@would_execute_sql }
1042
1210
  end
1043
-
1211
+
1044
1212
  it "should support the :options option to create_table" do
1045
1213
  schema_define do
1046
1214
  create_table :test_posts, :options=>'NOLOGGING', :force => true do |t|
@@ -1049,7 +1217,7 @@ end
1049
1217
  end
1050
1218
  @would_execute_sql.should =~ /CREATE +TABLE .* \(.*\) NOLOGGING/
1051
1219
  end
1052
-
1220
+
1053
1221
  it "should support the :tablespace option to create_table" do
1054
1222
  schema_define do
1055
1223
  create_table :test_posts, :tablespace=>'bogus', :force => true do |t|
@@ -1085,14 +1253,14 @@ end
1085
1253
  @would_execute_sql.should =~ /CREATE +TABLE .*\(.*\)\s+ORGANIZATION INDEX INITRANS 4 COMPRESS 1 TABLESPACE bogus/
1086
1254
  end
1087
1255
  end
1088
-
1256
+
1089
1257
  it "should support the :options option to add_index" do
1090
1258
  schema_define do
1091
1259
  add_index :keyboards, :name, :options=>'NOLOGGING'
1092
1260
  end
1093
1261
  @would_execute_sql.should =~ /CREATE +INDEX .* ON .* \(.*\) NOLOGGING/
1094
1262
  end
1095
-
1263
+
1096
1264
  it "should support the :tablespace option to add_index" do
1097
1265
  schema_define do
1098
1266
  add_index :keyboards, :name, :tablespace=>'bogus'