On Mon, Nov 15, 2021 at 11:50 AM Benjamin Hutton <benhut...@gmail.com> 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))" #<Content @values={:id=>2}> #<Audio @values={:id=>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)" #<Content @values={:id=>2}> #<Content @values={:id=>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.