简体   繁体   中英

What is a better, more idiomatic way of writing this Ruby method?

This is a simple method to check a cache and make an expensive API call for a cache miss.

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

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

      response
    end

But it seems wordy and not idiomatic.

Does Cache.set return the Cache object that is set? If so, this may work:

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

Let's do something crazy.

Add [] and []= to Cache

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

Create a module to reuse

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

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

Use the Cacheable module

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

Another option based on your question

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

If you can modify implementation of Cache#for and have it accept a block that will be executed if value is not found in cache, then, it can simplify the calling sequence to something like below:

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

You can add a modified for method like below:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM