在我的Ruby on Rails项目中,Course模型是这样的:
class Course < ActiveRecord::Base
has_many :teams, inverse_of: :course, dependent: :destroy
并且团队模型是这样的:
class Team < ActiveRecord::Base
belongs_to :course
当我执行以下if语句
时,Inverse_of应该可以帮助我阻止对数据库的查询 if(tm.course == current_course) #tm is a team and current_course is a course
return tm
我检查控制台输出,看到if语句仍然调用它:
CACHE (0.0ms) SELECT `courses`.* FROM `courses` WHERE `courses`.`id` = 2 LIMIT 1 [["id", 2]]
有什么想法和建议吗?
答案 0 :(得分:0)
这很好。该查询未再次访问数据库。 CACHE (0.0ms)
来自Rails缓存,通常在内存中,除非您在应用配置中更改它。
修改
实际上,如果您想频繁访问关联对象,您可能还想添加include
。
has_many :teams, -> { includes :course }, inverse_of: :course, dependent: :destroy
这应该强制Rails在单个数据库访问中加载两个记录并将它们保存在缓存中。
另一个编辑
如果您想避免第二次交易,可以执行tm = Team.includes(:course).find params[:id]
之类的操作。这样,当if发生时,查询将不需要新的事务。
相反,当你调用find
时,你会看到两个SELECT一个接着一个接一个。我认为这是最好的。
inverse_of
重要的一点是,tm.course.team
的目的是不会触发Team
上的第二次选择,而是注意.team
引用tm
并且只做两个选择而不是三个。
另一个编辑
请在rails console
中尝试此操作。
Team.first.course.team
的 inverse_of
,然后更改它,重新加载控制台并再次运行它。你会明白我的意思。
最终(HOPEFULLY)编辑
我会尝试详细解释this ......
prison = Prison.create(name: 'Bad House')
这将导致对表Prison
的数据库进行SELECT。
criminal = prison.criminals.create(name: 'Krazy 8')
这将导致表Criminal
中的INSERT,然后是SELECT以检索它并将其分配给变量criminal
。
如果我有inverse_of: :course
,则意味着访问criminal.prison
不会导致另一个查询,因为criminal
将“记住”他通过prison
它将返回变量prison
,而不是再次查询db。
在您的情况下......假设您正在创建tm
,就像这样:
tm = Team.find param[:id]
无论您做什么,这都将导致访问数据库。
然后tm.course == current_course
将需要第二个SELECT,这次是针对Course
查找课程,因为到目前为止您还没有使用Course
。
然后,我们假设您这样做:
course = tm.course
然后copy_of_team = course.team
。您可以在此处看到inverse_of
的效果。
如果你想摆脱第二次选择,你必须使用tm = Team.includes(:course).find param[:id]
。这当然仍然需要一个选择来检索课程信息,但它将在同一个数据库事务中发生,因此它比没有它更好。