Rails 关于缓存对象更新问题

ecloud · 2017年06月28日 · 最后由 mlzhuyi 回复于 2017年06月30日 · 1389 次阅读

先上代码

def self.cache_find(id)
    key = "work:" + id.to_s
    work = $redis.hgetall(key)
    # binding.pry
    if work.blank?
        work = Work.find(id)
        $redis.mapped_hmset(key, work.attributes)
        $redis.expire(key, 1.hour.to_i)
    else
        attrs = work
        work = Work.new
        attrs.each do |key, value|
            work.send("#{key.to_s}=", value)
        end
    end
    work
end

我的疑问是:如果我写如下的代码

work = Work.cache_find 1
work.name = 'test_work'
work.save

此时是不能更新数据的,因为 Rails 调用的不是 update 而是 save,在数据库中 id = 1 的数据已经存在,导致不能更新数据。请问有什么方法解决这个办法吗?

@huacnlee 大佬请指教,是因为

work.new_record?  # -> true

导致调用 save 吗?

用 second_level_cache

huacnlee 回复

大佬速度好快,去看了下 second_level_cache,果然好用。

当你对 id 为 1 的 work 有缓存的时候,会新建一个 id 为 1 的 work 对象,然后 save.这是一个 CREATE 操作不是 UPDATE, 所以 uniq index 冲突了。

mlzhuyi 回复

是的,生成的 sql 是 CREATE,而不是 UPDATE。我没有研究源码,不知道是怎么产生的 sql。如果是从数据库中查出来的对象,调用 save 时生成的 sql 是 UPDATE。能够有办法解决这个问题吗?

ecloud 回复
#work = Work.new
#attrs.each do |key, value|
#  work.send("#{key.to_s}=", value)
#end
work = Work.find_or_initialize_by id: attrs['id']
work.update(attrs)
ecloud 关闭了讨论。 07月12日 11:55
需要 登录 后方可回复, 如果你还没有账号请 注册新账号