Skip to content
Browse files

Expand the association_pks plugin to support composite primary keys.

  • Loading branch information...
1 parent 6c28b95 commit 166b0350e29873a7ef210756365b12080913a589 @chanks chanks committed
Showing with 381 additions and 24 deletions.
  1. +12 −9 lib/sequel/plugins/association_pks.rb
  2. +140 −10 spec/extensions/association_pks_spec.rb
  3. +229 −5 spec/integration/plugin_test.rb
View
21 lib/sequel/plugins/association_pks.rb
@@ -21,9 +21,6 @@ module Plugins
# not call any callbacks. If you have any association callbacks,
# you probably should not use the setter methods.
#
- # This plugin only works with singular primary keys, it does not work
- # with composite primary keys.
- #
# Usage:
#
# # Make all model subclass *_to_many associations have association_pks
@@ -53,15 +50,21 @@ def def_association_pks_setter(opts, &block)
def def_many_to_many(opts)
super
def_association_pks_getter(opts) do
- _join_table_dataset(opts).filter(opts[:left_key]=>send(opts[:left_primary_key])).select_map(opts[:right_key])
+ left_pk = Array(opts[:left_primary_key]).map{|k| send(k)}
+ _join_table_dataset(opts).filter(opts[:left_key]=>[left_pk]).select_map(opts[:right_key])
end
def_association_pks_setter(opts) do |pks|
pks = convert_pk_array(opts, pks)
checked_transaction do
- ds = _join_table_dataset(opts).filter(opts[:left_key]=>send(opts[:left_primary_key]))
+ left_pk = Array(opts[:left_primary_key]).map{|k| send(k)}
+ ds = _join_table_dataset(opts).filter(opts[:left_key]=>[left_pk])
ds.exclude(opts[:right_key]=>pks).delete
pks -= ds.select_map(opts[:right_key])
- pks.each{|pk| ds.insert(opts[:left_key]=>send(opts[:left_primary_key]), opts[:right_key]=>pk)}
+ pks.each do |pk|
+ left = Array(opts[:left_key]).zip(left_pk)
+ right = Array(opts[:right_key]).zip(Array(pk))
+ ds.insert(Hash[left + right])
+ end
end
end
end
@@ -79,9 +82,9 @@ def def_one_to_many(opts)
checked_transaction do
ds = send(opts.dataset_method)
primary_key = opts.associated_class.primary_key
- key = opts[:key]
- ds.unfiltered.filter(primary_key=>pks).update(key=>pk)
- ds.exclude(primary_key=>pks).update(key=>nil)
+ key = Array(opts[:key])
+ ds.unfiltered.filter(primary_key=>pks).update(Hash[key.zip(Array(pk))])
+ ds.exclude(primary_key=>pks).update(Hash[key.zip])
end
end
end
View
150 spec/extensions/association_pks_spec.rb
@@ -6,22 +6,55 @@
case sql
when "SELECT id FROM albums WHERE (albums.artist_id = 1)"
[{:id=>1}, {:id=>2}, {:id=>3}]
- when /SELECT tag_id FROM albums_tags WHERE \(album_id = (\d)\)/
+ when /SELECT tag_id FROM albums_tags WHERE \(album_id IN \(\((\d)\)\)\)/
a = []
a << {:tag_id=>1} if $1 == '1'
a << {:tag_id=>2} if $1 != '3'
a << {:tag_id=>3} if $1 == '2'
a
+ when "SELECT first, last FROM vocalists WHERE (vocalists.album_id = 1)"
+ [{:first=>"F1", :last=>"L1"}, {:first=>"F2", :last=>"L2"}]
+ when /SELECT first, last FROM albums_vocalists WHERE \(album_id IN \(\((\d)\)\)\)/
+ a = []
+ a << {:first=>"F1", :last=>"L1"} if $1 == '1'
+ a << {:first=>"F2", :last=>"L2"} if $1 != '3'
+ a << {:first=>"F3", :last=>"L3"} if $1 == '2'
+ a
+ when "SELECT id FROM instruments WHERE ((instruments.first = 'F1') AND (instruments.last = 'L1'))"
+ [{:id=>1}, {:id=>2}]
+ when /SELECT instrument_id FROM vocalists_instruments WHERE \(\(first, last\) IN \(\((.*)\)\)\)/
+ a = []
+ a << {:instrument_id=>1} if $1 == "'F1', 'L1'"
+ a << {:instrument_id=>2} if $1 != "'F3', 'L3'"
+ a << {:instrument_id=>3} if $1 == "'F2', 'L2'"
+ a
+ when "SELECT year, week FROM hits WHERE ((hits.first = 'F1') AND (hits.last = 'L1'))"
+ [{:year=>1997, :week=>1}, {:year=>1997, :week=>2}]
+ when /SELECT year, week FROM vocalists_hits WHERE \(\(first, last\) IN \(\((.*)\)\)\)/
+ a = []
+ a << {:year=>1997, :week=>1} if $1 == "'F1', 'L1'"
+ a << {:year=>1997, :week=>2} if $1 != "'F3', 'L3'"
+ a << {:year=>1997, :week=>3} if $1 == "'F2', 'L2'"
+ a
end
end)
@Artist = Class.new(Sequel::Model(@db[:artists]))
@Artist.columns :id
- @Album= Class.new(Sequel::Model(@db[:albums]))
+ @Album = Class.new(Sequel::Model(@db[:albums]))
@Album.columns :id, :artist_id
@Tag = Class.new(Sequel::Model(@db[:tags]))
@Tag.columns :id
+ @Vocalist = Class.new(Sequel::Model(@db[:vocalists]))
+ @Vocalist.columns :first, :last, :album_id
+ @Vocalist.set_primary_key [:first, :last]
+ @Instrument = Class.new(Sequel::Model(@db[:instruments]))
+ @Instrument.columns :id, :first, :last
+ @Hit = Class.new(Sequel::Model(@db[:hits]))
+ @Hit.columns :year, :week, :first, :last
+ @Hit.set_primary_key [:year, :week]
@Artist.plugin :association_pks
@Album.plugin :association_pks
+ @Vocalist.plugin :association_pks
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
@Album.many_to_many :tags, :class=>@Tag, :join_table=>:albums_tags, :left_key=>:album_id
@db.sqls
@@ -54,12 +87,109 @@
specify "should set associated pks correctly for a many_to_many association" do
@Album.load(:id=>2).tag_pks = [1, 3]
sqls = @db.sqls
- sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN (1, 3)))"
- sqls[1].should == 'SELECT tag_id FROM albums_tags WHERE (album_id = 2)'
+ sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id IN ((2))) AND (tag_id NOT IN (1, 3)))"
+ sqls[1].should == 'SELECT tag_id FROM albums_tags WHERE (album_id IN ((2)))'
sqls[2].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, 1|1, 2)\)/
sqls.length.should == 3
end
+ specify "should return correct right-side associated cpks for one_to_many associations" do
+ @Album.one_to_many :vocalists, :class=>@Vocalist, :key=>:album_id
+ @Album.load(:id=>1).vocalist_pks.should == [["F1", "L1"], ["F2", "L2"]]
+ @Album.load(:id=>2).vocalist_pks.should == []
+ end
+
+ specify "should return correct right-side associated cpks for many_to_many associations" do
+ @Album.many_to_many :vocalists, :class=>@Vocalist, :join_table=>:albums_vocalists, :left_key=>:album_id, :right_key=>[:first, :last]
+ @Album.load(:id=>1).vocalist_pks.should == [["F1", "L1"], ["F2", "L2"]]
+ @Album.load(:id=>2).vocalist_pks.should == [["F2", "L2"], ["F3", "L3"]]
+ @Album.load(:id=>3).vocalist_pks.should == []
+ end
+
+ specify "should set associated right-side cpks correctly for a one_to_many association" do
+ @Album.one_to_many :vocalists, :class=>@Vocalist, :key=>:album_id
+ @Album.load(:id=>1).vocalist_pks = [["F1", "L1"], ["F2", "L2"]]
+ @db.sqls.should == ["UPDATE vocalists SET album_id = 1 WHERE ((first, last) IN (('F1', 'L1'), ('F2', 'L2')))",
+ "UPDATE vocalists SET album_id = NULL WHERE ((vocalists.album_id = 1) AND ((first, last) NOT IN (('F1', 'L1'), ('F2', 'L2'))))"]
+ end
+
+ specify "should set associated right-side cpks correctly for a many_to_many association" do
+ @Album.many_to_many :vocalists, :class=>@Vocalist, :join_table=>:albums_vocalists, :left_key=>:album_id, :right_key=>[:first, :last]
+ @Album.load(:id=>2).vocalist_pks = [["F1", "L1"], ["F2", "L2"]]
+ sqls = @db.sqls
+ sqls[0].should == "DELETE FROM albums_vocalists WHERE ((album_id IN ((2))) AND ((first, last) NOT IN (('F1', 'L1'), ('F2', 'L2'))))"
+ sqls[1].should == 'SELECT first, last FROM albums_vocalists WHERE (album_id IN ((2)))'
+ match = sqls[2].match(/INSERT INTO albums_vocalists \((.*)\) VALUES \((.*)\)/)
+ Hash[match[1].split(', ').zip(match[2].split(', '))].should == {"first"=>"'F1'", "last"=>"'L1'", "album_id"=>"2"}
+ sqls.length.should == 3
+ end
+
+ specify "should return correct associated pks for left-side cpks for one_to_many associations" do
+ @Vocalist.one_to_many :instruments, :class=>@Instrument, :key=>[:first, :last]
+ @Vocalist.load(:first=>'F1', :last=>'L1').instrument_pks.should == [1, 2]
+ @Vocalist.load(:first=>'F2', :last=>'L2').instrument_pks.should == []
+ end
+
+ specify "should return correct associated pks for left-side cpks for many_to_many associations" do
+ @Vocalist.many_to_many :instruments, :class=>@Instrument, :join_table=>:vocalists_instruments, :left_key=>[:first, :last]
+ @Vocalist.load(:first=>'F1', :last=>'L1').instrument_pks.should == [1, 2]
+ @Vocalist.load(:first=>'F2', :last=>'L2').instrument_pks.should == [2, 3]
+ @Vocalist.load(:first=>'F3', :last=>'L3').instrument_pks.should == []
+ end
+
+ specify "should set associated pks correctly for left-side cpks for a one_to_many association" do
+ @Vocalist.one_to_many :instruments, :class=>@Instrument, :key=>[:first, :last]
+ @Vocalist.load(:first=>'F1', :last=>'L1').instrument_pks = [1, 2]
+ sqls = @db.sqls
+ sqls[0].should =~ /UPDATE instruments SET (first = 'F1', last = 'L1'|last = 'L1', first = 'F1') WHERE \(id IN \(1, 2\)\)/
+ sqls[1].should =~ /UPDATE instruments SET (first = NULL, last = NULL|last = NULL, first = NULL) WHERE \(\(instruments.first = 'F1'\) AND \(instruments.last = 'L1'\) AND \(id NOT IN \(1, 2\)\)\)/
+ sqls.length.should == 2
+ end
+
+ specify "should set associated pks correctly for left-side cpks for a many_to_many association" do
+ @Vocalist.many_to_many :instruments, :class=>@Instrument, :join_table=>:vocalists_instruments, :left_key=>[:first, :last]
+ @Vocalist.load(:first=>'F2', :last=>'L2').instrument_pks = [1, 2]
+ sqls = @db.sqls
+ sqls[0].should == "DELETE FROM vocalists_instruments WHERE (((first, last) IN (('F2', 'L2'))) AND (instrument_id NOT IN (1, 2)))"
+ sqls[1].should == "SELECT instrument_id FROM vocalists_instruments WHERE ((first, last) IN (('F2', 'L2')))"
+ match = sqls[2].match(/INSERT INTO vocalists_instruments \((.*)\) VALUES \((.*)\)/)
+ Hash[match[1].split(', ').zip(match[2].split(', '))].should == {"first"=>"'F2'", "last"=>"'L2'", "instrument_id"=>"1"}
+ sqls.length.should == 3
+ end
+
+ specify "should return correct right-side associated cpks for left-side cpks for one_to_many associations" do
+ @Vocalist.one_to_many :hits, :class=>@Hit, :key=>[:first, :last]
+ @Vocalist.load(:first=>'F1', :last=>'L1').hit_pks.should == [[1997, 1], [1997, 2]]
+ @Vocalist.load(:first=>'F2', :last=>'L2').hit_pks.should == []
+ end
+
+ specify "should return correct right-side associated cpks for left-side cpks for many_to_many associations" do
+ @Vocalist.many_to_many :hits, :class=>@Hit, :join_table=>:vocalists_hits, :left_key=>[:first, :last], :right_key=>[:year, :week]
+ @Vocalist.load(:first=>'F1', :last=>'L1').hit_pks.should == [[1997, 1], [1997, 2]]
+ @Vocalist.load(:first=>'F2', :last=>'L2').hit_pks.should == [[1997, 2], [1997, 3]]
+ @Vocalist.load(:first=>'F3', :last=>'L3').hit_pks.should == []
+ end
+
+ specify "should set associated right-side cpks correctly for left-side cpks for a one_to_many association" do
+ @Vocalist.one_to_many :hits, :class=>@Hit, :key=>[:first, :last], :order=>:week
+ @Vocalist.load(:first=>'F1', :last=>'L1').hit_pks = [[1997, 1], [1997, 2]]
+ sqls = @db.sqls
+ sqls[0].should =~ /UPDATE hits SET (first = 'F1', last = 'L1'|last = 'L1', first = 'F1') WHERE \(\(year, week\) IN \(\(1997, 1\), \(1997, 2\)\)\)/
+ sqls[1].should =~ /UPDATE hits SET (first = NULL, last = NULL|last = NULL, first = NULL) WHERE \(\(hits.first = 'F1'\) AND \(hits.last = 'L1'\) AND \(\(year, week\) NOT IN \(\(1997, 1\), \(1997, 2\)\)\)\)/
+ sqls.length.should == 2
+ end
+
+ specify "should set associated right-side cpks correctly for left-side cpks for a many_to_many association" do
+ @Vocalist.many_to_many :hits, :class=>@Hit, :join_table=>:vocalists_hits, :left_key=>[:first, :last], :right_key=>[:year, :week]
+ @Vocalist.load(:first=>'F2', :last=>'L2').hit_pks = [[1997, 1], [1997, 2]]
+ sqls = @db.sqls
+ sqls[0].should == "DELETE FROM vocalists_hits WHERE (((first, last) IN (('F2', 'L2'))) AND ((year, week) NOT IN ((1997, 1), (1997, 2))))"
+ sqls[1].should == "SELECT year, week FROM vocalists_hits WHERE ((first, last) IN (('F2', 'L2')))"
+ match = sqls[2].match(/INSERT INTO vocalists_hits \((.*)\) VALUES \((.*)\)/)
+ Hash[match[1].split(', ').zip(match[2].split(', '))].should == {"first"=>"'F2'", "last"=>"'L2'", "year"=>"1997", "week"=>"1"}
+ sqls.length.should == 3
+ end
+
specify "should use transactions if the object is configured to use transactions" do
artist = @Artist.load(:id=>1)
artist.use_transactions = true
@@ -74,8 +204,8 @@
album.tag_pks = [1, 3]
sqls = @db.sqls
sqls[0].should == "BEGIN"
- sqls[1].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN (1, 3)))"
- sqls[2].should == 'SELECT tag_id FROM albums_tags WHERE (album_id = 2)'
+ sqls[1].should == "DELETE FROM albums_tags WHERE ((album_id IN ((2))) AND (tag_id NOT IN (1, 3)))"
+ sqls[2].should == 'SELECT tag_id FROM albums_tags WHERE (album_id IN ((2)))'
sqls[3].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, 1|1, 2)\)/
sqls[4].should == "COMMIT"
sqls.length.should == 5
@@ -99,8 +229,8 @@
@Tag.db_schema[:id][:type] = :integer
@Album.load(:id=>2).tag_pks = %w'1 3'
sqls = @db.sqls
- sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN (1, 3)))"
- sqls[1].should == 'SELECT tag_id FROM albums_tags WHERE (album_id = 2)'
+ sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id IN ((2))) AND (tag_id NOT IN (1, 3)))"
+ sqls[1].should == 'SELECT tag_id FROM albums_tags WHERE (album_id IN ((2)))'
sqls[2].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, 1|1, 2)\)/
sqls.length.should == 3
end
@@ -109,8 +239,8 @@
@Tag.db_schema[:id][:type] = :string
@Album.load(:id=>2).tag_pks = %w'1 3'
sqls = @db.sqls
- sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN ('1', '3')))"
- sqls[1].should == 'SELECT tag_id FROM albums_tags WHERE (album_id = 2)'
+ sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id IN ((2))) AND (tag_id NOT IN ('1', '3')))"
+ sqls[1].should == 'SELECT tag_id FROM albums_tags WHERE (album_id IN ((2)))'
sqls[2].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, '1'|'1', 2)\)/
sqls[3].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, '3'|'3', 2)\)/
sqls.length.should == 4
View
234 spec/integration/plugin_test.rb
@@ -1069,7 +1069,7 @@ class ::Item < Sequel::Model(@db)
describe "AssociationPks plugin" do
before(:all) do
@db = INTEGRATION_DB
- @db.drop_table?(:albums_tags, :tags, :albums, :artists)
+ @db.drop_table?(:albums_tags, :albums_vocalists, :vocalists_instruments, :vocalists_hits, :hits, :instruments, :vocalists, :tags, :albums, :artists)
@db.create_table(:artists) do
primary_key :id
String :name
@@ -1087,6 +1087,46 @@ class ::Item < Sequel::Model(@db)
foreign_key :album_id, :albums
foreign_key :tag_id, :tags
end
+ @db.create_table(:vocalists) do
+ String :first
+ String :last
+ primary_key [:first, :last]
+ foreign_key :album_id, :albums
+ end
+ @db.create_table(:albums_vocalists) do
+ foreign_key :album_id, :albums
+ String :first
+ String :last
+ foreign_key [:first, :last], :vocalists
+ end
+ @db.create_table(:instruments) do
+ primary_key :id
+ String :first
+ String :last
+ foreign_key [:first, :last], :vocalists
+ end
+ @db.create_table(:vocalists_instruments) do
+ String :first
+ String :last
+ foreign_key [:first, :last], :vocalists
+ foreign_key :instrument_id, :instruments
+ end
+ @db.create_table(:hits) do
+ Integer :year
+ Integer :week
+ primary_key [:year, :week]
+ String :first
+ String :last
+ foreign_key [:first, :last], :vocalists
+ end
+ @db.create_table(:vocalists_hits) do
+ String :first
+ String :last
+ foreign_key [:first, :last], :vocalists
+ Integer :year
+ Integer :week
+ foreign_key [:year, :week], :hits
+ end
class ::Artist < Sequel::Model
plugin :association_pks
one_to_many :albums, :order=>:id
@@ -1097,9 +1137,17 @@ class ::Album < Sequel::Model
end
class ::Tag < Sequel::Model
end
+ class ::Vocalist < Sequel::Model
+ plugin :association_pks
+ end
+ class ::Instrument < Sequel::Model
+ plugin :association_pks
+ end
+ class ::Hit < Sequel::Model
+ end
end
before do
- [:albums_tags, :tags, :albums, :artists].each{|t| @db[t].delete}
+ [:albums_tags, :albums_vocalists, :vocalists_instruments, :vocalists_hits, :hits, :instruments, :vocalists, :tags, :albums, :artists].each{|t| @db[t].delete}
@ar1 =@db[:artists].insert(:name=>'YJM')
@ar2 =@db[:artists].insert(:name=>'AS')
@al1 =@db[:albums].insert(:name=>'RF', :artist_id=>@ar1)
@@ -1111,10 +1159,34 @@ class ::Tag < Sequel::Model
{@al1=>[@t1, @t2, @t3], @al2=>[@t2]}.each do |aid, tids|
tids.each{|tid| @db[:albums_tags].insert([aid, tid])}
end
+ @v1 = ['F1', 'L1']
+ @v2 = ['F2', 'L2']
+ @v3 = ['F3', 'L3']
+ @db[:vocalists].insert(@v1 + [@al1])
+ @db[:vocalists].insert(@v2 + [@al1])
+ @db[:vocalists].insert(@v3 + [@al1])
+ @i1 = @db[:instruments].insert([:first, :last], @v1)
+ @i2 = @db[:instruments].insert([:first, :last], @v1)
+ @i3 = @db[:instruments].insert([:first, :last], @v1)
+ @h1 = [1997, 1]
+ @h2 = [1997, 2]
+ @h3 = [1997, 3]
+ @db[:hits].insert(@h1 + @v1)
+ @db[:hits].insert(@h2 + @v1)
+ @db[:hits].insert(@h3 + @v1)
+ {@al1=>[@v1, @v2, @v3], @al2=>[@v2]}.each do |aid, vids|
+ vids.each{|vid| @db[:albums_vocalists].insert([aid] + vid)}
+ end
+ {@v1=>[@i1, @i2, @i3], @v2=>[@i2]}.each do |vid, iids|
+ iids.each{|iid| @db[:vocalists_instruments].insert(vid + [iid])}
+ end
+ {@v1=>[@h1, @h2, @h3], @v2=>[@h2]}.each do |vid, hids|
+ hids.each{|hid| @db[:vocalists_hits].insert(vid + hid)}
+ end
end
after(:all) do
- @db.drop_table? :albums_tags, :tags, :albums, :artists
- [:Artist, :Album, :Tag].each{|s| Object.send(:remove_const, s)}
+ @db.drop_table? :albums_tags, :albums_vocalists, :vocalists_instruments, :vocalists_hits, :hits, :instruments, :vocalists, :tags, :albums, :artists
+ [:Artist, :Album, :Tag, :Vocalist, :Instrument, :Hit].each{|s| Object.send(:remove_const, s)}
end
specify "should return correct associated pks for one_to_many associations" do
@@ -1125,6 +1197,36 @@ class ::Tag < Sequel::Model
Album.order(:id).all.map{|a| a.tag_pks.sort}.should == [[@t1, @t2, @t3], [@t2], []]
end
+ specify "should return correct associated right-side cpks for one_to_many associations" do
+ Album.one_to_many :vocalists, :order=>:first
+ Album.order(:id).all.map{|a| a.vocalist_pks.sort}.should == [[@v1, @v2, @v3], [], []]
+ end
+
+ specify "should return correct associated right-side cpks for many_to_many associations" do
+ Album.many_to_many :vocalists, :join_table=>:albums_vocalists, :right_key=>[:first, :last], :order=>:first
+ Album.order(:id).all.map{|a| a.vocalist_pks.sort}.should == [[@v1, @v2, @v3], [@v2], []]
+ end
+
+ specify "should return correct associated pks for left-side cpks for one_to_many associations" do
+ Vocalist.one_to_many :instruments, :key=>[:first, :last], :order=>:id
+ Vocalist.order(:first, :last).all.map{|a| a.instrument_pks.sort}.should == [[@i1, @i2, @i3], [], []]
+ end
+
+ specify "should return correct associated pks for left-side cpks for many_to_many associations" do
+ Vocalist.many_to_many :instruments, :join_table=>:vocalists_instruments, :left_key=>[:first, :last], :order=>:id
+ Vocalist.order(:first, :last).all.map{|a| a.instrument_pks.sort}.should == [[@i1, @i2, @i3], [@i2], []]
+ end
+
+ specify "should return correct associated right-side cpks for left-side cpks for one_to_many associations" do
+ Vocalist.one_to_many :hits, :key=>[:first, :last], :order=>:week
+ Vocalist.order(:first, :last).all.map{|a| a.hit_pks.sort}.should == [[@h1, @h2, @h3], [], []]
+ end
+
+ specify "should return correct associated right-side cpks for left-side cpks for many_to_many associations" do
+ Vocalist.many_to_many :hits, :join_table=>:vocalists_hits, :left_key=>[:first, :last], :right_key=>[:year, :week], :order=>:week
+ Vocalist.order(:first, :last).all.map{|a| a.hit_pks.sort}.should == [[@h1, @h2, @h3], [@h2], []]
+ end
+
specify "should set associated pks correctly for a one_to_many association" do
Artist.use_transactions = true
Album.order(:id).select_map(:artist_id).should == [@ar1, @ar1, @ar1]
@@ -1162,8 +1264,130 @@ class ::Tag < Sequel::Model
Album[@al3].tag_pks = []
@db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).should == []
end
-end
+ specify "should set associated right-side cpks correctly for a one_to_many association" do
+ Album.use_transactions = true
+ Album.one_to_many :vocalists, :order=>:first
+ Album.order(:id).all.map{|a| a.vocalist_pks.sort}.should == [[@v1, @v2, @v3], [], []]
+
+ Album[@al2].vocalist_pks = [@v1, @v3]
+ Album[@al1].vocalist_pks.should == [@v2]
+ Vocalist.order(:first, :last).select_map(:album_id).should == [@al2, @al1, @al2]
+
+ Album[@al1].vocalist_pks = [@v1]
+ Album[@al2].vocalist_pks.should == [@v3]
+ Vocalist.order(:first, :last).select_map(:album_id).should == [@al1, nil, @al2]
+
+ Album[@al1].vocalist_pks = [@v1, @v2]
+ Album[@al2].vocalist_pks.should == [@v3]
+ Vocalist.order(:first, :last).select_map(:album_id).should == [@al1, @al1, @al2]
+ end
+
+ specify "should set associated right-side cpks correctly for a many_to_many association" do
+ Album.use_transactions = true
+ Album.many_to_many :vocalists, :join_table=>:albums_vocalists, :right_key=>[:first, :last], :order=>:first
+
+ @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).should == [@v1, @v2, @v3]
+ Album[@al1].vocalist_pks = [@v1, @v3]
+ @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).should == [@v1, @v3]
+ Album[@al1].vocalist_pks = []
+ @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).should == []
+
+ @db[:albums_vocalists].filter(:album_id=>@al2).select_order_map([:first, :last]).should == [@v2]
+ Album[@al2].vocalist_pks = [@v1, @v2]
+ @db[:albums_vocalists].filter(:album_id=>@al2).select_order_map([:first, :last]).should == [@v1, @v2]
+ Album[@al2].vocalist_pks = []
+ @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).should == []
+
+ @db[:albums_vocalists].filter(:album_id=>@al3).select_order_map([:first, :last]).should == []
+ Album[@al3].vocalist_pks = [@v1, @v3]
+ @db[:albums_vocalists].filter(:album_id=>@al3).select_order_map([:first, :last]).should == [@v1, @v3]
+ Album[@al3].vocalist_pks = []
+ @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).should == []
+ end
+
+ specify "should set associated pks correctly with left-side cpks for a one_to_many association" do
+ Vocalist.use_transactions = true
+ Vocalist.one_to_many :instruments, :key=>[:first, :last], :order=>:id
+ Vocalist.order(:first, :last).all.map{|a| a.instrument_pks.sort}.should == [[@i1, @i2, @i3], [], []]
+
+ Vocalist[@v2].instrument_pks = [@i1, @i3]
+ Vocalist[@v1].instrument_pks.should == [@i2]
+ Instrument.order(:id).select_map([:first, :last]).should == [@v2, @v1, @v2]
+
+ Vocalist[@v1].instrument_pks = [@i1]
+ Vocalist[@v2].instrument_pks.should == [@i3]
+ Instrument.order(:id).select_map([:first, :last]).should == [@v1, [nil, nil], @v2]
+
+ Vocalist[@v1].instrument_pks = [@i1, @i2]
+ Vocalist[@v2].instrument_pks.should == [@i3]
+ Instrument.order(:id).select_map([:first, :last]).should == [@v1, @v1, @v2]
+ end
+
+ specify "should set associated pks correctly with left-side cpks for a many_to_many association" do
+ Vocalist.use_transactions = true
+ Vocalist.many_to_many :instruments, :join_table=>:vocalists_instruments, :left_key=>[:first, :last], :order=>:id
+
+ @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).should == [@i1, @i2, @i3]
+ Vocalist[@v1].instrument_pks = [@i1, @i3]
+ @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).should == [@i1, @i3]
+ Vocalist[@v1].instrument_pks = []
+ @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).should == []
+
+ @db[:vocalists_instruments].filter([:first, :last]=>[@v2]).select_order_map(:instrument_id).should == [@i2]
+ Vocalist[@v2].instrument_pks = [@i1, @i2]
+ @db[:vocalists_instruments].filter([:first, :last]=>[@v2]).select_order_map(:instrument_id).should == [@i1, @i2]
+ Vocalist[@v2].instrument_pks = []
+ @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).should == []
+
+ @db[:vocalists_instruments].filter([:first, :last]=>[@v3]).select_order_map(:instrument_id).should == []
+ Vocalist[@v3].instrument_pks = [@i1, @i3]
+ @db[:vocalists_instruments].filter([:first, :last]=>[@v3]).select_order_map(:instrument_id).should == [@i1, @i3]
+ Vocalist[@v3].instrument_pks = []
+ @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).should == []
+ end
+
+ specify "should set associated right-side cpks correctly with left-side cpks for a one_to_many association" do
+ Vocalist.use_transactions = true
+ Vocalist.one_to_many :hits, :key=>[:first, :last], :order=>:week
+ Vocalist.order(:first, :last).all.map{|a| a.hit_pks.sort}.should == [[@h1, @h2, @h3], [], []]
+
+ Vocalist[@v2].hit_pks = [@h1, @h3]
+ Vocalist[@v1].hit_pks.should == [@h2]
+ Hit.order(:year, :week).select_map([:first, :last]).should == [@v2, @v1, @v2]
+
+ Vocalist[@v1].hit_pks = [@h1]
+ Vocalist[@v2].hit_pks.should == [@h3]
+ Hit.order(:year, :week).select_map([:first, :last]).should == [@v1, [nil, nil], @v2]
+
+ Vocalist[@v1].hit_pks = [@h1, @h2]
+ Vocalist[@v2].hit_pks.should == [@h3]
+ Hit.order(:year, :week).select_map([:first, :last]).should == [@v1, @v1, @v2]
+ end
+
+ specify "should set associated right-side cpks correctly with left-side cpks for a many_to_many association" do
+ Vocalist.use_transactions = true
+ Vocalist.many_to_many :hits, :join_table=>:vocalists_hits, :left_key=>[:first, :last], :right_key=>[:year, :week], :order=>:week
+
+ @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).should == [@h1, @h2, @h3]
+ Vocalist[@v1].hit_pks = [@h1, @h3]
+ @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).should == [@h1, @h3]
+ Vocalist[@v1].hit_pks = []
+ @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).should == []
+
+ @db[:vocalists_hits].filter([:first, :last]=>[@v2]).select_order_map([:year, :week]).should == [@h2]
+ Vocalist[@v2].hit_pks = [@h1, @h2]
+ @db[:vocalists_hits].filter([:first, :last]=>[@v2]).select_order_map([:year, :week]).should == [@h1, @h2]
+ Vocalist[@v2].hit_pks = []
+ @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).should == []
+
+ @db[:vocalists_hits].filter([:first, :last]=>[@v3]).select_order_map([:year, :week]).should == []
+ Vocalist[@v3].hit_pks = [@h1, @h3]
+ @db[:vocalists_hits].filter([:first, :last]=>[@v3]).select_order_map([:year, :week]).should == [@h1, @h3]
+ Vocalist[@v3].hit_pks = []
+ @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).should == []
+ end
+end
describe "List plugin without a scope" do
before(:all) do

0 comments on commit 166b035

Please sign in to comment.
Something went wrong with that request. Please try again.