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 <benh...@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/ce3834da-8adf-4438-b624-686c9f15d13en%40googlegroups.com.