Skip to content

Instantly share code, notes, and snippets.

@mileszs
Created May 19, 2010 20:21
Show Gist options
  • Select an option

  • Save mileszs/406791 to your computer and use it in GitHub Desktop.

Select an option

Save mileszs/406791 to your computer and use it in GitHub Desktop.
class Memcached
def fetch(key)
if value = get(key)
value
elsif block_given?
begin
add(key, value = yield)
rescue Memcached::NotStored => e
value = get(key)
end
value
end
end
end
@sneakin
Copy link
Copy Markdown

sneakin commented May 19, 2010

Semantics are wrong. Hash#fetch doesn't store if there's no value. So you should yield and do nothing else but return.

@sneakin
Copy link
Copy Markdown

sneakin commented May 20, 2010

So: def fetch(key); get(key) || yield if block_given?; end

@mileszs
Copy link
Copy Markdown
Author

mileszs commented May 20, 2010

This is a copy of ActiveSupport::Cache::Store#fetch, more or less. http://apidock.com/rails/ActiveSupport/Cache/Store/fetch

The goal is, if there's no value from the #get, store the return value of the block as the value for the given key.

@sneakin
Copy link
Copy Markdown

sneakin commented May 20, 2010

@avdi recently highlighted Hash#fetch. idk, place the yield as an argument to #add. One liner bliss?

@mileszs
Copy link
Copy Markdown
Author

mileszs commented May 20, 2010

Haha, there's that. It's a difficult method to make elegant, because it seems necessary to write it very defensively.

@sneakin
Copy link
Copy Markdown

sneakin commented May 20, 2010

Looking at it again...the rescue clause is useless since #get should return nil since nothing was stored. Here's another stab:

  def fetch(key)
    value = get(key)
    if value.nil? && block_given?
      value = yield
      add(key, value)
    end

    value
  rescue Memcached::NotStored
    nil # or do we want value, the result of the yield? change the above to ensure?
  end

And now to curse FriendFeed. :-)

@mileszs
Copy link
Copy Markdown
Author

mileszs commented May 20, 2010

I don't know that it's necessarily completely useless. If, for some reason, the add to Memcache is slow, and a key of the same name gets added between the check for a value and the completion of our add, we'll get the NotStored error. If that happens, we want to return the value of the key that was stored while we were trying to store something else. Haha.

Maybe it's overly defensive? I don't know. I left it out initially, but I can see its purpose.

@sneakin
Copy link
Copy Markdown

sneakin commented May 20, 2010

  def fetch(key)
      get(key) || add(key, yield) rescue get(key) if block_given?
  end

Is that legal? Ruby ♥ moment if it is. Where's the spec?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment