Tuesday, September 27, 2011

Rails: The power of 'inverse_of'

There is a 'less known' feature of ActiveRecord associations that is very handy: the ability of marking an association as the mirror of another :inverse_of

The best is to rescue an example from the oficial documentation

class Dungeon < ActiveRecord::Base
  has_many :traps, :inverse_of => :dungeon
  has_one :evil_wizard, :inverse_of => :dungeon
end

class Trap < ActiveRecord::Base
  belongs_to :dungeon, :inverse_of => :traps
end

class EvilWizard < ActiveRecord::Base
  belongs_to :dungeon, :inverse_of => :evil_wizard
end
 
dungeon = Dungeon.first
wizard = dungeon.evil_wizard 



In a normal configuration, doing wizard.dungeon will hit the database and instantiate a new 'dungeon' (2 instances of the same object). 
 
With :inverse_of , Active record is aware of the relation and will use the same instance in memory. This has 2 benefits:
- we save a DB call
- as both 'dungeons' are the same instance, modifications on dungeon are seen from wizard (an the otehr way around)
 
Without :inverse_of , a modification on dungeon, is not seen by wizard.dungeon what can lead to subtle errors.
 
+1 for :inverse_of 
 
 

15 comments:

  1. What's the point of specifying inverse_of for "has_many <-> belongs_to" association? Aren't they ignored anyway?

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. In Rails 4.1 and later they're automatically inferred as long as you don't use class_name or foreign_key. But ... if you do have a more complex belongs_to or has_many then you will need to set inverse_of.

    Here's a video that has a kinda complex relationship with two foreign keys between a couple models, so it does require explicitly setting the inverse_of. An RSpec test is written to first show that object_ids are different, and then after adding inverse_of they end up to be the same:

    https://www.youtube.com/watch?v=5sfufoY59Ek&t=42m54s

    ReplyDelete
  4. In Rails 4.1 and later they're automatically inferred as long as you don't use class_name or foreign_key. But ... if you do have a more complex belongs_to or has_many then you will need to set inverse_of.

    Here's a video that has a kinda complex relationship with two foreign keys between a couple models, so it does require explicitly setting the inverse_of. An RSpec test is written to first show that object_ids are different, and then after adding inverse_of they end up to be the same:

    https://www.youtube.com/watch?v=5sfufoY59Ek&t=42m54s

    ReplyDelete
  5. In Rails 4.1 they're automatically inferred as long as you don't use class_name or foreign_key. But ... if you do have a more complex belongs_to or has_many then you will need to set inverse_of.

    Here's a video that has a kinda complex relationship with two foreign keys between a couple models, so it does require explicitly setting the inverse_of. An RSpec test is written to first show that object_ids are different, and then after adding inverse_of they end up to be the same:

    https://www.youtube.com/watch?v=5sfufoY59Ek&feature=youtu.be&t=42m54s

    ReplyDelete
  6. We provide marketing services to startups and small businesses looking for a partner for their digital media.digital technology institute

    ReplyDelete
  7. Thank you for sharing very useful information and Local SEO Services Delhi or best Training in India 2021 Amazon SEO Services Delhi

    ReplyDelete
  8. We offer the best content writing, SEO, Graphic and website development & web designing services at reasonable prices. Get the best deals on Services of all digital marketing online by Webgross

    ReplyDelete
  9. This blog post is very informative which tells us about The power of 'inverse_of'. Thanks for sharing with us I follow your daily blog post.
    Social media marketing services Delhi

    ReplyDelete