sequel 3.46.0 → 3.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +96 -0
  3. data/Rakefile +7 -1
  4. data/bin/sequel +6 -4
  5. data/doc/active_record.rdoc +1 -1
  6. data/doc/advanced_associations.rdoc +14 -35
  7. data/doc/association_basics.rdoc +66 -4
  8. data/doc/migration.rdoc +4 -0
  9. data/doc/opening_databases.rdoc +6 -0
  10. data/doc/postgresql.rdoc +302 -0
  11. data/doc/release_notes/3.47.0.txt +270 -0
  12. data/doc/security.rdoc +6 -0
  13. data/lib/sequel/adapters/ibmdb.rb +9 -9
  14. data/lib/sequel/adapters/jdbc.rb +22 -7
  15. data/lib/sequel/adapters/jdbc/postgresql.rb +7 -2
  16. data/lib/sequel/adapters/mock.rb +2 -0
  17. data/lib/sequel/adapters/postgres.rb +44 -13
  18. data/lib/sequel/adapters/shared/mssql.rb +1 -1
  19. data/lib/sequel/adapters/shared/mysql.rb +2 -2
  20. data/lib/sequel/adapters/shared/postgres.rb +94 -55
  21. data/lib/sequel/adapters/shared/sqlite.rb +3 -1
  22. data/lib/sequel/adapters/sqlite.rb +2 -2
  23. data/lib/sequel/adapters/utils/pg_types.rb +1 -14
  24. data/lib/sequel/adapters/utils/split_alter_table.rb +3 -3
  25. data/lib/sequel/connection_pool/threaded.rb +1 -1
  26. data/lib/sequel/core.rb +1 -1
  27. data/lib/sequel/database/connecting.rb +2 -2
  28. data/lib/sequel/database/features.rb +5 -0
  29. data/lib/sequel/database/misc.rb +47 -5
  30. data/lib/sequel/database/query.rb +2 -2
  31. data/lib/sequel/dataset/actions.rb +4 -2
  32. data/lib/sequel/dataset/misc.rb +1 -1
  33. data/lib/sequel/dataset/prepared_statements.rb +1 -1
  34. data/lib/sequel/dataset/query.rb +8 -6
  35. data/lib/sequel/dataset/sql.rb +8 -6
  36. data/lib/sequel/extensions/constraint_validations.rb +5 -2
  37. data/lib/sequel/extensions/migration.rb +10 -8
  38. data/lib/sequel/extensions/pagination.rb +3 -0
  39. data/lib/sequel/extensions/pg_array.rb +85 -25
  40. data/lib/sequel/extensions/pg_hstore.rb +8 -1
  41. data/lib/sequel/extensions/pg_hstore_ops.rb +4 -1
  42. data/lib/sequel/extensions/pg_inet.rb +16 -13
  43. data/lib/sequel/extensions/pg_interval.rb +6 -2
  44. data/lib/sequel/extensions/pg_json.rb +18 -11
  45. data/lib/sequel/extensions/pg_range.rb +17 -2
  46. data/lib/sequel/extensions/pg_range_ops.rb +7 -5
  47. data/lib/sequel/extensions/pg_row.rb +29 -12
  48. data/lib/sequel/extensions/pretty_table.rb +3 -0
  49. data/lib/sequel/extensions/query.rb +3 -0
  50. data/lib/sequel/extensions/schema_caching.rb +2 -0
  51. data/lib/sequel/extensions/schema_dumper.rb +3 -1
  52. data/lib/sequel/extensions/select_remove.rb +3 -0
  53. data/lib/sequel/model.rb +8 -2
  54. data/lib/sequel/model/associations.rb +39 -27
  55. data/lib/sequel/model/base.rb +99 -38
  56. data/lib/sequel/model/plugins.rb +25 -0
  57. data/lib/sequel/plugins/association_autoreloading.rb +27 -22
  58. data/lib/sequel/plugins/association_dependencies.rb +1 -7
  59. data/lib/sequel/plugins/auto_validations.rb +110 -0
  60. data/lib/sequel/plugins/boolean_readers.rb +1 -6
  61. data/lib/sequel/plugins/caching.rb +6 -13
  62. data/lib/sequel/plugins/class_table_inheritance.rb +1 -0
  63. data/lib/sequel/plugins/composition.rb +14 -7
  64. data/lib/sequel/plugins/constraint_validations.rb +2 -13
  65. data/lib/sequel/plugins/defaults_setter.rb +1 -6
  66. data/lib/sequel/plugins/dirty.rb +8 -0
  67. data/lib/sequel/plugins/error_splitter.rb +54 -0
  68. data/lib/sequel/plugins/force_encoding.rb +1 -5
  69. data/lib/sequel/plugins/hook_class_methods.rb +1 -6
  70. data/lib/sequel/plugins/input_transformer.rb +79 -0
  71. data/lib/sequel/plugins/instance_filters.rb +7 -1
  72. data/lib/sequel/plugins/instance_hooks.rb +7 -1
  73. data/lib/sequel/plugins/json_serializer.rb +5 -10
  74. data/lib/sequel/plugins/lazy_attributes.rb +20 -7
  75. data/lib/sequel/plugins/list.rb +1 -6
  76. data/lib/sequel/plugins/many_through_many.rb +1 -2
  77. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +23 -39
  78. data/lib/sequel/plugins/optimistic_locking.rb +1 -5
  79. data/lib/sequel/plugins/pg_row.rb +4 -2
  80. data/lib/sequel/plugins/pg_typecast_on_load.rb +3 -7
  81. data/lib/sequel/plugins/prepared_statements.rb +1 -5
  82. data/lib/sequel/plugins/prepared_statements_safe.rb +2 -11
  83. data/lib/sequel/plugins/rcte_tree.rb +2 -2
  84. data/lib/sequel/plugins/serialization.rb +11 -13
  85. data/lib/sequel/plugins/serialization_modification_detection.rb +13 -1
  86. data/lib/sequel/plugins/single_table_inheritance.rb +4 -4
  87. data/lib/sequel/plugins/static_cache.rb +67 -19
  88. data/lib/sequel/plugins/string_stripper.rb +7 -27
  89. data/lib/sequel/plugins/subclasses.rb +3 -5
  90. data/lib/sequel/plugins/tactical_eager_loading.rb +2 -2
  91. data/lib/sequel/plugins/timestamps.rb +2 -7
  92. data/lib/sequel/plugins/touch.rb +5 -8
  93. data/lib/sequel/plugins/tree.rb +1 -6
  94. data/lib/sequel/plugins/typecast_on_load.rb +1 -5
  95. data/lib/sequel/plugins/update_primary_key.rb +26 -14
  96. data/lib/sequel/plugins/validation_class_methods.rb +31 -16
  97. data/lib/sequel/plugins/validation_helpers.rb +50 -26
  98. data/lib/sequel/plugins/xml_serializer.rb +3 -6
  99. data/lib/sequel/sql.rb +1 -1
  100. data/lib/sequel/version.rb +1 -1
  101. data/spec/adapters/postgres_spec.rb +131 -15
  102. data/spec/adapters/sqlite_spec.rb +1 -1
  103. data/spec/core/connection_pool_spec.rb +16 -17
  104. data/spec/core/database_spec.rb +111 -40
  105. data/spec/core/dataset_spec.rb +65 -74
  106. data/spec/core/expression_filters_spec.rb +6 -5
  107. data/spec/core/object_graph_spec.rb +0 -1
  108. data/spec/core/schema_spec.rb +23 -23
  109. data/spec/core/spec_helper.rb +5 -1
  110. data/spec/extensions/association_dependencies_spec.rb +1 -1
  111. data/spec/extensions/association_proxies_spec.rb +1 -1
  112. data/spec/extensions/auto_validations_spec.rb +90 -0
  113. data/spec/extensions/caching_spec.rb +6 -0
  114. data/spec/extensions/class_table_inheritance_spec.rb +8 -1
  115. data/spec/extensions/composition_spec.rb +12 -5
  116. data/spec/extensions/constraint_validations_spec.rb +4 -4
  117. data/spec/extensions/core_refinements_spec.rb +29 -79
  118. data/spec/extensions/dirty_spec.rb +14 -0
  119. data/spec/extensions/error_splitter_spec.rb +18 -0
  120. data/spec/extensions/identity_map_spec.rb +0 -1
  121. data/spec/extensions/input_transformer_spec.rb +54 -0
  122. data/spec/extensions/instance_filters_spec.rb +6 -0
  123. data/spec/extensions/instance_hooks_spec.rb +12 -1
  124. data/spec/extensions/json_serializer_spec.rb +0 -1
  125. data/spec/extensions/lazy_attributes_spec.rb +64 -55
  126. data/spec/extensions/looser_typecasting_spec.rb +1 -1
  127. data/spec/extensions/many_through_many_spec.rb +3 -4
  128. data/spec/extensions/many_to_one_pk_lookup_spec.rb +53 -15
  129. data/spec/extensions/migration_spec.rb +16 -0
  130. data/spec/extensions/null_dataset_spec.rb +1 -1
  131. data/spec/extensions/pg_array_spec.rb +48 -1
  132. data/spec/extensions/pg_hstore_ops_spec.rb +10 -2
  133. data/spec/extensions/pg_hstore_spec.rb +5 -0
  134. data/spec/extensions/pg_inet_spec.rb +5 -0
  135. data/spec/extensions/pg_interval_spec.rb +7 -3
  136. data/spec/extensions/pg_json_spec.rb +6 -1
  137. data/spec/extensions/pg_range_ops_spec.rb +4 -1
  138. data/spec/extensions/pg_range_spec.rb +5 -0
  139. data/spec/extensions/pg_row_plugin_spec.rb +13 -0
  140. data/spec/extensions/pg_row_spec.rb +28 -19
  141. data/spec/extensions/pg_typecast_on_load_spec.rb +6 -1
  142. data/spec/extensions/prepared_statements_associations_spec.rb +1 -1
  143. data/spec/extensions/query_literals_spec.rb +1 -1
  144. data/spec/extensions/rcte_tree_spec.rb +2 -2
  145. data/spec/extensions/schema_spec.rb +2 -2
  146. data/spec/extensions/serialization_modification_detection_spec.rb +8 -0
  147. data/spec/extensions/serialization_spec.rb +15 -1
  148. data/spec/extensions/sharding_spec.rb +1 -1
  149. data/spec/extensions/single_table_inheritance_spec.rb +1 -1
  150. data/spec/extensions/static_cache_spec.rb +59 -9
  151. data/spec/extensions/tactical_eager_loading_spec.rb +19 -4
  152. data/spec/extensions/update_primary_key_spec.rb +17 -1
  153. data/spec/extensions/validation_class_methods_spec.rb +25 -0
  154. data/spec/extensions/validation_helpers_spec.rb +59 -3
  155. data/spec/integration/associations_test.rb +5 -5
  156. data/spec/integration/eager_loader_test.rb +32 -63
  157. data/spec/integration/model_test.rb +2 -2
  158. data/spec/integration/plugin_test.rb +88 -56
  159. data/spec/integration/prepared_statement_test.rb +1 -1
  160. data/spec/integration/schema_test.rb +1 -1
  161. data/spec/integration/timezone_test.rb +0 -1
  162. data/spec/integration/transaction_test.rb +0 -1
  163. data/spec/model/association_reflection_spec.rb +1 -1
  164. data/spec/model/associations_spec.rb +106 -84
  165. data/spec/model/base_spec.rb +4 -4
  166. data/spec/model/eager_loading_spec.rb +8 -8
  167. data/spec/model/model_spec.rb +27 -9
  168. data/spec/model/plugins_spec.rb +71 -0
  169. data/spec/model/record_spec.rb +99 -13
  170. metadata +12 -2
@@ -44,7 +44,7 @@ describe "Blockless Ruby Filters" do
44
44
  end
45
45
 
46
46
  it "should use = 't' and != 't' OR IS NULL if IS TRUE is not supported" do
47
- @d.meta_def(:supports_is_true?){false}
47
+ meta_def(@d, :supports_is_true?){false}
48
48
  @d.l(:x => true).should == "(x = 't')"
49
49
  @d.l(~Sequel.expr(:x => true)).should == "((x != 't') OR (x IS NULL))"
50
50
  @d.l(:x => false).should == "(x = 'f')"
@@ -169,7 +169,7 @@ describe "Blockless Ruby Filters" do
169
169
  end
170
170
 
171
171
  it "should emulate multiple column in if not supported" do
172
- @d.meta_def(:supports_multiple_column_in?){false}
172
+ meta_def(@d, :supports_multiple_column_in?){false}
173
173
  @d.l([:x, :y]=>Sequel.value_list([[1,2], [3,4]])).should == '(((x = 1) AND (y = 2)) OR ((x = 3) AND (y = 4)))'
174
174
  @d.l([:x, :y, :z]=>[[1,2,5], [3,4,6]]).should == '(((x = 1) AND (y = 2) AND (z = 5)) OR ((x = 3) AND (y = 4) AND (z = 6)))'
175
175
  end
@@ -398,7 +398,7 @@ describe Sequel::SQL::VirtualRow do
398
398
  db = Sequel::Database.new
399
399
  db.quote_identifiers = true
400
400
  @d = db[:items]
401
- @d.meta_def(:supports_window_functions?){true}
401
+ meta_def(@d, :supports_window_functions?){true}
402
402
  def @d.l(*args, &block)
403
403
  literal(filter_expr(*args, &block))
404
404
  end
@@ -481,7 +481,8 @@ describe Sequel::SQL::VirtualRow do
481
481
  end
482
482
 
483
483
  it "should raise an error if window functions are not supported" do
484
- @d.meta_def(:supports_window_functions?){false}
484
+ class << @d; remove_method :supports_window_functions? end
485
+ meta_def(@d, :supports_window_functions?){false}
485
486
  proc{@d.l{count(:over, :* =>true, :partition=>a, :order=>b, :window=>:win, :frame=>:rows){}}}.should raise_error(Sequel::Error)
486
487
  proc{Sequel::Dataset.new(nil).filter{count(:over, :* =>true, :partition=>a, :order=>b, :window=>:win, :frame=>:rows){}}.sql}.should raise_error(Sequel::Error)
487
488
  end
@@ -980,7 +981,7 @@ describe "Sequel.delay" do
980
981
  @a += 1
981
982
  end
982
983
  def _a
983
- @a
984
+ @a if defined?(@a)
984
985
  end
985
986
 
986
987
  attr_accessor :b
@@ -163,7 +163,6 @@ describe Sequel::Dataset, " graphing" do
163
163
  @ds1.opts.should == o2
164
164
  ds1.opts.should_not == o1
165
165
  o3 = ds1.opts
166
- o4 = o3.dup
167
166
  ds2 = ds1.add_graph_aliases(:y=>[:blah,:id])
168
167
  ds1.opts.should == o3
169
168
  ds1.opts.should == o3
@@ -389,7 +389,7 @@ describe "DB#create_table" do
389
389
  @db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE INDEX cats_id_index ON cats (id)"]
390
390
  end
391
391
 
392
- specify "should accept unique index definitions" do
392
+ specify "should accept unique constraint definitions" do
393
393
  @db.create_table(:cats) do
394
394
  text :name
395
395
  unique :name
@@ -443,7 +443,7 @@ describe "DB#create_table" do
443
443
  end
444
444
 
445
445
  specify "should ignore errors if the database raises an error on an index creation statement and the :ignore_index_errors option is used" do
446
- @db.meta_def(:execute_ddl){|*a| raise Sequel::DatabaseError if /blah/.match(a.first); super(*a)}
446
+ meta_def(@db, :execute_ddl){|*a| raise Sequel::DatabaseError if /blah/.match(a.first); super(*a)}
447
447
  lambda{@db.create_table(:cats){Integer :id; index :blah; index :id}}.should raise_error(Sequel::DatabaseError)
448
448
  @db.sqls.should == ['CREATE TABLE cats (id integer)']
449
449
  lambda{@db.create_table(:cats, :ignore_index_errors=>true){Integer :id; index :blah; index :id}}.should_not raise_error(Sequel::DatabaseError)
@@ -643,13 +643,13 @@ describe "DB#create_table!" do
643
643
  end
644
644
 
645
645
  specify "should create the table if it does not exist" do
646
- @db.meta_def(:table_exists?){|a| false}
646
+ meta_def(@db, :table_exists?){|a| false}
647
647
  @db.create_table!(:cats){|*a|}
648
648
  @db.sqls.should == ['CREATE TABLE cats ()']
649
649
  end
650
650
 
651
651
  specify "should drop the table before creating it if it already exists" do
652
- @db.meta_def(:table_exists?){|a| true}
652
+ meta_def(@db, :table_exists?){|a| true}
653
653
  @db.create_table!(:cats){|*a|}
654
654
  @db.sqls.should == ['DROP TABLE cats', 'CREATE TABLE cats ()']
655
655
  end
@@ -661,19 +661,19 @@ describe "DB#create_table?" do
661
661
  end
662
662
 
663
663
  specify "should not create the table if the table already exists" do
664
- @db.meta_def(:table_exists?){|a| true}
664
+ meta_def(@db, :table_exists?){|a| true}
665
665
  @db.create_table?(:cats){|*a|}
666
666
  @db.sqls.should == []
667
667
  end
668
668
 
669
669
  specify "should create the table if the table doesn't already exist" do
670
- @db.meta_def(:table_exists?){|a| false}
670
+ meta_def(@db, :table_exists?){|a| false}
671
671
  @db.create_table?(:cats){|*a|}
672
672
  @db.sqls.should == ['CREATE TABLE cats ()']
673
673
  end
674
674
 
675
675
  specify "should use IF NOT EXISTS if the database supports that" do
676
- @db.meta_def(:supports_create_table_if_not_exists?){true}
676
+ meta_def(@db, :supports_create_table_if_not_exists?){true}
677
677
  @db.create_table?(:cats){|*a|}
678
678
  @db.sqls.should == ['CREATE TABLE IF NOT EXISTS cats ()']
679
679
  end
@@ -787,37 +787,37 @@ describe "DB#drop_table?" do
787
787
  end
788
788
 
789
789
  specify "should drop the table if it exists" do
790
- @db.meta_def(:table_exists?){|a| true}
790
+ meta_def(@db, :table_exists?){|a| true}
791
791
  @db.drop_table?(:cats)
792
792
  @db.sqls.should == ["DROP TABLE cats"]
793
793
  end
794
794
 
795
795
  specify "should do nothing if the table does not exist" do
796
- @db.meta_def(:table_exists?){|a| false}
796
+ meta_def(@db, :table_exists?){|a| false}
797
797
  @db.drop_table?(:cats)
798
798
  @db.sqls.should == []
799
799
  end
800
800
 
801
801
  specify "should operate on multiple tables at once" do
802
- @db.meta_def(:table_exists?){|a| a == :cats}
802
+ meta_def(@db, :table_exists?){|a| a == :cats}
803
803
  @db.drop_table? :cats, :dogs
804
804
  @db.sqls.should == ['DROP TABLE cats']
805
805
  end
806
806
 
807
807
  specify "should take an options hash and support the :cascade option" do
808
- @db.meta_def(:table_exists?){|a| true}
808
+ meta_def(@db, :table_exists?){|a| true}
809
809
  @db.drop_table? :cats, :dogs, :cascade=>true
810
810
  @db.sqls.should == ['DROP TABLE cats CASCADE', 'DROP TABLE dogs CASCADE']
811
811
  end
812
812
 
813
813
  specify "should use IF NOT EXISTS if the database supports that" do
814
- @db.meta_def(:supports_drop_table_if_exists?){true}
814
+ meta_def(@db, :supports_drop_table_if_exists?){true}
815
815
  @db.drop_table? :cats, :dogs
816
816
  @db.sqls.should == ['DROP TABLE IF EXISTS cats', 'DROP TABLE IF EXISTS dogs']
817
817
  end
818
818
 
819
819
  specify "should use IF NOT EXISTS with CASCADE if the database supports that" do
820
- @db.meta_def(:supports_drop_table_if_exists?){true}
820
+ meta_def(@db, :supports_drop_table_if_exists?){true}
821
821
  @db.drop_table? :cats, :dogs, :cascade=>true
822
822
  @db.sqls.should == ['DROP TABLE IF EXISTS cats CASCADE', 'DROP TABLE IF EXISTS dogs CASCADE']
823
823
  end
@@ -926,7 +926,7 @@ describe "DB#alter_table" do
926
926
  end
927
927
 
928
928
  specify "should ignore errors if the database raises an error on an add_index call and the :ignore_errors option is used" do
929
- @db.meta_def(:execute_ddl){|*a| raise Sequel::DatabaseError}
929
+ meta_def(@db, :execute_ddl){|*a| raise Sequel::DatabaseError}
930
930
  lambda{@db.add_index(:cats, :id)}.should raise_error(Sequel::DatabaseError)
931
931
  lambda{@db.add_index(:cats, :id, :ignore_errors=>true)}.should_not raise_error(Sequel::DatabaseError)
932
932
  @db.sqls.should == []
@@ -1065,7 +1065,7 @@ describe "DB#alter_table" do
1065
1065
  end
1066
1066
 
1067
1067
  specify "should combine operations into a single query if the database supports it" do
1068
- @db.meta_def(:supports_combining_alter_table_ops?){true}
1068
+ meta_def(@db, :supports_combining_alter_table_ops?){true}
1069
1069
  @db.alter_table(:cats) do
1070
1070
  add_column :a, Integer
1071
1071
  drop_column :b
@@ -1080,7 +1080,7 @@ describe "DB#alter_table" do
1080
1080
  end
1081
1081
 
1082
1082
  specify "should combine operations into consecutive groups of combinable operations if the database supports combining operations" do
1083
- @db.meta_def(:supports_combining_alter_table_ops?){true}
1083
+ meta_def(@db, :supports_combining_alter_table_ops?){true}
1084
1084
  @db.alter_table(:cats) do
1085
1085
  add_column :a, Integer
1086
1086
  drop_column :b
@@ -1342,21 +1342,21 @@ describe "Schema Parser" do
1342
1342
  end
1343
1343
 
1344
1344
  specify "should raise an error if there are no columns" do
1345
- @db.meta_def(:schema_parse_table) do |t, opts|
1345
+ meta_def(@db, :schema_parse_table) do |t, opts|
1346
1346
  []
1347
1347
  end
1348
1348
  proc{@db.schema(:x)}.should raise_error(Sequel::Error)
1349
1349
  end
1350
1350
 
1351
1351
  specify "should cache data by default" do
1352
- @db.meta_def(:schema_parse_table) do |t, opts|
1352
+ meta_def(@db, :schema_parse_table) do |t, opts|
1353
1353
  [[:a, {}]]
1354
1354
  end
1355
1355
  @db.schema(:x).should equal(@db.schema(:x))
1356
1356
  end
1357
1357
 
1358
1358
  specify "should not cache data if :reload=>true is given" do
1359
- @db.meta_def(:schema_parse_table) do |t, opts|
1359
+ meta_def(@db, :schema_parse_table) do |t, opts|
1360
1360
  [[:a, {}]]
1361
1361
  end
1362
1362
  @db.schema(:x).should_not equal(@db.schema(:x, :reload=>true))
@@ -1364,7 +1364,7 @@ describe "Schema Parser" do
1364
1364
 
1365
1365
  specify "should not cache schema metadata if cache_schema is false" do
1366
1366
  @db.cache_schema = false
1367
- @db.meta_def(:schema_parse_table) do |t, opts|
1367
+ meta_def(@db, :schema_parse_table) do |t, opts|
1368
1368
  [[:a, {}]]
1369
1369
  end
1370
1370
  @db.schema(:x).should_not equal(@db.schema(:x))
@@ -1372,7 +1372,7 @@ describe "Schema Parser" do
1372
1372
 
1373
1373
  specify "should provide options if given a table name" do
1374
1374
  c = nil
1375
- @db.meta_def(:schema_parse_table) do |t, opts|
1375
+ meta_def(@db, :schema_parse_table) do |t, opts|
1376
1376
  c = [t, opts]
1377
1377
  [[:a, {:db_type=>t.to_s}]]
1378
1378
  end
@@ -1388,7 +1388,7 @@ describe "Schema Parser" do
1388
1388
  specify "should parse the schema correctly for a single table" do
1389
1389
  sqls = @sqls
1390
1390
  proc{@db.schema(:x)}.should raise_error(Sequel::Error)
1391
- @db.meta_def(:schema_parse_table) do |t, opts|
1391
+ meta_def(@db, :schema_parse_table) do |t, opts|
1392
1392
  sqls << t
1393
1393
  [[:a, {:db_type=>t.to_s}]]
1394
1394
  end
@@ -1401,7 +1401,7 @@ describe "Schema Parser" do
1401
1401
  end
1402
1402
 
1403
1403
  specify "should convert various types of table name arguments" do
1404
- @db.meta_def(:schema_parse_table) do |t, opts|
1404
+ meta_def(@db, :schema_parse_table) do |t, opts|
1405
1405
  [[t, opts]]
1406
1406
  end
1407
1407
  s1 = @db.schema(:x)
@@ -11,7 +11,11 @@ unless Object.const_defined?('Sequel')
11
11
  require 'sequel/core'
12
12
  end
13
13
 
14
- Sequel.extension :meta_def
14
+ (defined?(RSpec) ? RSpec::Core::ExampleGroup : Spec::Example::ExampleGroup).class_eval do
15
+ def meta_def(obj, name, &block)
16
+ (class << obj; self end).send(:define_method, name, &block)
17
+ end
18
+ end
15
19
 
16
20
  if ENV['SEQUEL_COLUMNS_INTROSPECTION']
17
21
  Sequel.extension :columns_introspection
@@ -2,7 +2,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe "AssociationDependencies plugin" do
4
4
  before do
5
- mods = @mods = []
5
+ @mods = []
6
6
  @c = Class.new(Sequel::Model)
7
7
  @c.plugin :association_dependencies
8
8
  @Artist = Class.new(@c).set_dataset(:artists)
@@ -23,7 +23,7 @@ describe "Sequel::Plugins::AssociationProxies" do
23
23
  @i.associations.has_key?(:tags).should == true
24
24
  end
25
25
 
26
- it "should send method calls to the association dataset sent another method" do
26
+ it "should send method calls to the association dataset if sent a non-array method" do
27
27
  @i.associations.has_key?(:tags).should == false
28
28
  @t.filter(:a=>1).sql.should == "SELECT tags.* FROM tags INNER JOIN items_tags ON ((items_tags.tag_id = tags.id) AND (items_tags.item_id = 1)) WHERE (a = 1)"
29
29
  @i.associations.has_key?(:tags).should == false
@@ -0,0 +1,90 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "Sequel::Plugins::AutoValidations" do
4
+ before do
5
+ db = Sequel.mock(:fetch=>{:v=>1})
6
+ def db.schema_parse_table(*) true; end
7
+ def db.schema(t, *)
8
+ t = t.first_source if t.is_a?(Sequel::Dataset)
9
+ return [] if t != :test
10
+ [[:id, {:primary_key=>true, :type=>:integer}],
11
+ [:name, {:primary_key=>false, :type=>:string, :allow_null=>false}],
12
+ [:num, {:primary_key=>false, :type=>:integer, :allow_null=>true}],
13
+ [:d, {:primary_key=>false, :type=>:date, :allow_null=>false}]]
14
+ end
15
+ def db.indexes(t, *)
16
+ return [] if t != :test
17
+ {:a=>{:columns=>[:name, :num], :unique=>true}, :b=>{:columns=>[:num], :unique=>false}}
18
+ end
19
+ @c = Class.new(Sequel::Model(db[:test]))
20
+ @c.send(:def_column_accessor, :id, :name, :num, :d)
21
+ @c.raise_on_typecast_failure = false
22
+ @c.plugin :auto_validations
23
+ @m = @c.new
24
+ db.sqls
25
+ end
26
+
27
+ it "should have automatically created validations" do
28
+ @m.valid?.should be_false
29
+ @m.errors.should == {:d=>["is not present"], :name=>["is not present"]}
30
+
31
+ @m.name = ''
32
+ @m.valid?.should be_false
33
+ @m.errors.should == {:d=>["is not present"]}
34
+
35
+ @m.set(:d=>'/', :num=>'a', :name=>'1')
36
+ @m.valid?.should be_false
37
+ @m.errors.should == {:d=>["is not a valid date"], :num=>["is not a valid integer"]}
38
+
39
+ @m.set(:d=>Date.today, :num=>1)
40
+ @m.valid?.should be_false
41
+ @m.errors.should == {[:name, :num]=>["is already taken"]}
42
+ end
43
+
44
+ it "should allow skipping validations by type" do
45
+ @c = Class.new(@c)
46
+ @m = @c.new
47
+ @c.skip_auto_validations(:presence)
48
+ @m.valid?.should be_true
49
+
50
+ @m.set(:d=>'/', :num=>'a', :name=>'1')
51
+ @m.valid?.should be_false
52
+ @m.errors.should == {:d=>["is not a valid date"], :num=>["is not a valid integer"]}
53
+
54
+ @c.skip_auto_validations(:types)
55
+ @m.valid?.should be_false
56
+ @m.errors.should == {[:name, :num]=>["is already taken"]}
57
+
58
+ @c.skip_auto_validations(:unique)
59
+ @m.valid?.should be_true
60
+ end
61
+
62
+ it "should allow skipping all auto validations" do
63
+ @c = Class.new(@c)
64
+ @m = @c.new
65
+ @c.skip_auto_validations(:all)
66
+ @m.valid?.should be_true
67
+ @m.set(:d=>'/', :num=>'a', :name=>'1')
68
+ @m.valid?.should be_true
69
+ end
70
+
71
+ it "should work correctly in subclasses" do
72
+ @c = Class.new(@c)
73
+ @m = @c.new
74
+ @m.valid?.should be_false
75
+ @m.errors.should == {:d=>["is not present"], :name=>["is not present"]}
76
+
77
+ @m.set(:d=>'/', :num=>'a', :name=>'1')
78
+ @m.valid?.should be_false
79
+ @m.errors.should == {:d=>["is not a valid date"], :num=>["is not a valid integer"]}
80
+
81
+ @m.set(:d=>Date.today, :num=>1)
82
+ @m.valid?.should be_false
83
+ @m.errors.should == {[:name, :num]=>["is already taken"]}
84
+ end
85
+
86
+ it "should work correctly when changing the dataset" do
87
+ @c.set_dataset(@c.db[:foo])
88
+ @c.new.valid?.should be_true
89
+ end
90
+ end
@@ -14,6 +14,7 @@ describe Sequel::Model, "caching" do
14
14
  attr_accessor :ttl
15
15
  def set(k, v, ttl); self[k] = v; @ttl = ttl; end
16
16
  def get(k); if self[k] then return self[k]; else raise ArgumentError; end end
17
+ def delete(k); if self[k] then super; else raise ArgumentError; end end
17
18
  end
18
19
  cache2 = @memcached_class.new
19
20
  @memcached = cache2
@@ -225,10 +226,15 @@ describe Sequel::Model, "caching" do
225
226
 
226
227
  it "should raise an exception if cache_store is memcached and ignore_exception is not enabled" do
227
228
  proc{@c3[1]}.should raise_error
229
+ m = @c3.new.save
230
+ proc{m.update({:name=>'blah'})}.should raise_error
228
231
  end
229
232
 
230
233
  it "should rescue an exception if cache_store is memcached and ignore_exception is enabled" do
231
234
  @c4[1].values.should == {:name => 'sharon', :id => 1}
235
+ m = @c4.new.save
236
+ proc{m.update({:name=>'blah'})}.should_not raise_error
237
+ m.values.should == {:name => 'blah', :id => 1, :x => 1}
232
238
  end
233
239
 
234
240
  it "should support Model.cache_get_pk for getting a value from the cache by primary key" do
@@ -9,7 +9,7 @@ describe "class_table_inheritance plugin" do
9
9
  :executives=>[[:id, {:type=>:integer}], [:num_managers, {:type=>:integer}]],
10
10
  :staff=>[[:id, {:type=>:integer}], [:manager_id, {:type=>:integer}]],
11
11
  }[table.is_a?(Sequel::Dataset) ? table.first_source_table : table]
12
- end
12
+ end
13
13
  @db.extend_datasets do
14
14
  def columns
15
15
  {[:employees]=>[:id, :name, :kind],
@@ -162,6 +162,13 @@ describe "class_table_inheritance plugin" do
162
162
  @db.sqls.should == ["DELETE FROM executives WHERE (id = 1)", "DELETE FROM managers WHERE (id = 1)", "DELETE FROM employees WHERE (id = 1)"]
163
163
  end
164
164
 
165
+ it "should not allow deletion of frozen object" do
166
+ o = Executive.load(:id=>1)
167
+ o.freeze
168
+ proc{o.delete}.should raise_error(Sequel::Error)
169
+ @db.sqls.should == []
170
+ end
171
+
165
172
  it "should insert the correct rows into all tables when inserting" do
166
173
  Executive.create(:num_managers=>3, :num_staff=>2, :name=>'E')
167
174
  sqls = @db.sqls
@@ -91,28 +91,28 @@ describe "Composition plugin" do
91
91
  end
92
92
 
93
93
  it "should clear compositions cache when using set_values" do
94
- @c.composition :date, :composer=>proc{}, :decomposer=>proc{called = true}
94
+ @c.composition :date, :composer=>proc{}, :decomposer=>proc{}
95
95
  @o.date = Date.new(3, 4, 5)
96
96
  @o.set_values(:id=>1)
97
97
  @o.compositions.should == {}
98
98
  end
99
99
 
100
100
  it "should clear compositions cache when refreshing" do
101
- @c.composition :date, :composer=>proc{}, :decomposer=>proc{called = true}
101
+ @c.composition :date, :composer=>proc{}, :decomposer=>proc{}
102
102
  @o.date = Date.new(3, 4, 5)
103
103
  @o.refresh
104
104
  @o.compositions.should == {}
105
105
  end
106
106
 
107
107
  it "should clear compositions cache when refreshing after save" do
108
- @c.composition :date, :composer=>proc{}, :decomposer=>proc{called = true}
108
+ @c.composition :date, :composer=>proc{}, :decomposer=>proc{}
109
109
  @c.create(:date=>Date.new(3, 4, 5)).compositions.should == {}
110
110
  end
111
111
 
112
112
  it "should clear compositions cache when saving with insert_select" do
113
113
  def (@c.instance_dataset).supports_insert_select?() true end
114
114
  def (@c.instance_dataset).insert_select(*) {:id=>1} end
115
- @c.composition :date, :composer=>proc{}, :decomposer=>proc{called = true}
115
+ @c.composition :date, :composer=>proc{}, :decomposer=>proc{}
116
116
  @c.create(:date=>Date.new(3, 4, 5)).compositions.should == {}
117
117
  end
118
118
 
@@ -125,7 +125,7 @@ describe "Composition plugin" do
125
125
 
126
126
  it "should cache value of composition" do
127
127
  times = 0
128
- @c.composition :date, :composer=>proc{times+=1}, :decomposer=>proc{called = true}
128
+ @c.composition :date, :composer=>proc{times+=1}, :decomposer=>proc{}
129
129
  times.should == 0
130
130
  @o.date
131
131
  times.should == 1
@@ -201,6 +201,13 @@ describe "Composition plugin" do
201
201
  sql.should include("day = NULL")
202
202
  end
203
203
 
204
+ it "should work with frozen instances" do
205
+ @c.composition :date, :mapping=>[:year, :month, :day]
206
+ @o.freeze
207
+ @o.date.should == Date.new(1, 2, 3)
208
+ proc{@o.date = Date.today}.should raise_error
209
+ end
210
+
204
211
  it "should work correctly with subclasses" do
205
212
  @c.composition :date, :mapping=>[:year, :month, :day]
206
213
  c = Class.new(@c)