玩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的一个作用是为了避免二次查询,提高查询效率