This project is archived and is in readonly mode.

#3760 ✓hold
Murray Steele

Make AR guess the inverse of an association if not specified

Reported by Murray Steele | January 20th, 2010 @ 11:28 PM | in 3.1

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.

Comments and changes to this ticket

  • Murray Steele

    Murray Steele January 20th, 2010 @ 11:30 PM

    • 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.

  • Nate Wiger

    Nate Wiger January 23rd, 2010 @ 07:53 PM

    +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.

  • Murray Steele

    Murray Steele January 25th, 2010 @ 04:23 PM

    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.

  • Eloy Duran

    Eloy Duran January 26th, 2010 @ 05:57 PM

    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.

  • Jeremy Kemper

    Jeremy Kemper January 26th, 2010 @ 06:31 PM

    • 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.

  • Eloy Duran

    Eloy Duran July 8th, 2010 @ 08:37 AM

    • Assigned user changed from “Eloy Duran” to “José Valim”
    • Importance changed from “” to “High”
  • José Valim

    José Valim July 19th, 2010 @ 02:51 PM

    • 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.

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Attachments

Pages