Re: many_to_many associations with cloning and classes
On Mon, Nov 15, 2021 at 1:01 PM Benjamin Hutton wrote: > thanks! > > FWIW, all my class names are actually passed around as strings > Yep, that's pretty common in most apps. I guess it is very uncommon to clone associations and use a different :class in a cloned association, otherwise someone would have hit this before. In any case, the problem has been fixed: https://github.com/jeremyevans/sequel/commit/64480baf60976bf2ba89985f592ef0a205413e99 Thanks, Jeremy -- You received this message because you are subscribed to the Google Groups "sequel-talk" group. To unsubscribe from this group and stop receiving emails from it, send an email to sequel-talk+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/sequel-talk/CADGZSSeFW-zr0-O_N9JRt9zm6p-bjzohf6G8N7T_F9m7f3CuNQ%40mail.gmail.com.
Re: many_to_many associations with cloning and classes
thanks! FWIW, all my class names are actually passed around as strings On Monday, November 15, 2021 at 3:37:18 PM UTC-5 Jeremy Evans wrote: > On Mon, Nov 15, 2021 at 11:50 AM Benjamin Hutton > wrote: > >> Hey Jeremy, >> >> I am seeing some strange behavior with many_to_many associations, >> association cloning, and classes. >> >> I am building a set of sequel models to interact with a legacy database >> that we are slowly migrating away from, and trying to untangle some >> polymorphism in the old database. >> >> I started with a bunch of associations like the following: >> >> many_to_many :audios, class: 'Legacy::Models::SequelAudio', join_table: >> :content_syndications, left_key: :contentable_id, right_key: :content_id >> do |ds| >>ds.where(:contents[:type] => 'Contents::Audio') >> end >> >> I then realized that I can do the following, in order to get rid of the >> block on the association: >> >> class Legacy::Models::SequelAudio < Legacy::Models::SequelContent >> set_dataset LEGACY_DB[:contents].where(type: 'Contents::Audio') >> end >> >> Which leads to: >> >> many_to_many :audios, class: 'Legacy::Models::SequelAudio', join_table: >> :content_syndications, left_key: :contentable_id, right_key: :content_id >> >> At this point, I realize I am relying on something cool going on with the >> class argument. >> >> I then try to further DRY up my code by doing this: >> >> many_to_many :audios, clone: :contents, class: >> 'Legacy::Models::SequelAudio' >> >> Unfortunately, it seems like the class that I am specifying is no longer >> getting applied. The association returns records with the class that is >> on the cloned contents association, not the audios association. And it >> isn't using the correct dataset anymore. >> >> Is there something else that I need to be doing? Am I misunderstanding >> cloning? >> > > I had trouble reproducing the example at first, using the following code: > > A = Class.new(Sequel::Model) > Content = Class.new(Sequel::Model(:contents)) > Audio = Class.new(Sequel::Model(DB[:contents].where(:type=>'audio') )) > A.many_to_many :contents, :class=>Content, :join_table=>:x > A.many_to_many :audios, :clone=>:contents, :class=>Audio > DB.fetch = {:id=>2} > p A.association_reflection(:contents).associated_class > p A.association_reflection(:audios).associated_class > p A.load(:id=>1).contents_dataset.sql > p A.load(:id=>1).audios_dataset.sql > p A.load(:id=>1).contents.first > p A.load(:id=>1).audios.first > > The output from that is: > > Content > Audio > "SELECT contents.* FROM contents INNER JOIN x ON (x.content_id = > contents.id) WHERE (x.a_id = 1)" > "SELECT contents.* FROM contents INNER JOIN x ON (x.audio_id = contents.id) > WHERE ((type = 'audio') AND (x.a_id = 1))" > #2}> > #2}> > > However, I was able to reproduce this when using a symbol to the :class > option: > > A.many_to_many :contents, :class=>:Content, :join_table=>:x > A.many_to_many :audios, :clone=>:contents, :class=>:Audio > > With that change, the output is: > > Content > Content > "SELECT contents.* FROM contents INNER JOIN x ON (x.content_id = > contents.id) WHERE (x.a_id = 1)" > "SELECT contents.* FROM contents INNER JOIN x ON (x.audio_id = contents.id) > WHERE (x.a_id = 1)" > #2}> > #2}> > > So this is definitely a bug, and it's related to the late binding of > classes by using a string or symbol, probably because the :class option is > renamed to :class_name in that case, but the cloning code doesn't handle > that. I'll work on a fix for it shortly. > > Thanks, > Jeremy > -- You received this message because you are subscribed to the Google Groups "sequel-talk" group. To unsubscribe from this group and stop receiving emails from it, send an email to sequel-talk+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/sequel-talk/ce3834da-8adf-4438-b624-686c9f15d13en%40googlegroups.com.
Re: many_to_many associations with cloning and classes
On Mon, Nov 15, 2021 at 11:50 AM Benjamin Hutton wrote: > Hey Jeremy, > > I am seeing some strange behavior with many_to_many associations, > association cloning, and classes. > > I am building a set of sequel models to interact with a legacy database > that we are slowly migrating away from, and trying to untangle some > polymorphism in the old database. > > I started with a bunch of associations like the following: > > many_to_many :audios, class: 'Legacy::Models::SequelAudio', join_table: > :content_syndications, left_key: :contentable_id, right_key: :content_id > do |ds| >ds.where(:contents[:type] => 'Contents::Audio') > end > > I then realized that I can do the following, in order to get rid of the > block on the association: > > class Legacy::Models::SequelAudio < Legacy::Models::SequelContent > set_dataset LEGACY_DB[:contents].where(type: 'Contents::Audio') > end > > Which leads to: > > many_to_many :audios, class: 'Legacy::Models::SequelAudio', join_table: > :content_syndications, left_key: :contentable_id, right_key: :content_id > > At this point, I realize I am relying on something cool going on with the > class argument. > > I then try to further DRY up my code by doing this: > > many_to_many :audios, clone: :contents, class: > 'Legacy::Models::SequelAudio' > > Unfortunately, it seems like the class that I am specifying is no longer > getting applied. The association returns records with the class that is > on the cloned contents association, not the audios association. And it > isn't using the correct dataset anymore. > > Is there something else that I need to be doing? Am I misunderstanding > cloning? > I had trouble reproducing the example at first, using the following code: A = Class.new(Sequel::Model) Content = Class.new(Sequel::Model(:contents)) Audio = Class.new(Sequel::Model(DB[:contents].where(:type=>'audio') )) A.many_to_many :contents, :class=>Content, :join_table=>:x A.many_to_many :audios, :clone=>:contents, :class=>Audio DB.fetch = {:id=>2} p A.association_reflection(:contents).associated_class p A.association_reflection(:audios).associated_class p A.load(:id=>1).contents_dataset.sql p A.load(:id=>1).audios_dataset.sql p A.load(:id=>1).contents.first p A.load(:id=>1).audios.first The output from that is: Content Audio "SELECT contents.* FROM contents INNER JOIN x ON (x.content_id = contents.id) WHERE (x.a_id = 1)" "SELECT contents.* FROM contents INNER JOIN x ON (x.audio_id = contents.id) WHERE ((type = 'audio') AND (x.a_id = 1))" #2}> #2}> However, I was able to reproduce this when using a symbol to the :class option: A.many_to_many :contents, :class=>:Content, :join_table=>:x A.many_to_many :audios, :clone=>:contents, :class=>:Audio With that change, the output is: Content Content "SELECT contents.* FROM contents INNER JOIN x ON (x.content_id = contents.id) WHERE (x.a_id = 1)" "SELECT contents.* FROM contents INNER JOIN x ON (x.audio_id = contents.id) WHERE (x.a_id = 1)" #2}> #2}> So this is definitely a bug, and it's related to the late binding of classes by using a string or symbol, probably because the :class option is renamed to :class_name in that case, but the cloning code doesn't handle that. I'll work on a fix for it shortly. Thanks, Jeremy -- You received this message because you are subscribed to the Google Groups "sequel-talk" group. To unsubscribe from this group and stop receiving emails from it, send an email to sequel-talk+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/sequel-talk/CADGZSSdC2q-qaSBa2B8Z6uZDcvwNnh3NX%2B0YghNksD0VLXBjiA%40mail.gmail.com.
many_to_many associations with cloning and classes
Hey Jeremy, I am seeing some strange behavior with many_to_many associations, association cloning, and classes. I am building a set of sequel models to interact with a legacy database that we are slowly migrating away from, and trying to untangle some polymorphism in the old database. I started with a bunch of associations like the following: many_to_many :audios, class: 'Legacy::Models::SequelAudio', join_table: :content_syndications, left_key: :contentable_id, right_key: :content_id do |ds| ds.where(:contents[:type] => 'Contents::Audio') end I then realized that I can do the following, in order to get rid of the block on the association: class Legacy::Models::SequelAudio < Legacy::Models::SequelContent set_dataset LEGACY_DB[:contents].where(type: 'Contents::Audio') end Which leads to: many_to_many :audios, class: 'Legacy::Models::SequelAudio', join_table: :content_syndications, left_key: :contentable_id, right_key: :content_id At this point, I realize I am relying on something cool going on with the class argument. I then try to further DRY up my code by doing this: many_to_many :audios, clone: :contents, class: 'Legacy::Models::SequelAudio' Unfortunately, it seems like the class that I am specifying is no longer getting applied. The association returns records with the class that is on the cloned contents association, not the audios association. And it isn't using the correct dataset anymore. Is there something else that I need to be doing? Am I misunderstanding cloning? -Ben -- You received this message because you are subscribed to the Google Groups "sequel-talk" group. To unsubscribe from this group and stop receiving emails from it, send an email to sequel-talk+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/sequel-talk/0d070dc1-abe1-4849-b979-25afef58a539n%40googlegroups.com.