新手问题 Rails 简单页面浏览量计数器的问题

vincent178 · 2013年01月30日 · 最后由 Vincent178 回复于 2013年02月01日 · 4974 次阅读

各位大大,求助!

效果

每次点击"Detail"链接,viewed_count 计数器加 1,然后在 index 页面上显示出来

我的方法

Controller

def show
  @patient = Patient.find(params[:id])
  @patient.view!
end

Model

def view!
  if self.viewed_count.nil?
    self.viewed_count = 1
  else
    self.viewed_count += 1
  end
end

实际结果

计数器就停留在 1 上面就不动了。。。

大家帮帮忙,看看我哪里错了!

@Vincent178 没见到楼主调用 save 啊, 还是没有贴出来

#1 楼 @shawnyu 在 model 里面吗?之前却是没有调用, = =,我刚试了一下,会产生这样的错误

undefined method `save' for 1:Fixnum

我想应该是 viewed_count 的值为 1 了,没有 save 的方法~

#1 楼 @shawnyu 搞定啦,万分感谢。现在 view! 方法是这样的

def view!
  if self.viewed_count.nil?
    self.viewed_count = 1
    self.save
  else
    self.viewed_count += 1
    self.save
  end
end

提个小建议,楼主的代码风格应该 ruby 一点。估计看到帖子的人心里知道但是没说....

self.class.update_counters self.id, views_count: 1

#4 楼 @WilliamZhu 嗯,谢谢你的建议。你看这段代码可以怎样改进呢?

#5 楼 @as181920 cool, 大哥你太神了。终于看懂了,马上去用一下!

def view!
  self.viewed_count ||= 0
  self.viewed_count += 1
  self.save
end

#8 楼 @fresh_fish 比我原来的好看很多, ||=用到这里好棒,谢谢

数据库创建的时候建议给个默认值 0,然后可以用

def show
  @patient = Patient.find(params[:id])
  @patient.increment!(:view_count)
end

#10 楼 @quakewang 正解. 除去代码写法外,计数类的一定要考虑到对数据库性能影响。 有两种方案:

  1. 使用外部 (如 Redis) 进行计数,积累到一定次数后一次 update
  2. 使用对象缓存 对缓存的 patient 进行计数更新。当缓存进行的同步的时候会自动将计数更新进数据库。

#10 楼 @quakewang Great, 已经用上了你的方案!thx~

#11 楼 @WilliamZhu 感觉有点理解不能,主要是对 “性能"这个词完全没有感觉,我觉得我还要揣摩好久,不过谢谢

#11 楼 @WilliamZhu Good!如果因为这个用上 Redis 有点未免太重,简单的在内存里 cache 下,定时 increase 到数据库中就好了,不过这样有部分数据丢失的风险,比如服务重启。

Patient.update_counters @patient.id, :viewed_count => 1

http://apidock.com/rails/ActiveRecord/CounterCache/update_counters

#15 楼 @Rei Great, helps a lot! thx!

#15 楼 @Rei 这种方式也是不会缓存的。点击一次,update 一次数据库。 #14 楼 @Magic 不中。应该很少应用没有用到外置缓存吧。内存 Cache 无法做到负载均衡。一个简单浏览计数,丢掉就丢掉,你 1000000 次访问丢掉几十次访问,应该没什么问题吧。服务重启的话,连访问暂时都没搁置了,还要什么点击次数

匿名 #18 2013年02月01日

没有考虑同一 IP 多次访问限制的问题?

#18 楼 @lewisgrady 嗯,这个没有考虑进去 如果加入同 IP 算一次访问,是不是用 impressionist?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号