Ruby On Rails : Bidirectional Associations

It has been found that in any activerecord relationship you can point to either of the object at either of the ends. But, there exists a situation where it behaves odd from the mainstream.

It’s normal for associations to work in two directions, requiring declaration on two different models:

class Customer < ActiveRecord::Base
  has_many :orders
end
class Order < ActiveRecord::Base
  belongs_to :customer
end

By default, Active Record doesn’t know about the connection between these associations. This can lead to two copies of an object getting out of sync:

c = Customer.first
o = c.orders.first
c.first_name == o.customer.first_name # => true
c.first_name = 'Manny'
c.first_name == o.customer.first_name # => false

This happens because c and o.customer are two different in-memory representations of the same data, and neither one is automatically refreshed from changes to the other. Active Record provides the :inverse_of option so that you can inform it of these relations:

class Customer < ActiveRecord::Base
  has_many :orders, inverse_of: :customer
end
class Order < ActiveRecord::Base
  belongs_to :customer, inverse_of: :orders
end

With these changes, Active Record will only load one copy of the customer object, preventing inconsistencies and making your application more efficient:

c = Customer.first
o = c.orders.first
c.first_name == o.customer.first_name # => true
c.first_name = 'Manny'
c.first_name == o.customer.first_name # => true

There are a few limitations to inverse_of support:

  • They do not work with :through associations.
  • They do not work with :polymorphic associations.
  • They do not work with :as associations.
  • For belongs_to associations, has_many inverse associations are ignored.

Every association will attempt to automatically find the inverse association and set the :inverse_ofoption heuristically (based on the association name). Most associations with standard names will be supported. However, associations that contain the following options will not have their inverses set automatically:

  • :conditions
  • :through
  • :polymorphic
  • :foreign_key

Sources:

http://guides.rubyonrails.org/association_basics.html#bi-directional-associations

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s