Rails / inverse_ofでメモリ効率化

Shunsuke Sawada

ここに記載がある inverse_of。
あんまり意識した事なかったけど使った方がいいんだね。

http://railsguides.jp/active_record_validations.html#presence
  
こういう関係だとします。

ruby
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Place < ActiveRecord::Base

  has_many :shops
  accepts_nested_attributes_for :shops

end


class Shop < ActiveRecord::Base

  belongs_to :place

  validates :name,  presence: true
  validates :owner, presence: true

end

  
こうしてみる。

ruby
1
2
3
4
5
6
7
# irb(main):001:0> 
place = Place.create(name: "Favorite Place")
shop = place.shops.create(name: "Nice Shop", owner: "Sawada")

shop.place == place
#Place Load (1.1ms)  SELECT "places".* FROM "places" WHERE "places"."id" = $1 LIMIT 1  [["id", 6]]
=> true

なのに対し、
has_many :shops, inverse_of: :place としてみると…
  

ruby
1
2
3
# irb(main):003:0>
shop.place == place
=> true

  
あら、データベースを叩いてない。すてき。

A model's associations, as far as memory is concerned, are one-way bindings. The :inverse_of option basically gives us two-way memory bindings when one of the associations is a :belongs_to.
http://viget.com/extend/exploring-the-inverse-of-option-on-rails-model-associations

2方向のアソシエーションをしてくれるからメモリの効率がいいと。
というか普通のアソシエーションが1方向だけだとは知らなかった。

と、思ったら、
自動でやってくれるらしい。

Every association will attempt to automatically find the inverse association and set the :inverse_of option heuristically (based on the association name). Most associations with standard names will be supported.

  
ただし、これらのオプションがついていないアソシエーションに関してのみなので注意。

:conditions
:through
:polymorphic
:foreign_key

でも上の例は Rails 4.0.13 での実行例。
指定しないと有効になってないのはなぜ…。

参考

http://viget.com/extend/exploring-the-inverse-of-option-on-rails-model-associations
http://gsusmonzon.blogspot.com.br/2011/09/rails-power-of-inverseof.html
http://guides.rubyonrails.org/association_basics.html

Shunsuke Sawada

おすすめの記事

RailsでFacebookログインを実装する
20
Rails / validates_associatedはなんのためにあるのか?
7
Rails / Deviceでないユーザー登録・ログインを実装する
81