Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Make AR guess the inverse of an association if not specified

#3760

Change ActiveRecord so that if the model doesn't specify an explicit :inverse_of option AR will try to guess and give the model the benefits of :inverse_of. In some cases AR won't be able to guess, or will guess wrong, so you can still specify explcitly using :inverse_of. You can also turn off the feature on a case by case basis if you specify :inverse_of => nil.

You might want to do this if you have validations or autosaves on your associations that might cause an infinite loop.

Reported by Murray Steele · January 20th, 2010 @ 11:28 PM

State: hold
Milestone: 3.1
Assigned to: José Valim José Valim
Importance: High

Activity

  1. Murray Steele
    Murray Steele
    • Tag changed from inverse_of activerecord patch to activerecord, inverse_of, patch

    The patch is complete, but it might want some work or thought about the API it exposes. Or more tests - I'm not sure about the testing strategy.

    January 20th, 2010 @ 11:30 PM

  2. Nate Wiger
    Nate Wiger

    +1 for sure. This would be great - DataMapper and Sequel already support correct inverse associations, so it's really something that AR should support as well.

    January 23rd, 2010 @ 07:53 PM

  3. Murray Steele
    Murray Steele

    After discussion with Eloy in IRC it seems it's useful to put a note about some of the gotchas here.

    With this patch, AR will try to guess the association on a loaded model that is the inverse of the association it was loaded through, but this It has the exact same limitations as the explicit :inverse_of feature. Namely that it doesn't work for :through associations, and it won't work for belongs_to associations that have a has_many association as the inverse.

    The reason for the has_many limitation is partly implementation, in that has_many associations don't have the set_XXX_target that other associations do, and that's what the current :inverse_of implementation uses to set inverses. The other reason for the limitation is that it's not hugely clear what exactly we should do. Given:

      class Car < ActiveRecord::Base
        has_many :wheels
      end
      
      class Wheel < ActiveRecord::Base
        belongs_to :car
      end
    

    When we do:

      car = Car.first
      wheels = car.wheels
    

    It's obvious what should be set as an inverse, each instance of Wheel should have the Car we loaded first set as the target of their car association.

    If we do:

      wheel = Wheel.first
      car = wheel.car
      wheels = car.wheels
    

    It's not particularly obvious what should be in this wheels array. Should we have all the wheels associated to the car loaded from the DB, apart from the one we started with? Should we just have the wheel we started with? Clearly the first option is correct, it's just hard to see the benefit of using the pre-loaded wheel here. We can't avoid a DB query to find out which other wheels we need and then inserting the wheel we already have into the set of objects returned from that query is extra work.

    It seems more pragmatic to ignore the belongs_to -> has_many case for now until we have a clear solution or full identity map.

    January 25th, 2010 @ 04:23 PM

  4. Eloy Duran
    Eloy Duran

    As discussed with Murray on IRC, I'm gonna take a look later this week if we can also solve the problem with autosave as outlined.

    Also inviting Jeremy to the ticket.

    January 26th, 2010 @ 05:57 PM

  5. Jeremy Kemper
    Jeremy Kemper
    • State changed from new to open
    It's not particularly obvious what should be in this wheels array. Should we have all the wheels associated to the car loaded from the DB, apart from the one we started with? Should we just have the wheel we started with?

    Should load all the car's wheels from the DB.

    January 26th, 2010 @ 06:31 PM

  6. Eloy Duran
    Eloy Duran
    • Assigned user changed from Eloy Duran to José Valim
    • Importance changed from to High

    July 8th, 2010 @ 08:37 AM

  7. José Valim
    José Valim
    • Milestone set to 3.1
    • State changed from open to hold

    I'm marking this as hold because this should probably be achieved by the RSoC student working on identity map.

    July 19th, 2010 @ 02:51 PM