sequel 4.43.0 → 4.44.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.
- checksums.yaml +4 -4
- data/CHANGELOG +40 -0
- data/doc/active_record.rdoc +2 -2
- data/doc/code_order.rdoc +15 -0
- data/doc/dataset_filtering.rdoc +1 -1
- data/doc/model_dataset_method_design.rdoc +132 -0
- data/doc/opening_databases.rdoc +2 -2
- data/doc/release_notes/4.44.0.txt +125 -0
- data/lib/sequel/adapters/jdbc.rb +5 -1
- data/lib/sequel/adapters/jdbc/as400.rb +1 -1
- data/lib/sequel/adapters/postgres.rb +23 -14
- data/lib/sequel/core.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +27 -0
- data/lib/sequel/dataset/actions.rb +1 -1
- data/lib/sequel/dataset/query.rb +5 -1
- data/lib/sequel/extensions/eval_inspect.rb +4 -4
- data/lib/sequel/extensions/implicit_subquery.rb +48 -0
- data/lib/sequel/extensions/to_dot.rb +1 -1
- data/lib/sequel/model.rb +3 -5
- data/lib/sequel/model/associations.rb +107 -4
- data/lib/sequel/model/base.rb +98 -12
- data/lib/sequel/model/dataset_module.rb +1 -1
- data/lib/sequel/plugins/active_model.rb +11 -3
- data/lib/sequel/plugins/association_dependencies.rb +7 -0
- data/lib/sequel/plugins/auto_validations.rb +10 -0
- data/lib/sequel/plugins/blacklist_security.rb +13 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +11 -0
- data/lib/sequel/plugins/column_conflicts.rb +8 -0
- data/lib/sequel/plugins/composition.rb +12 -2
- data/lib/sequel/plugins/constraint_validations.rb +12 -0
- data/lib/sequel/plugins/csv_serializer.rb +9 -0
- data/lib/sequel/plugins/defaults_setter.rb +6 -0
- data/lib/sequel/plugins/force_encoding.rb +4 -3
- data/lib/sequel/plugins/hook_class_methods.rb +6 -0
- data/lib/sequel/plugins/input_transformer.rb +9 -0
- data/lib/sequel/plugins/insert_returning_select.rb +8 -0
- data/lib/sequel/plugins/instance_hooks.rb +4 -3
- data/lib/sequel/plugins/json_serializer.rb +9 -0
- data/lib/sequel/plugins/lazy_attributes.rb +7 -0
- data/lib/sequel/plugins/many_through_many.rb +13 -2
- data/lib/sequel/plugins/nested_attributes.rb +7 -0
- data/lib/sequel/plugins/pg_array_associations.rb +18 -2
- data/lib/sequel/plugins/pg_row.rb +3 -3
- data/lib/sequel/plugins/pg_typecast_on_load.rb +7 -0
- data/lib/sequel/plugins/prepared_statements.rb +2 -2
- data/lib/sequel/plugins/prepared_statements_safe.rb +7 -0
- data/lib/sequel/plugins/serialization.rb +9 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +13 -1
- data/lib/sequel/plugins/subclasses.rb +15 -1
- data/lib/sequel/plugins/touch.rb +7 -0
- data/lib/sequel/plugins/tree.rb +7 -0
- data/lib/sequel/plugins/typecast_on_load.rb +7 -0
- data/lib/sequel/plugins/update_refresh.rb +24 -13
- data/lib/sequel/plugins/validation_class_methods.rb +13 -0
- data/lib/sequel/sql.rb +28 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +18 -15
- data/spec/core/dataset_spec.rb +5 -0
- data/spec/core/expression_filters_spec.rb +33 -0
- data/spec/extensions/active_model_spec.rb +15 -1
- data/spec/extensions/association_dependencies_spec.rb +8 -0
- data/spec/extensions/auto_validations_spec.rb +8 -0
- data/spec/extensions/blacklist_security_spec.rb +6 -0
- data/spec/extensions/class_table_inheritance_spec.rb +9 -0
- data/spec/extensions/column_conflicts_spec.rb +6 -0
- data/spec/extensions/composition_spec.rb +8 -0
- data/spec/extensions/constraint_validations_plugin_spec.rb +12 -0
- data/spec/extensions/csv_serializer_spec.rb +7 -0
- data/spec/extensions/defaults_setter_spec.rb +7 -0
- data/spec/extensions/force_encoding_spec.rb +14 -0
- data/spec/extensions/hook_class_methods_spec.rb +10 -0
- data/spec/extensions/implicit_subquery_spec.rb +60 -0
- data/spec/extensions/input_transformer_spec.rb +10 -0
- data/spec/extensions/insert_returning_select_spec.rb +6 -0
- data/spec/extensions/json_serializer_spec.rb +7 -0
- data/spec/extensions/lazy_attributes_spec.rb +6 -0
- data/spec/extensions/many_through_many_spec.rb +44 -0
- data/spec/extensions/nested_attributes_spec.rb +5 -0
- data/spec/extensions/pg_array_associations_spec.rb +46 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +5 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +5 -0
- data/spec/extensions/serialization_spec.rb +7 -0
- data/spec/extensions/single_table_inheritance_spec.rb +19 -2
- data/spec/extensions/subclasses_spec.rb +13 -0
- data/spec/extensions/to_dot_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +6 -0
- data/spec/extensions/tree_spec.rb +6 -0
- data/spec/extensions/typecast_on_load_spec.rb +6 -0
- data/spec/extensions/update_refresh_spec.rb +7 -1
- data/spec/extensions/validation_class_methods_spec.rb +13 -0
- data/spec/model/association_reflection_spec.rb +177 -0
- data/spec/model/associations_spec.rb +16 -0
- data/spec/model/dataset_methods_spec.rb +59 -0
- data/spec/model/model_spec.rb +59 -0
- metadata +8 -2
@@ -694,4 +694,9 @@ describe "NestedAttributes plugin" do
|
|
694
694
|
@Tag.columns :id, :name, :number
|
695
695
|
proc{@Album.load(:id=>10, :name=>'Al').set_nested_attributes(:tags, [{:id=>30, :name=>'T2', :number=>3}], :fields=>[:name])}.must_raise(Sequel::Error)
|
696
696
|
end
|
697
|
+
|
698
|
+
it "should freeze nested_attributes_module when freezing model class" do
|
699
|
+
@Artist.freeze
|
700
|
+
@Artist.nested_attributes_module.frozen?.must_equal true
|
701
|
+
end
|
697
702
|
end
|
@@ -735,3 +735,49 @@ describe Sequel::Model, "pg_array_associations" do
|
|
735
735
|
t.artists.must_equal [a]
|
736
736
|
end
|
737
737
|
end
|
738
|
+
|
739
|
+
describe "Sequel::Model.finalize_associations" do
|
740
|
+
before do
|
741
|
+
class ::Foo < Sequel::Model
|
742
|
+
plugin :pg_array_associations
|
743
|
+
many_to_pg_array :items
|
744
|
+
end
|
745
|
+
class ::Item < Sequel::Model
|
746
|
+
plugin :pg_array_associations
|
747
|
+
pg_array_to_many :foos
|
748
|
+
end
|
749
|
+
[Foo, Item].each(&:finalize_associations)
|
750
|
+
end
|
751
|
+
after do
|
752
|
+
Object.send(:remove_const, :Item)
|
753
|
+
Object.send(:remove_const, :Foo)
|
754
|
+
end
|
755
|
+
|
756
|
+
it "should finalize pg_array_to_many associations" do
|
757
|
+
r = Item.association_reflection(:foos)
|
758
|
+
r[:class].must_equal Foo
|
759
|
+
r[:_dataset].sql.must_equal "SELECT * FROM foos"
|
760
|
+
r[:associated_eager_dataset].sql.must_equal "SELECT * FROM foos"
|
761
|
+
r.fetch(:_eager_limit_strategy).must_be_nil
|
762
|
+
r[:filter_by_associations_conditions_dataset].sql.must_equal "SELECT array_agg(foos.id) FROM foos WHERE (foos.id IS NOT NULL)"
|
763
|
+
r[:predicate_key].must_equal Sequel.qualify(:foos, :id)
|
764
|
+
r[:predicate_keys].must_equal [Sequel.qualify(:foos, :id)]
|
765
|
+
r[:reciprocal].must_equal :items
|
766
|
+
r[:array_type].must_equal :integer
|
767
|
+
r[:primary_key].must_equal :id
|
768
|
+
r[:primary_key_method].must_equal :id
|
769
|
+
end
|
770
|
+
|
771
|
+
it "should finalize many_to_pg_array associations" do
|
772
|
+
r = Foo.association_reflection(:items)
|
773
|
+
r[:class].must_equal Item
|
774
|
+
r[:_dataset].sql.must_equal "SELECT * FROM items"
|
775
|
+
r[:associated_eager_dataset].sql.must_equal "SELECT * FROM items"
|
776
|
+
r.fetch(:_eager_limit_strategy).must_be_nil
|
777
|
+
r[:filter_by_associations_conditions_dataset].sql.must_equal "SELECT unnest(items.foo_ids) FROM items WHERE (items.foo_ids IS NOT NULL)"
|
778
|
+
r[:predicate_key].must_equal Sequel.qualify(:items, :foo_ids)
|
779
|
+
r[:predicate_keys].must_equal [Sequel.qualify(:items, :foo_ids)]
|
780
|
+
r[:reciprocal].must_equal :foos
|
781
|
+
r[:array_type].must_equal :integer
|
782
|
+
end
|
783
|
+
end
|
@@ -60,4 +60,9 @@ describe Sequel::Model, "PgTypecastOnLoad plugin" do
|
|
60
60
|
it "should not mark the object as modified" do
|
61
61
|
@c.first.modified?.must_equal false
|
62
62
|
end
|
63
|
+
|
64
|
+
it "should freeze pg_typecast_on_load_columns" do
|
65
|
+
@c.freeze
|
66
|
+
@c.pg_typecast_on_load_columns.frozen?.must_equal true
|
67
|
+
end
|
63
68
|
end
|
@@ -58,4 +58,9 @@ describe "prepared_statements_safe plugin" do
|
|
58
58
|
c1.prepared_statements_column_defaults.must_equal(:name=>'foo')
|
59
59
|
Class.new(c1).prepared_statements_column_defaults.must_equal(:name=>'foo')
|
60
60
|
end
|
61
|
+
|
62
|
+
it "should freeze prepared statement column defaults when freezing model class" do
|
63
|
+
@c.freeze
|
64
|
+
@c.prepared_statements_column_defaults.frozen?.must_equal true
|
65
|
+
end
|
61
66
|
end
|
@@ -361,4 +361,11 @@ describe "Serialization plugin" do
|
|
361
361
|
o.column_changes.must_equal(:abc=>[1, 2], :def=>["hello", "hello2"])
|
362
362
|
end
|
363
363
|
|
364
|
+
it "should freeze serialization metadata when freezing model class" do
|
365
|
+
@c.plugin :serialization, :yaml, :abc, :def
|
366
|
+
@c.freeze
|
367
|
+
@c.serialization_map.frozen?.must_equal true
|
368
|
+
@c.deserialization_map.frozen?.must_equal true
|
369
|
+
@c.serialization_module.frozen?.must_equal true
|
370
|
+
end
|
364
371
|
end
|
@@ -19,6 +19,16 @@ describe Sequel::Model, "single table inheritance plugin" do
|
|
19
19
|
Object.send(:remove_const, :StiTest)
|
20
20
|
end
|
21
21
|
|
22
|
+
it "should freeze sti metadata when freezing model class" do
|
23
|
+
StiTest.freeze
|
24
|
+
StiTest.sti_dataset.frozen?.must_equal true
|
25
|
+
|
26
|
+
StiTestSub1.freeze
|
27
|
+
StiTestSub1.sti_key_array.frozen?.must_equal true
|
28
|
+
|
29
|
+
proc{class ::StiTestSub1Sub1 < StiTestSub1; end}.must_raise RuntimeError, TypeError
|
30
|
+
end
|
31
|
+
|
22
32
|
it "should have simple_table = nil" do
|
23
33
|
StiTest.simple_table.must_equal "sti_tests"
|
24
34
|
StiTestSub1.simple_table.must_be_nil
|
@@ -180,8 +190,15 @@ describe Sequel::Model, "single table inheritance plugin" do
|
|
180
190
|
end
|
181
191
|
after do
|
182
192
|
Object.send(:remove_const, :StiTest2)
|
183
|
-
Object.send(:remove_const, :StiTest3)
|
184
|
-
Object.send(:remove_const, :StiTest4)
|
193
|
+
Object.send(:remove_const, :StiTest3) if defined?(StiTest3)
|
194
|
+
Object.send(:remove_const, :StiTest4) if defined?(StiTest4)
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should freeze sti key and model map if given as hashes when freezing model class" do
|
198
|
+
StiTest2.plugin :single_table_inheritance, :kind, :model_map=>{0=>StiTest2, 1=>:StiTest3, 2=>'StiTest4'}, :key_map=>{StiTest2=>4, 'StiTest3'=>5, 'StiTest4'=>6}
|
199
|
+
StiTest2.freeze
|
200
|
+
StiTest2.sti_key_map.frozen?.must_equal true
|
201
|
+
StiTest2.sti_model_map.frozen?.must_equal true
|
185
202
|
end
|
186
203
|
|
187
204
|
it "should have working row_proc if using set_dataset in subclass to remove columns" do
|
@@ -50,6 +50,19 @@ describe Sequel::Model, "Subclasses plugin" do
|
|
50
50
|
sssc1.descendents.must_equal []
|
51
51
|
end
|
52
52
|
|
53
|
+
it "#freeze_descendents should finalize the associations for all descendents" do
|
54
|
+
sc1 = Class.new(@c)
|
55
|
+
sc1.set_dataset :bars
|
56
|
+
sc1.set_primary_key :foo
|
57
|
+
sc2 = Class.new(@c)
|
58
|
+
sc2.set_dataset :bazs
|
59
|
+
sc2.many_to_one :bar, :class=>sc1
|
60
|
+
@c.freeze_descendents
|
61
|
+
sc1.frozen?.must_equal true
|
62
|
+
sc2.frozen?.must_equal true
|
63
|
+
sc2.association_reflection(:bar)[:primary_key].must_equal :foo
|
64
|
+
end
|
65
|
+
|
53
66
|
it "plugin block should be called with each subclass created" do
|
54
67
|
c = Class.new(Sequel::Model)
|
55
68
|
a = []
|
@@ -80,7 +80,7 @@ END
|
|
80
80
|
end
|
81
81
|
|
82
82
|
it "should handle LiteralStrings" do
|
83
|
-
dot(@ds.filter('a')).must_equal ["1 -> 2 [label=\"where\"];", "2 [label=\"\\\"(a)\\\"
|
83
|
+
dot(@ds.filter('a')).must_equal ["1 -> 2 [label=\"where\"];", "2 [label=\"Sequel.lit(\\\"(a)\\\")\"];"]
|
84
84
|
end
|
85
85
|
|
86
86
|
it "should handle true, false, nil" do
|
@@ -208,4 +208,10 @@ describe "Touch plugin" do
|
|
208
208
|
DB.sqls.must_equal ["UPDATE artists SET modified_on = CURRENT_TIMESTAMP WHERE (id = 4)",
|
209
209
|
"UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.artist_id = 4)"]
|
210
210
|
end
|
211
|
+
|
212
|
+
it "should freeze touched associations when freezing model class" do
|
213
|
+
@Artist.plugin :touch, :associations=>:albums
|
214
|
+
@Artist.freeze
|
215
|
+
@Artist.touched_associations.frozen?.must_equal true
|
216
|
+
end
|
211
217
|
end
|
@@ -274,5 +274,11 @@ describe Sequel::Model, "tree plugin with composite keys" do
|
|
274
274
|
@c.dataset = @c.dataset.with_fetch(:id=>1, :id2=>6, :parent_id=>nil, :parent_id2=>2, :name=>'r')
|
275
275
|
@c.root.update(:name => 'fdsa')
|
276
276
|
end
|
277
|
+
|
278
|
+
it "freezes tree_order if it is an array" do
|
279
|
+
@c.tree_order = [:id]
|
280
|
+
@c.freeze
|
281
|
+
@c.tree_order.frozen?.must_equal true
|
282
|
+
end
|
277
283
|
end
|
278
284
|
end
|
@@ -77,4 +77,10 @@ describe Sequel::Model, "TypecastOnLoad plugin" do
|
|
77
77
|
@c.plugin :typecast_on_load, :b
|
78
78
|
@c.load(:id=>1, :b=>"1", :y=>"0").modified?.must_equal false
|
79
79
|
end
|
80
|
+
|
81
|
+
it "should freeze typecast_on_load columns when freezing model class" do
|
82
|
+
@c.plugin :typecast_on_load, :b
|
83
|
+
@c.freeze
|
84
|
+
@c.typecast_on_load_columns.frozen?.must_equal true
|
85
|
+
end
|
80
86
|
end
|
@@ -38,7 +38,6 @@ describe "Sequel::Plugins::UpdateRefresh" do
|
|
38
38
|
o.name.must_equal 'b'
|
39
39
|
end
|
40
40
|
|
41
|
-
|
42
41
|
it "should refresh the instance after updating when returning specific columns" do
|
43
42
|
@db.extend_datasets{def supports_returning?(x) true end; def update_sql(*); sql = super; update_returning_sql(sql); sql end}
|
44
43
|
@c.plugin :insert_returning_select
|
@@ -50,4 +49,11 @@ describe "Sequel::Plugins::UpdateRefresh" do
|
|
50
49
|
@db.sqls.must_equal ["UPDATE test SET name = 'a' WHERE (id = 1) RETURNING id, name"]
|
51
50
|
o.name.must_equal 'b'
|
52
51
|
end
|
52
|
+
|
53
|
+
it "should freeze update refresh columns when freezing model class" do
|
54
|
+
@db.extend_datasets{def supports_returning?(x) true end; def update_sql(*); sql = super; update_returning_sql(sql); sql end}
|
55
|
+
@c.plugin :update_refresh, :columns => [ :a ]
|
56
|
+
@c.freeze
|
57
|
+
@c.update_refresh_columns.frozen?.must_equal true
|
58
|
+
end
|
53
59
|
end
|
@@ -16,6 +16,19 @@ describe Sequel::Model do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
it "should freeze validation metadata when freezing model class" do
|
20
|
+
@c.validates_acceptance_of(:a)
|
21
|
+
@c.freeze
|
22
|
+
@c.validations.frozen?.must_equal true
|
23
|
+
@c.validations.values.all?(&:frozen?).must_equal true
|
24
|
+
@c.validation_reflections.frozen?.must_equal true
|
25
|
+
@c.validation_reflections.values.all? do |vs|
|
26
|
+
vs.frozen? && vs.all? do |v|
|
27
|
+
v.frozen? && v.last.frozen?
|
28
|
+
end
|
29
|
+
end.must_equal true
|
30
|
+
end
|
31
|
+
|
19
32
|
it "should respond to validations, has_validations?, and validation_reflections" do
|
20
33
|
@c.must_respond_to(:validations)
|
21
34
|
@c.must_respond_to(:has_validations?)
|
@@ -15,6 +15,19 @@ describe Sequel::Model::Associations::AssociationReflection, "#associated_class"
|
|
15
15
|
@c.association_reflection(:c).associated_class.must_equal ParParent
|
16
16
|
end
|
17
17
|
|
18
|
+
it "should have inspect include association class and representation of association definition " do
|
19
|
+
ParParent.many_to_one :c
|
20
|
+
ParParent.association_reflection(:c).inspect.must_equal "#<Sequel::Model::Associations::ManyToOneAssociationReflection ParParent.many_to_one :c>"
|
21
|
+
ParParent.many_to_one :c, :class=>ParParent
|
22
|
+
ParParent.association_reflection(:c).inspect.must_equal "#<Sequel::Model::Associations::ManyToOneAssociationReflection ParParent.many_to_one :c, :class=>ParParent>"
|
23
|
+
ParParent.many_to_one :c, :class=>ParParent, :key=>:c_id
|
24
|
+
["#<Sequel::Model::Associations::ManyToOneAssociationReflection ParParent.many_to_one :c, :key=>:c_id, :class=>ParParent>",
|
25
|
+
"#<Sequel::Model::Associations::ManyToOneAssociationReflection ParParent.many_to_one :c, :class=>ParParent, :key=>:c_id>"].must_include ParParent.association_reflection(:c).inspect
|
26
|
+
|
27
|
+
@c.one_to_many :foos do |ds| ds end
|
28
|
+
@c.association_reflection(:foos).inspect.must_equal "#<Sequel::Model::Associations::OneToManyAssociationReflection #{@c.to_s}.one_to_many :foos, :block=>#{@c.association_reflection(:foos)[:block].inspect}>"
|
29
|
+
end
|
30
|
+
|
18
31
|
it "should figure out the class if the :class value is not present" do
|
19
32
|
@c.many_to_one :c, :class=>'ParParent'
|
20
33
|
@c.association_reflection(:c).keys.wont_include(:class)
|
@@ -30,6 +43,17 @@ describe Sequel::Model::Associations::AssociationReflection, "#associated_class"
|
|
30
43
|
ParParent.many_to_one :par_parent, :class=>'ParParent', :class_namespace=>'ParParent'
|
31
44
|
ParParent.association_reflection(:par_parent).associated_class.must_equal ParParent::ParParent
|
32
45
|
end
|
46
|
+
|
47
|
+
it "should include association inspect output if an exception would be raised" do
|
48
|
+
r = @c.many_to_one(:c)
|
49
|
+
|
50
|
+
begin
|
51
|
+
r.associated_class
|
52
|
+
rescue NameError => e
|
53
|
+
end
|
54
|
+
|
55
|
+
e.message.must_include r.inspect
|
56
|
+
end
|
33
57
|
end
|
34
58
|
|
35
59
|
describe Sequel::Model::Associations::AssociationReflection, "#primary_key" do
|
@@ -563,3 +587,156 @@ describe Sequel::Model::Associations::AssociationReflection, "with default assoc
|
|
563
587
|
r[:bar].must_equal 2
|
564
588
|
end
|
565
589
|
end
|
590
|
+
|
591
|
+
describe "Sequel::Model.freeze" do
|
592
|
+
it "should freeze the model class and not allow any changes to associations" do
|
593
|
+
model = Class.new(Sequel::Model(:items))
|
594
|
+
model.many_to_one :foo, :class=>model, :key=>:id
|
595
|
+
model.default_association_options = {:read_only=>true}
|
596
|
+
model.freeze
|
597
|
+
|
598
|
+
model.association_reflections.frozen?.must_equal true
|
599
|
+
model.association_reflection(:foo).frozen?.must_equal true
|
600
|
+
model.autoreloading_associations.frozen?.must_equal true
|
601
|
+
model.autoreloading_associations[:id].frozen?.must_equal true
|
602
|
+
model.default_association_options.frozen?.must_equal true
|
603
|
+
end
|
604
|
+
|
605
|
+
it "should allow subclasses of frozen model classes to modify associations" do
|
606
|
+
model = Class.new(Sequel::Model(:items))
|
607
|
+
model.many_to_one :foo, :class=>model, :key=>:id
|
608
|
+
model.freeze
|
609
|
+
model = Class.new(model)
|
610
|
+
model.dataset = :items2
|
611
|
+
|
612
|
+
model.association_reflection(:foo).frozen?.must_equal true
|
613
|
+
model.autoreloading_associations.frozen?.must_equal false
|
614
|
+
model.autoreloading_associations[:id].frozen?.must_equal false
|
615
|
+
|
616
|
+
model.many_to_one :bar, :class=>model, :key=>:id
|
617
|
+
model.many_to_one :foo, :class=>model, :key=>:id
|
618
|
+
model.association_reflections.frozen?.must_equal false
|
619
|
+
model.association_reflection(:foo).frozen?.must_equal false
|
620
|
+
model.association_reflection(:bar).frozen?.must_equal false
|
621
|
+
|
622
|
+
model.default_association_options.frozen?.wont_equal true
|
623
|
+
model.default_association_options = {:read_only=>true}
|
624
|
+
model.default_association_options.frozen?.wont_equal true
|
625
|
+
end
|
626
|
+
end
|
627
|
+
|
628
|
+
describe "Sequel::Model.finalize_associations" do
|
629
|
+
before do
|
630
|
+
class ::MtmItem < Sequel::Model
|
631
|
+
set_primary_key :mtm_id
|
632
|
+
many_to_many :items
|
633
|
+
many_to_one :item
|
634
|
+
end
|
635
|
+
class ::OtoItem < Sequel::Model
|
636
|
+
set_primary_key :oto_id
|
637
|
+
end
|
638
|
+
class ::Item < Sequel::Model
|
639
|
+
many_to_one :item
|
640
|
+
one_to_many :items, :limit=>10
|
641
|
+
one_to_one :mtm_item
|
642
|
+
many_to_many :mtm_items
|
643
|
+
one_through_one :oto_item
|
644
|
+
end
|
645
|
+
[MtmItem, OtoItem, Item].each(&:finalize_associations)
|
646
|
+
end
|
647
|
+
after do
|
648
|
+
Object.send(:remove_const, :Item)
|
649
|
+
Object.send(:remove_const, :MtmItem)
|
650
|
+
Object.send(:remove_const, :OtoItem)
|
651
|
+
end
|
652
|
+
|
653
|
+
it "should finalize many_to_one associations" do
|
654
|
+
r = Item.association_reflection(:item)
|
655
|
+
r[:class].must_equal Item
|
656
|
+
r[:_dataset].sql.must_equal "SELECT * FROM items LIMIT 1"
|
657
|
+
r[:associated_eager_dataset].sql.must_equal "SELECT * FROM items"
|
658
|
+
r[:filter_by_associations_conditions_dataset].sql.must_equal "SELECT items.id FROM items WHERE (items.id IS NOT NULL)"
|
659
|
+
r[:placeholder_loader].wont_be_nil
|
660
|
+
r[:predicate_key].must_equal Sequel.qualify(:items, :id)
|
661
|
+
r[:primary_key].must_equal :id
|
662
|
+
r[:primary_keys].must_equal [:id]
|
663
|
+
r[:primary_key_method].must_equal :id
|
664
|
+
r[:primary_key_methods].must_equal [:id]
|
665
|
+
r[:qualified_primary_key].must_equal Sequel.qualify(:items, :id)
|
666
|
+
r.fetch(:reciprocal_type).must_equal :one_to_many
|
667
|
+
r.fetch(:reciprocal).must_equal :items
|
668
|
+
end
|
669
|
+
|
670
|
+
it "should finalize one_to_many associations" do
|
671
|
+
r = Item.association_reflection(:items)
|
672
|
+
r[:class].must_equal Item
|
673
|
+
r[:_dataset].sql.must_equal "SELECT * FROM items LIMIT 10"
|
674
|
+
r[:associated_eager_dataset].sql.must_equal "SELECT * FROM items"
|
675
|
+
r[:_eager_limit_strategy].must_equal :union
|
676
|
+
r[:filter_by_associations_conditions_dataset].sql.must_equal "SELECT items.item_id FROM items WHERE ((items.item_id IS NOT NULL) AND (items.id IN (SELECT t1.id FROM items AS t1 WHERE (t1.item_id = items.item_id) LIMIT 10)))"
|
677
|
+
r[:placeholder_loader].wont_be_nil
|
678
|
+
r[:predicate_key].must_equal Sequel.qualify(:items, :item_id)
|
679
|
+
r[:predicate_keys].must_equal [Sequel.qualify(:items, :item_id)]
|
680
|
+
r[:qualified_primary_key].must_equal Sequel.qualify(:items, :id)
|
681
|
+
r.fetch(:reciprocal).must_equal :item
|
682
|
+
end
|
683
|
+
|
684
|
+
it "should finalize one_to_one associations" do
|
685
|
+
r = Item.association_reflection(:mtm_item)
|
686
|
+
r[:class].must_equal MtmItem
|
687
|
+
r[:_dataset].sql.must_equal "SELECT * FROM mtm_items LIMIT 1"
|
688
|
+
r[:associated_eager_dataset].sql.must_equal "SELECT * FROM mtm_items"
|
689
|
+
r[:_eager_limit_strategy].must_be_nil
|
690
|
+
r[:filter_by_associations_conditions_dataset].sql.must_equal "SELECT mtm_items.item_id FROM mtm_items WHERE (mtm_items.item_id IS NOT NULL)"
|
691
|
+
r[:placeholder_loader].wont_be_nil
|
692
|
+
r[:predicate_key].must_equal Sequel.qualify(:mtm_items, :item_id)
|
693
|
+
r[:predicate_keys].must_equal [Sequel.qualify(:mtm_items, :item_id)]
|
694
|
+
r[:qualified_primary_key].must_equal Sequel.qualify(:items, :id)
|
695
|
+
r.fetch(:reciprocal).must_equal :item
|
696
|
+
end
|
697
|
+
|
698
|
+
it "should finalize many_to_many associations" do
|
699
|
+
r = Item.association_reflection(:mtm_items)
|
700
|
+
r[:class].must_equal MtmItem
|
701
|
+
r[:_dataset].sql.must_equal "SELECT mtm_items.* FROM mtm_items INNER JOIN items_mtm_items ON (items_mtm_items.mtm_item_id = mtm_items.mtm_id)"
|
702
|
+
r[:associated_eager_dataset].sql.must_equal "SELECT mtm_items.* FROM mtm_items INNER JOIN items_mtm_items ON (items_mtm_items.mtm_item_id = mtm_items.mtm_id)"
|
703
|
+
r[:_eager_limit_strategy].must_be_nil
|
704
|
+
r[:filter_by_associations_conditions_dataset].sql.must_equal "SELECT items_mtm_items.item_id FROM mtm_items INNER JOIN items_mtm_items ON (items_mtm_items.mtm_item_id = mtm_items.mtm_id) WHERE (items_mtm_items.item_id IS NOT NULL)"
|
705
|
+
r[:placeholder_loader].wont_be_nil
|
706
|
+
r[:predicate_key].must_equal Sequel.qualify(:items_mtm_items, :item_id)
|
707
|
+
r[:predicate_keys].must_equal [Sequel.qualify(:items_mtm_items, :item_id)]
|
708
|
+
r.fetch(:reciprocal).must_equal :items
|
709
|
+
r[:associated_key_array].must_equal [Sequel.qualify(:items_mtm_items, :item_id).as(:x_foreign_key_x)]
|
710
|
+
r[:qualified_right_key].must_equal Sequel.qualify(:items_mtm_items, :mtm_item_id)
|
711
|
+
r[:join_table_source].must_equal :items_mtm_items
|
712
|
+
r[:join_table_alias].must_equal :items_mtm_items
|
713
|
+
r[:qualified_right_primary_key].must_equal Sequel.qualify(:mtm_items, :mtm_id)
|
714
|
+
r[:right_primary_key].must_equal :mtm_id
|
715
|
+
r[:right_primary_keys].must_equal [:mtm_id]
|
716
|
+
r[:right_primary_key_method].must_equal :mtm_id
|
717
|
+
r[:right_primary_key_methods].must_equal [:mtm_id]
|
718
|
+
r[:select].must_equal Sequel::SQL::ColumnAll.new(:mtm_items)
|
719
|
+
end
|
720
|
+
|
721
|
+
it "should finalize one_through_one associations" do
|
722
|
+
r = Item.association_reflection(:oto_item)
|
723
|
+
r[:class].must_equal OtoItem
|
724
|
+
r[:_dataset].sql.must_equal "SELECT oto_items.* FROM oto_items INNER JOIN items_oto_items ON (items_oto_items.oto_item_id = oto_items.oto_id) LIMIT 1"
|
725
|
+
r[:associated_eager_dataset].sql.must_equal "SELECT oto_items.* FROM oto_items INNER JOIN items_oto_items ON (items_oto_items.oto_item_id = oto_items.oto_id)"
|
726
|
+
r[:_eager_limit_strategy].must_be_nil
|
727
|
+
r[:filter_by_associations_conditions_dataset].sql.must_equal "SELECT items_oto_items.item_id FROM oto_items INNER JOIN items_oto_items ON (items_oto_items.oto_item_id = oto_items.oto_id) WHERE (items_oto_items.item_id IS NOT NULL)"
|
728
|
+
r[:placeholder_loader].wont_be_nil
|
729
|
+
r[:predicate_key].must_equal Sequel.qualify(:items_oto_items, :item_id)
|
730
|
+
r[:predicate_keys].must_equal [Sequel.qualify(:items_oto_items, :item_id)]
|
731
|
+
r[:associated_key_array].must_equal [Sequel.qualify(:items_oto_items, :item_id).as(:x_foreign_key_x)]
|
732
|
+
r[:qualified_right_key].must_equal Sequel.qualify(:items_oto_items, :oto_item_id)
|
733
|
+
r[:join_table_source].must_equal :items_oto_items
|
734
|
+
r[:join_table_alias].must_equal :items_oto_items
|
735
|
+
r[:qualified_right_primary_key].must_equal Sequel.qualify(:oto_items, :oto_id)
|
736
|
+
r[:right_primary_key].must_equal :oto_id
|
737
|
+
r[:right_primary_keys].must_equal [:oto_id]
|
738
|
+
r[:right_primary_key_method].must_equal :oto_id
|
739
|
+
r[:right_primary_key_methods].must_equal [:oto_id]
|
740
|
+
r[:select].must_equal Sequel::SQL::ColumnAll.new(:oto_items)
|
741
|
+
end
|
742
|
+
end
|
@@ -4624,3 +4624,19 @@ describe "association autoreloading" do
|
|
4624
4624
|
DB.sqls.must_equal ['SELECT * FROM artists WHERE id = 1']
|
4625
4625
|
end
|
4626
4626
|
end
|
4627
|
+
|
4628
|
+
describe Sequel::Model, ".dataset_module" do
|
4629
|
+
before do
|
4630
|
+
@c = Class.new(Sequel::Model(:items))
|
4631
|
+
end
|
4632
|
+
|
4633
|
+
it "should have dataset_module support an eager method" do
|
4634
|
+
@c.many_to_one :foo, :class=>@c
|
4635
|
+
@c.many_to_one :bar, :class=>@c
|
4636
|
+
@c.many_to_one :baz, :class=>@c
|
4637
|
+
@c.many_to_one :quux, :class=>@c
|
4638
|
+
@c.dataset_module{eager(:foo, {:foo=>{:bar=>:baz}}, :quux)}
|
4639
|
+
@c.foo.opts[:eager].must_equal(:foo=>{:bar=>:baz}, :quux=>nil)
|
4640
|
+
@c.where(:bar).foo.opts[:eager].must_equal(:foo=>{:bar=>:baz}, :quux=>nil)
|
4641
|
+
end
|
4642
|
+
end
|