玩inverse_of的時候,會疑惑這家伙到底有什么用?
就查到https://www.viget.com/articles/exploring-the-inverse-of-option-on-rails-model-associations這篇文章,這里面講:
如果建立prison和criminal這樣一對多關系的兩個model:
class Criminal < ActiveRecord::Base
belongs_to :prison, inverse_of: :criminals
end
class Prison < ActiveRecord::Base
has_many :criminals, inverse_of: :prison
end
然后:
prison = Prison.create(name: 'Bad House')
criminal = prison.criminals.create(name: 'Krazy 8')
當去掉inverse_of的時候,會再次查詢數據庫
# Without :inverse_of
criminal.prison == prison
# Prison Load (0.1ms) SELECT "prisons".* FROM "prisons" WHERE "prisons"."id" = 2 LIMIT 1
# => true
加上inverse_of時,就直接從內存中找
# With :inverse_of
criminal.prison == prison
# => true
但是,當我去掉inverse_of時,并沒有出現:
# Prison Load (0.1ms) SELECT "prisons".* FROM "prisons" WHERE "prisons"."id" = 2 LIMIT 1
當時就想可能是rails console不顯示這樣的查詢過程吧(原諒我的無知),后來就用pry看rails server的過程,也沒出現。當時也想過可能是rails版本的問題,rails -v看下,但是沒有繼續深究下去,如果當時朝著這方向就好了。
繼續google,發現這篇文章https://ruby-china.org/topics/24998才明白,原來真的是rails版本問題
原來是這樣的:
發表時間
這篇文章是2014年發表的,可能當時作者的環境還是rails 4.1以前的,rails4.1以后的版本是默認帶有inverse_of的,github上是這樣說的:
rails4.1 automatic inverse_of breaks existing relation on polymorphic association #15337
鏈接:https://github.com/rails/rails/issues/15337
也就是說,rails4.1版本會
所以,作者直接去掉inverse_of,prison.criminals時是會再次查詢數據庫的,也就是會顯示下面這樣:
# Prison Load (0.1ms) SELECT "prisons".* FROM "prisons" WHERE "prisons"."id" = 2 LIMIT 1
最后總結:inverse_of的一個作用是為了避免二次查詢,提高查詢效率