编写这个Ruby方法的更好,更惯用的方法是什么?

时间:2016-03-25 21:33:44

标签: ruby caching refactoring

这是一种检查缓存并为缓存未命中进行昂贵的API调用的简单方法。

    def search_for params
      cache = Cache.for( params )
      return cache if cache

      response = HTTParty.get( URL, params )
      Cache.set params, response

      response
    end

但它看似冗长而不是惯用语。

4 个答案:

答案 0 :(得分:4)

Cache.set是否返回设置的Cache对象?如果是这样,这可能有效:

def search_for params
  Cache.for(params) || Cache.set(params, HTTParty.get( URL, params ))
end

答案 1 :(得分:2)

让我们做一些疯狂的事。

[][]=添加到Cache

Cache.instance_eval do
  alias_method :[], :for
  alias_method :[]=, :set
end

创建要重用的模块

module Cacheable
  def cached(key)
    Cache[key] ||= yield
  end

  def self.included(base)
    base.extend self
  end
end

使用Cacheable模块

class Foo
  include Cacheable

  # `cached` can be used in instance methods
  def search_for(params)
    cached(params) do
      HTTParty.get(URL, params)
    end
  end

  # `cached` can also be used in class methods
  def self.search_for(params)
    cached(params) do
      HTTParty.get(URL, params)
    end
  end
end

答案 2 :(得分:1)

基于您的问题的另一种选择

def search_for params
  unless response = Cache.for( params )
    response = HTTParty.get( URL, params )
    Cache.set params, response
  end
  response
end

答案 3 :(得分:1)

如果您可以修改Cache#for的实现并让它接受在缓存中找不到值时将执行的块,那么它可以将调用序列简化为如下所示:

def search_for params
  return Cache.for( params ) { HTTParty.get( URL, params ) }
end

您可以添加修改后的for方法,如下所示:

class Cache
    # alias the original `for` as `lookup`
    singleton_class.send(:alias_method, :lookup, :for)

    def self.for params, &block
        value = lookup(params);
        if (block_given? and not value) then
            value = block.call
            set params, value
        end
        value
    end
end