sequel 3.46.0 → 3.47.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -136,7 +136,7 @@ describe Sequel::Model::Associations::AssociationReflection, "#select" do
136
136
  @c.association_reflection(:cs).keys.should_not include(:select)
137
137
  @c.association_reflection(:cs).select.should == Sequel::SQL::ColumnAll.new(:par_parents)
138
138
  end
139
- it "should be if :select is not present for a many_to_one and one_to_many associaiton" do
139
+ it "should be blank if :select is not present for a many_to_one and one_to_many associaiton" do
140
140
  @c.one_to_many :cs, :class=>'ParParent'
141
141
  @c.association_reflection(:cs).keys.should_not include(:select)
142
142
  @c.association_reflection(:cs).select.should == nil
@@ -200,7 +200,7 @@ describe Sequel::Model, "many_to_one" do
200
200
  MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 234) LIMIT 1"]
201
201
  end
202
202
 
203
- it "should allow association with the same name as the key if :key_alias is given" do
203
+ it "should allow association with the same name as the key if :key_column is given" do
204
204
  @c2.def_column_alias(:parent_id_id, :parent_id)
205
205
  @c2.many_to_one :parent_id, :key_column=>:parent_id, :class => @c2
206
206
  d = @c2.load(:id => 1, :parent_id => 234)
@@ -378,7 +378,7 @@ describe Sequel::Model, "many_to_one" do
378
378
  MODEL_DB.sqls.should == ['UPDATE nodes SET parent_id = 345 WHERE (id = 1)']
379
379
  end
380
380
 
381
- it "should set cached instance variable when accessed" do
381
+ it "should populate cache when accessed" do
382
382
  @c2.many_to_one :parent, :class => @c2
383
383
 
384
384
  d = @c2.load(:id => 1)
@@ -390,7 +390,7 @@ describe Sequel::Model, "many_to_one" do
390
390
  d.associations[:parent].should == e
391
391
  end
392
392
 
393
- it "should set cached instance variable when assigned" do
393
+ it "should populate cache when assigned" do
394
394
  @c2.many_to_one :parent, :class => @c2
395
395
 
396
396
  d = @c2.create(:id => 1)
@@ -402,7 +402,7 @@ describe Sequel::Model, "many_to_one" do
402
402
  MODEL_DB.sqls.should == []
403
403
  end
404
404
 
405
- it "should use cached instance variable if available" do
405
+ it "should use cache if available" do
406
406
  @c2.many_to_one :parent, :class => @c2
407
407
 
408
408
  d = @c2.create(:id => 1, :parent_id => 234)
@@ -412,7 +412,7 @@ describe Sequel::Model, "many_to_one" do
412
412
  MODEL_DB.sqls.should == []
413
413
  end
414
414
 
415
- it "should not use cached instance variable if asked to reload" do
415
+ it "should not use cache if asked to reload" do
416
416
  @c2.many_to_one :parent, :class => @c2
417
417
 
418
418
  d = @c2.create(:id => 1)
@@ -445,7 +445,7 @@ describe Sequel::Model, "many_to_one" do
445
445
  MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.id = 234) AND (name > 'M')) LIMIT 1"]
446
446
  end
447
447
 
448
- it "should have the setter add to the reciprocal one_to_many cached association list if it exists" do
448
+ it "should have the setter add to the reciprocal one_to_many cached association array if it exists" do
449
449
  @c2.many_to_one :parent, :class => @c2
450
450
  @c2.one_to_many :children, :class => @c2, :key=>:parent_id
451
451
  @c2.dataset._fetch = []
@@ -466,7 +466,7 @@ describe Sequel::Model, "many_to_one" do
466
466
  MODEL_DB.sqls.should == []
467
467
  end
468
468
 
469
- it "should have many_to_one setter deal with a one_to_one reciprocal" do
469
+ it "should have setter deal with a one_to_one reciprocal" do
470
470
  @c2.many_to_one :parent, :class => @c2, :key=>:parent_id
471
471
  @c2.one_to_one :child, :class => @c2, :key=>:parent_id
472
472
 
@@ -488,7 +488,7 @@ describe Sequel::Model, "many_to_one" do
488
488
  e.child.should == d
489
489
  end
490
490
 
491
- it "should have the setter remove the object from the previous associated object's reciprocal one_to_many cached association list if it exists" do
491
+ it "should have the setter remove the object from the previous associated object's reciprocal one_to_many cached association array if it exists" do
492
492
  @c2.many_to_one :parent, :class => @c2
493
493
  @c2.one_to_many :children, :class => @c2, :key=>:parent_id
494
494
  @c2.dataset._fetch = []
@@ -583,6 +583,15 @@ describe Sequel::Model, "many_to_one" do
583
583
  p.instance_variable_get(:@x).should == c
584
584
  end
585
585
 
586
+ it "should have the :setter option define the _association= method" do
587
+ @c2.many_to_one :parent, :class => @c2, :setter=>proc{|x| @x = x}
588
+ p = @c2.new
589
+ c = @c2.load(:id=>123)
590
+ p.should_not_receive(:parent_id=)
591
+ p.parent = c
592
+ p.instance_variable_get(:@x).should == c
593
+ end
594
+
586
595
  it "should support (before|after)_set callbacks" do
587
596
  h = []
588
597
  @c2.many_to_one :parent, :class => @c2, :before_set=>[proc{|x,y| h << x.pk; h << (y ? -y.pk : :y)}, :blah], :after_set=>proc{h << 3}
@@ -656,28 +665,6 @@ describe Sequel::Model, "many_to_one" do
656
665
  @c2.many_to_one :parent, :class => @c2, :before_set=>Object.new
657
666
  proc{@c2.new.parent = @c2.load(:id=>1)}.should raise_error(Sequel::Error)
658
667
  end
659
-
660
- it "should call the remove callbacks for the previous object and the add callbacks for the new object" do
661
- c = @c2.load(:id=>123)
662
- d = @c2.load(:id=>321)
663
- p = @c2.new
664
- p.associations[:parent] = d
665
- @c2.many_to_one :parent, :class => @c2, :before_set=>:bs, :after_set=>:as
666
- @c2.class_eval do
667
- self::Foo = []
668
- def []=(a, v)
669
- a == :parent_id ? (model::Foo << 5) : super
670
- end
671
- def bs(x)
672
- model::Foo << x.pk
673
- end
674
- def as(x)
675
- model::Foo << x.pk * 2
676
- end
677
- end
678
- p.parent = c
679
- @c2::Foo.should == [123, 5, 246]
680
- end
681
668
  end
682
669
 
683
670
  describe Sequel::Model, "one_to_one" do
@@ -918,7 +905,7 @@ describe Sequel::Model, "one_to_one" do
918
905
  "UPDATE nodes SET node_id = 1 WHERE (id = 3)"]
919
906
  end
920
907
 
921
- it "should set cached instance variable when accessed" do
908
+ it "should populate cache when accessed" do
922
909
  @c2.one_to_one :parent, :class => @c2
923
910
 
924
911
  d = @c2.load(:id => 1)
@@ -931,7 +918,7 @@ describe Sequel::Model, "one_to_one" do
931
918
  d.associations[:parent].should == e
932
919
  end
933
920
 
934
- it "should set cached instance variable when assigned" do
921
+ it "should populate cache when assigned" do
935
922
  @c2.one_to_one :parent, :class => @c2
936
923
 
937
924
  d = @c2.load(:id => 1)
@@ -943,7 +930,7 @@ describe Sequel::Model, "one_to_one" do
943
930
  e.should == f
944
931
  end
945
932
 
946
- it "should use cached instance variable if available" do
933
+ it "should use cache if available" do
947
934
  @c2.one_to_one :parent, :class => @c2
948
935
  d = @c2.load(:id => 1, :parent_id => 234)
949
936
  d.associations[:parent] = 42
@@ -951,7 +938,7 @@ describe Sequel::Model, "one_to_one" do
951
938
  MODEL_DB.sqls.should == []
952
939
  end
953
940
 
954
- it "should not use cached instance variable if asked to reload" do
941
+ it "should not use cache if asked to reload" do
955
942
  @c2.one_to_one :parent, :class => @c2
956
943
  d = @c2.load(:id => 1)
957
944
  d.associations[:parent] = [42]
@@ -974,7 +961,7 @@ describe Sequel::Model, "one_to_one" do
974
961
  MODEL_DB.sqls.should == ["UPDATE nodes SET parent_id = NULL WHERE (parent_id = 1)"]
975
962
  end
976
963
 
977
- it "should have the setter remove the object from the previous associated object's reciprocal many_to_one cached association list if it exists" do
964
+ it "should have the setter remove the object from the previous associated object's reciprocal many_to_one cached association array if it exists" do
978
965
  @c2.one_to_one :parent, :class => @c2, :key=>:parent_id
979
966
  @c2.many_to_one :child, :class => @c2, :key=>:parent_id
980
967
  @c2.dataset._fetch = []
@@ -1034,6 +1021,15 @@ describe Sequel::Model, "one_to_one" do
1034
1021
  p.instance_variable_get(:@x).should == c
1035
1022
  end
1036
1023
 
1024
+ it "should have a :setter option define the _association= method" do
1025
+ @c2.one_to_one :parent, :class => @c2, :setter=>proc{|x| @x = x}
1026
+ c = @c2.new
1027
+ p = @c2.load(:id=>123)
1028
+ p.should_not_receive(:parent_id=)
1029
+ p.parent = c
1030
+ p.instance_variable_get(:@x).should == c
1031
+ end
1032
+
1037
1033
  it "should support (before|after)_set callbacks" do
1038
1034
  h = []
1039
1035
  @c2.one_to_one :parent, :class => @c2, :before_set=>[proc{|x,y| h << x.pk; h << (y ? -y.pk : :y)}, :blah], :after_set=>proc{h << 3}
@@ -1093,29 +1089,6 @@ describe Sequel::Model, "one_to_one" do
1093
1089
  proc{@c2.new.parent = @c2.load(:id=>1)}.should raise_error(Sequel::Error)
1094
1090
  end
1095
1091
 
1096
- it "should call the set callbacks" do
1097
- c = @c2.load(:id=>123)
1098
- d = @c2.load(:id=>321)
1099
- p = @c2.load(:id=>32)
1100
- p.associations[:parent] = [d]
1101
- h = []
1102
- @c2.one_to_one :parent, :class => @c2, :before_set=>:bs, :after_set=>:as
1103
- @c2.class_eval do
1104
- self::Foo = h
1105
- def []=(a, v)
1106
- a == :node_id ? (model::Foo << 5) : super
1107
- end
1108
- def bs(x)
1109
- model::Foo << x.pk
1110
- end
1111
- def as(x)
1112
- model::Foo << x.pk * 2
1113
- end
1114
- end
1115
- p.parent = c
1116
- h.should == [123, 5, 246]
1117
- end
1118
-
1119
1092
  it "should work_correctly when used with associate" do
1120
1093
  @c2.associate :one_to_one, :parent, :class => @c2
1121
1094
  @c2.load(:id => 567).parent.should == @c2.load({})
@@ -1419,21 +1392,21 @@ describe Sequel::Model, "one_to_many" do
1419
1392
  @c2.new(:id => 1234).attributes_dataset.sql.should == "SELECT * FROM attributes WHERE (attributes.node_id = 1234) ORDER BY kind1, kind2"
1420
1393
  end
1421
1394
 
1422
- it "should return array with all members of the association" do
1395
+ it "should have a dataset method for the associated object dataset" do
1423
1396
  @c2.one_to_many :attributes, :class => @c1
1424
1397
  @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE (attributes.node_id = 1234)'
1425
1398
  end
1426
1399
 
1427
1400
  it "should accept a block" do
1428
1401
  @c2.one_to_many :attributes, :class => @c1 do |ds|
1429
- ds.filter(:xxx => @xxx)
1402
+ ds.filter(:xxx => nil)
1430
1403
  end
1431
1404
  @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (xxx IS NULL))'
1432
1405
  end
1433
1406
 
1434
1407
  it "should support :order option with block" do
1435
1408
  @c2.one_to_many :attributes, :class => @c1, :order => :kind do |ds|
1436
- ds.filter(:xxx => @xxx)
1409
+ ds.filter(:xxx => nil)
1437
1410
  end
1438
1411
  @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (xxx IS NULL)) ORDER BY kind'
1439
1412
  end
@@ -1467,7 +1440,7 @@ describe Sequel::Model, "one_to_many" do
1467
1440
  @c2.new(:id => 1234).attributes_dataset.opts[:eager].should == {:attributes=>nil}
1468
1441
  end
1469
1442
 
1470
- it "should set cached instance variable when accessed" do
1443
+ it "should populate cache when accessed" do
1471
1444
  @c2.one_to_many :attributes, :class => @c1
1472
1445
  n = @c2.new(:id => 1234)
1473
1446
  n.associations.include?(:attributes).should == false
@@ -1476,7 +1449,7 @@ describe Sequel::Model, "one_to_many" do
1476
1449
  MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
1477
1450
  end
1478
1451
 
1479
- it "should use cached instance variable if available" do
1452
+ it "should use cache if available" do
1480
1453
  @c2.one_to_many :attributes, :class => @c1
1481
1454
  n = @c2.new(:id => 1234)
1482
1455
  n.associations[:attributes] = 42
@@ -1484,7 +1457,7 @@ describe Sequel::Model, "one_to_many" do
1484
1457
  MODEL_DB.sqls.should == []
1485
1458
  end
1486
1459
 
1487
- it "should not use cached instance variable if asked to reload" do
1460
+ it "should not use cache if asked to reload" do
1488
1461
  @c2.one_to_many :attributes, :class => @c1
1489
1462
  n = @c2.new(:id => 1234)
1490
1463
  n.associations[:attributes] = 42
@@ -1492,7 +1465,7 @@ describe Sequel::Model, "one_to_many" do
1492
1465
  MODEL_DB.sqls.should == ['SELECT * FROM attributes WHERE (attributes.node_id = 1234)']
1493
1466
  end
1494
1467
 
1495
- it "should add item to cached instance variable if it exists when calling add_" do
1468
+ it "should add item to cache if it exists when calling add_" do
1496
1469
  @c2.one_to_many :attributes, :class => @c1
1497
1470
  n = @c2.new(:id => 1234)
1498
1471
  att = @c1.load(:id => 345)
@@ -1502,7 +1475,7 @@ describe Sequel::Model, "one_to_many" do
1502
1475
  a.should == [att]
1503
1476
  end
1504
1477
 
1505
- it "should set object to item's reciprocal cached association variable when calling add_" do
1478
+ it "should set object to item's reciprocal cache when calling add_" do
1506
1479
  @c2.one_to_many :attributes, :class => @c1
1507
1480
  @c1.many_to_one :node, :class => @c2
1508
1481
 
@@ -1512,7 +1485,7 @@ describe Sequel::Model, "one_to_many" do
1512
1485
  att.node.should == n
1513
1486
  end
1514
1487
 
1515
- it "should remove item from cached instance variable if it exists when calling remove_" do
1488
+ it "should remove item from cache if it exists when calling remove_" do
1516
1489
  @c2.one_to_many :attributes, :class => @c1
1517
1490
 
1518
1491
  n = @c2.load(:id => 1234)
@@ -1523,7 +1496,7 @@ describe Sequel::Model, "one_to_many" do
1523
1496
  a.should == []
1524
1497
  end
1525
1498
 
1526
- it "should remove item's reciprocal cached association variable when calling remove_" do
1499
+ it "should remove item's reciprocal cache calling remove_" do
1527
1500
  @c2.one_to_many :attributes, :class => @c1
1528
1501
  @c1.many_to_one :node, :class => @c2
1529
1502
 
@@ -1561,7 +1534,7 @@ describe Sequel::Model, "one_to_many" do
1561
1534
  im2.should_not(include('remove_all_attributes'))
1562
1535
  end
1563
1536
 
1564
- it "should populate the reciprocal many_to_one instance variable when loading the one_to_many association" do
1537
+ it "should populate the reciprocal many_to_one cache when loading the one_to_many association" do
1565
1538
  @c2.one_to_many :attributes, :class => @c1, :key => :node_id
1566
1539
  @c1.many_to_one :node, :class => @c2, :key => :node_id
1567
1540
 
@@ -1573,7 +1546,7 @@ describe Sequel::Model, "one_to_many" do
1573
1546
  MODEL_DB.sqls.should == []
1574
1547
  end
1575
1548
 
1576
- it "should use an explicit reciprocal instance variable if given" do
1549
+ it "should use an explicit :reciprocal option if given" do
1577
1550
  @c2.one_to_many :attributes, :class => @c1, :key => :node_id, :reciprocal=>:wxyz
1578
1551
 
1579
1552
  n = @c2.new(:id => 1234)
@@ -1584,7 +1557,7 @@ describe Sequel::Model, "one_to_many" do
1584
1557
  MODEL_DB.sqls.should == []
1585
1558
  end
1586
1559
 
1587
- it "should have an remove_all_ method that removes all associations" do
1560
+ it "should have an remove_all_ method that removes all associated objects" do
1588
1561
  @c2.one_to_many :attributes, :class => @c1
1589
1562
  @c2.new(:id => 1234).remove_all_attributes
1590
1563
  MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE (node_id = 1234)']
@@ -1612,14 +1585,14 @@ describe Sequel::Model, "one_to_many" do
1612
1585
  sqls.should == []
1613
1586
  end
1614
1587
 
1615
- it "remove_all should set the cached instance variable to []" do
1588
+ it "remove_all should set the cache to []" do
1616
1589
  @c2.one_to_many :attributes, :class => @c1
1617
1590
  node = @c2.new(:id => 1234)
1618
1591
  node.remove_all_attributes
1619
1592
  node.associations[:attributes].should == []
1620
1593
  end
1621
1594
 
1622
- it "remove_all should return the array of previously associated items if the cached instance variable exists" do
1595
+ it "remove_all should return the array of previously associated items if the cache is populated" do
1623
1596
  @c2.one_to_many :attributes, :class => @c1
1624
1597
  attrib = @c1.new(:id=>3)
1625
1598
  node = @c2.new(:id => 1234)
@@ -1630,12 +1603,12 @@ describe Sequel::Model, "one_to_many" do
1630
1603
  node.remove_all_attributes.should == [attrib]
1631
1604
  end
1632
1605
 
1633
- it "remove_all should return nil if the cached instance variable does not exist" do
1606
+ it "remove_all should return nil if the cache is not populated" do
1634
1607
  @c2.one_to_many :attributes, :class => @c1
1635
1608
  @c2.new(:id => 1234).remove_all_attributes.should == nil
1636
1609
  end
1637
1610
 
1638
- it "remove_all should remove the current item from all reciprocal instance varaibles if it cached instance variable exists" do
1611
+ it "remove_all should remove the current item from all reciprocal association caches if they are populated" do
1639
1612
  @c2.one_to_many :attributes, :class => @c1
1640
1613
  @c1.many_to_one :node, :class => @c2
1641
1614
  @c2.dataset._fetch = []
@@ -1663,6 +1636,15 @@ describe Sequel::Model, "one_to_many" do
1663
1636
  p.instance_variable_get(:@x).should == c
1664
1637
  end
1665
1638
 
1639
+ it "should support an :adder option for defining the _add_ method" do
1640
+ @c2.one_to_many :attributes, :class => @c1, :adder=>proc{|x| @x = x}
1641
+ p = @c2.load(:id=>10)
1642
+ c = @c1.load(:id=>123)
1643
+ c.should_not_receive(:node_id=)
1644
+ p.add_attribute(c)
1645
+ p.instance_variable_get(:@x).should == c
1646
+ end
1647
+
1666
1648
  it "should allow additional arguments given to the add_ method and pass them onwards to the _add_ method" do
1667
1649
  @c2.one_to_many :attributes, :class => @c1
1668
1650
  p = @c2.load(:id=>10)
@@ -1690,6 +1672,15 @@ describe Sequel::Model, "one_to_many" do
1690
1672
  p.instance_variable_get(:@x).should == c
1691
1673
  end
1692
1674
 
1675
+ it "should support a :remover option for defining the _remove_ method" do
1676
+ @c2.one_to_many :attributes, :class => @c1, :remover=>proc{|x| @x = x}
1677
+ p = @c2.load(:id=>10)
1678
+ c = @c1.load(:id=>123)
1679
+ c.should_not_receive(:node_id=)
1680
+ p.remove_attribute(c)
1681
+ p.instance_variable_get(:@x).should == c
1682
+ end
1683
+
1693
1684
  it "should allow additional arguments given to the remove_ method and pass them onwards to the _remove_ method" do
1694
1685
  @c2.one_to_many :attributes, :class => @c1
1695
1686
  p = @c2.load(:id=>10)
@@ -1727,6 +1718,13 @@ describe Sequel::Model, "one_to_many" do
1727
1718
  p.instance_variable_get(:@x).should == :foo
1728
1719
  end
1729
1720
 
1721
+ it "should support a :clearer option for defining the _remove_all_ method" do
1722
+ @c2.one_to_many :attributes, :class => @c1, :clearer=>proc{@x = :foo}
1723
+ p = @c2.load(:id=>10)
1724
+ p.remove_all_attributes
1725
+ p.instance_variable_get(:@x).should == :foo
1726
+ end
1727
+
1730
1728
  it "should support (before|after)_(add|remove) callbacks" do
1731
1729
  h = []
1732
1730
  @c2.one_to_many :attributes, :class => @c1, :before_add=>[proc{|x,y| h << x.pk; h << -y.pk}, :blah], :after_add=>proc{h << 3}, :before_remove=>:blah, :after_remove=>[:blahr]
@@ -1965,7 +1963,6 @@ describe Sequel::Model, "many_to_many" do
1965
1963
  end
1966
1964
 
1967
1965
  it "should support a :dataset option that accepts the reflection as an argument" do
1968
- c1 = @c1
1969
1966
  @c2.many_to_many :attributes, :class => @c1, :dataset=>lambda{|opts| opts.associated_dataset.join_table(:natural, :an).filter(:an__nodeid=>pk)}, :order=> :a, :limit=>10, :select=>nil do |ds|
1970
1967
  ds.filter(:xxx => @xxx)
1971
1968
  end
@@ -2220,7 +2217,7 @@ describe Sequel::Model, "many_to_many" do
2220
2217
  MODEL_DB.sqls.should == ['SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))']
2221
2218
  end
2222
2219
 
2223
- it "should set cached instance variable when accessed" do
2220
+ it "should populate cache when accessed" do
2224
2221
  @c2.many_to_many :attributes, :class => @c1
2225
2222
 
2226
2223
  n = @c2.new(:id => 1234)
@@ -2229,7 +2226,7 @@ describe Sequel::Model, "many_to_many" do
2229
2226
  atts.should == n.associations[:attributes]
2230
2227
  end
2231
2228
 
2232
- it "should use cached instance variable if available" do
2229
+ it "should use cache if available" do
2233
2230
  @c2.many_to_many :attributes, :class => @c1
2234
2231
 
2235
2232
  n = @c2.new(:id => 1234)
@@ -2238,7 +2235,7 @@ describe Sequel::Model, "many_to_many" do
2238
2235
  MODEL_DB.sqls.should == []
2239
2236
  end
2240
2237
 
2241
- it "should not use cached instance variable if asked to reload" do
2238
+ it "should not use cache if asked to reload" do
2242
2239
  @c2.many_to_many :attributes, :class => @c1
2243
2240
 
2244
2241
  n = @c2.new(:id => 1234)
@@ -2247,7 +2244,7 @@ describe Sequel::Model, "many_to_many" do
2247
2244
  MODEL_DB.sqls.should == ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))"]
2248
2245
  end
2249
2246
 
2250
- it "should add item to cached instance variable if it exists when calling add_" do
2247
+ it "should add item to cache if it exists when calling add_" do
2251
2248
  @c2.many_to_many :attributes, :class => @c1
2252
2249
 
2253
2250
  n = @c2.new(:id => 1234)
@@ -2258,7 +2255,7 @@ describe Sequel::Model, "many_to_many" do
2258
2255
  a.should == [att]
2259
2256
  end
2260
2257
 
2261
- it "should add item to reciprocal cached instance variable if it exists when calling add_" do
2258
+ it "should add item to reciprocal's cache if it exists when calling add_" do
2262
2259
  @c2.many_to_many :attributes, :class => @c1
2263
2260
  @c1.many_to_many :nodes, :class => @c2
2264
2261
 
@@ -2269,7 +2266,7 @@ describe Sequel::Model, "many_to_many" do
2269
2266
  att.nodes.should == [n]
2270
2267
  end
2271
2268
 
2272
- it "should remove item from cached instance variable if it exists when calling remove_" do
2269
+ it "should remove item from cache if it exists when calling remove_" do
2273
2270
  @c2.many_to_many :attributes, :class => @c1
2274
2271
 
2275
2272
  n = @c2.new(:id => 1234)
@@ -2280,7 +2277,7 @@ describe Sequel::Model, "many_to_many" do
2280
2277
  a.should == []
2281
2278
  end
2282
2279
 
2283
- it "should remove item from reciprocal cached instance variable if it exists when calling remove_" do
2280
+ it "should remove item from reciprocal's if it exists when calling remove_" do
2284
2281
  @c2.many_to_many :attributes, :class => @c1
2285
2282
  @c1.many_to_many :nodes, :class => @c2
2286
2283
 
@@ -2398,6 +2395,15 @@ describe Sequel::Model, "many_to_many" do
2398
2395
  MODEL_DB.sqls.should == []
2399
2396
  end
2400
2397
 
2398
+ it "should support an :adder option for defining the _add_ method" do
2399
+ @c2.many_to_many :attributes, :class => @c1, :adder=>proc{|x| @x = x}
2400
+ p = @c2.load(:id=>10)
2401
+ c = @c1.load(:id=>123)
2402
+ p.add_attribute(c)
2403
+ p.instance_variable_get(:@x).should == c
2404
+ MODEL_DB.sqls.should == []
2405
+ end
2406
+
2401
2407
  it "should allow additional arguments given to the add_ method and pass them onwards to the _add_ method" do
2402
2408
  @c2.many_to_many :attributes, :class => @c1
2403
2409
  p = @c2.load(:id=>10)
@@ -2424,6 +2430,15 @@ describe Sequel::Model, "many_to_many" do
2424
2430
  MODEL_DB.sqls.should == []
2425
2431
  end
2426
2432
 
2433
+ it "should support a :remover option for defining the _remove_ method" do
2434
+ @c2.many_to_many :attributes, :class => @c1, :remover=>proc{|x| @x = x}
2435
+ p = @c2.load(:id=>10)
2436
+ c = @c1.load(:id=>123)
2437
+ p.remove_attribute(c)
2438
+ p.instance_variable_get(:@x).should == c
2439
+ MODEL_DB.sqls.should == []
2440
+ end
2441
+
2427
2442
  it "should allow additional arguments given to the remove_ method and pass them onwards to the _remove_ method" do
2428
2443
  @c2.many_to_many :attributes, :class => @c1
2429
2444
  p = @c2.load(:id=>10)
@@ -2440,7 +2455,6 @@ describe Sequel::Model, "many_to_many" do
2440
2455
  it "should allow additional arguments given to the remove_all_ method and pass them onwards to the _remove_all_ method" do
2441
2456
  @c2.many_to_many :attributes, :class => @c1
2442
2457
  p = @c2.load(:id=>10)
2443
- c = @c1.load(:id=>123)
2444
2458
  def p._remove_all_attributes(*y)
2445
2459
  @y = y
2446
2460
  end
@@ -2460,6 +2474,14 @@ describe Sequel::Model, "many_to_many" do
2460
2474
  MODEL_DB.sqls.should == []
2461
2475
  end
2462
2476
 
2477
+ it "should support a :clearer option for defining the _remove_all_ method" do
2478
+ @c2.many_to_many :attributes, :class => @c1, :clearer=>proc{@x = :foo}
2479
+ p = @c2.load(:id=>10)
2480
+ p.remove_all_attributes
2481
+ p.instance_variable_get(:@x).should == :foo
2482
+ MODEL_DB.sqls.should == []
2483
+ end
2484
+
2463
2485
  it "should support (before|after)_(add|remove) callbacks" do
2464
2486
  h = []
2465
2487
  @c2.many_to_many :attributes, :class => @c1, :before_add=>[proc{|x,y| h << x.pk; h << -y.pk}, :blah], :after_add=>proc{h << 3}, :before_remove=>:blah, :after_remove=>[:blahr]