First stop was to find out where the "<<" operator was being overloaded. Yes, I know that in Ruby it's not an operator, it's a message, and it's not overloaded. But I'm an old fart, and those are the terms I was weaned on, so deal with it. But I digress.
I found the magic in this file:
And the code looks like this:
class AssociationCollection < AssociationProxy
result = true
flatten_deeper(records).each do |record|
result &&= insert_record(record) unless @owner.new_record?
@target << record
result && self
Pretty straight forward. It looks like it's defering to a method named "insert_record" to handle the databaseness, so that was my next stop, and I found it in this file:
And here's the code:
class HasManyAssociation < AssociationCollection
Now some of the pieces are starting to fall into place. What it's doing here is only going to (and only does) work for a one-to-many relationship. What is does is takes the record passed in to the collection, sets its foreign key value, then saves the record.
What I need it to do is recognize that in some cases it's dealing with a many-to-many relationship and rather than saving the record that is passed into the collection it needs to create the record for the cross-reference.
Now the code above should have all of the information it needs to do just that. After all, it built the collection by querying the right tables, so it knows all of the tables names and their important columns, so it should be able to write that relationship back into the database. I need to dig a little more to figure out how I can leverage that.
I'm a bit surprised it hasn't already been done, which leads me to fear that it's rather ugly or nigh-impossible to accomplish, but I'm holding out hope. I'm hoping that somebody in the know stumbles across these rants and offers a helping hand in either making it work or explaining why it wasn't built to do so.