论坛首页 编程语言技术论坛

Rails宝典之第一式: 实例变量做查询缓存?

浏览 5189 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-07-24  
前段时间对Rails的跟进有点懈怠,因为公司让我做Spring的内部培训,便抽空回归Java,看了下字符集,字节码,Annotation,
JavaConfig,JavaScript,Perl,花生壳等等乱七八糟的东西,差点把心收不回来准备去搞C#.net了。

每天一剂Rails良药要开工了,顺便把《The Ruby Way》eMule下来了,再写个“每天一条Ruby小道”怎么样?

前段时间订阅了很多外国网站的rss,发现Railscasts还是比较有趣的一个Rails技术教学网站,里面已经发布了
60多个教学视频,我想把这些教学拿到每天一剂Rails良药里来是不错的选择。
另外为了让本系列文章更有趣,我觉得把文章名字改为Rails宝典之第N式会很有意思。

今天就以这个开始吧:使用实例变量做查询缓存?

我们经常需要在application.rb里写一个current_user方法来便于得到当前登录的用户:
class ApplicationController < ActionController::Base

  def current_user
    User.find(session[:user_id])
  end

end

问题来了:当我们每次调用current_user来得到当前登录的用户时,我们都会查询一次数据库,这样大大浪费了资源。

所以,我们可以这样做:
class ApplicationController < ActionController::Base

  def current_user
    @current_user ||= User.find(session[:user_id])
  end

end

这样当前用户被实例变量“缓存”起来,大大减少了数据库查询。

看起来不错,但是实际上有问题:
实例变量的作用域是一次请求,即一次请求结束后@current_user这个实例变量就没了,下次请求时会照样调用User.find(session[:user_id])
即每次请求都会查询数据库。

所以这个视频中作者Ryan Bates在script/console中反复调用@current_user ||= User.find(session[:user_id])然后log中显示只查询数据库一次,
这是完全没有意义的!还好后来作者在后面的网页评论中作出了自我批评,但是想不通后面紧跟着一位“chineseGuy”在这里溜须拍马个不亦乐乎,
估计他根本没看懂这部视频,幸庆的是这位国人没有在留言时把自己的名字写成“chineseGay”。

而最重要的是,Rails目前已经内建支持查询缓存,见ActiveRecord源码包里的query_cache.rb。
这样,即使一次请求里调用current_user方法多次,查询缓存仍然会让你只接触数据库一次。

另外,我推荐这种@current_user获取方式:http://hideto.iteye.com/blog/100820
其中logged_in?、require_login、editable?等辅助方法也很有用

非常不幸,第一次介绍Railscasts,结果介绍了一部完全没有价值的教学视频。希望后面的视频会让人满意。
   发表时间:2007-07-25  
为什么不放到session 里呢?
0 请登录后投票
   发表时间:2007-07-25  
session里只存user_id,每次取user相关信息时都查一下数据库,这样可以保证取得的user对象数据以及user相关的字段信息(如post_count)都是新的,而直接把user对象存在session里的话,每次更新user相关的数据时就麻烦了,自己去更新session吧。

query_cache则很好用,查询时有缓存而不用连接数据库,如果数据更新,则query_cache会在数据更新后帮你更新缓存。
0 请登录后投票
   发表时间:2007-07-25  
的确,按照《agile rails》里面说的,rails针对每次请求都会创建一个控制器对象实例,这样的话,每次都要重新查询生成实例变量的。
至于为什么建议不要在session中存放对象而只是存放数据库id,书里面也有讲的,可以参他在实现购物车时所遇到的问题,正如hideto所述。

非常感谢hideto大大,希望这个系列以及新的系列能持续发表下去,以帮助我们这些rails新手学习,嘿嘿。
0 请登录后投票
   发表时间:2007-07-26  
既然“使用实例变量做查询缓存”是错误的,那总该讲讲
query_cache 吧... :-)
0 请登录后投票
   发表时间:2007-07-26  
query_cache就一百行代码,确实没什么好讲的,相信大家都能看懂
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics