Rails 关于缓存对象更新问题

ecloud · 发布于 2017年06月28日 · 最后由 mlzhuyi 回复于 2017年06月30日 · 340 次阅读
96

先上代码

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 的数据已经存在,导致不能更新数据。请问有什么方法解决这个办法吗?

共收到 6 条回复
96

@huacnlee 大佬请指教,是因为

work.new_record?  # -> true

导致调用save吗?

De6df3

用 second_level_cache

96
De6df3huacnlee 回复

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

19159

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

96
19159mlzhuyi 回复

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

19159
32ecloud 回复
#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)
32 ecloud 关闭了讨论 07月12日 11:55
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册