user1650177
user1650177

Reputation: 455

Lazy loading / caching Ruby model attributes?

I'm storing user session keys in a Rails active record model in a column called skey. skey must be obtained every 10 minutes via an external API call, but until 10 minutes have elapsed I'd like to cache skey and return the cached value. Here's what I've got:

def skey_valid?
  (Time.now - self.skey_used_at) < 7.minutes
end

def skey
  if skey_valid? == false
    _skey = authenticate #external API call
    if _skey.nil?
      return nil
    end

    update_attribute :skey, _skey
  end

  update_attribute :skey_used_at, Time.now
  return self[:skey]
end

The problem is now when I call User.skey, it enters an infinite loop and stack overflows. Apparently when I execute update_attribute :skey, _skey, my custom skey function is called which again calls update_attribute :skey, _skey.

Any suggestions on how to get around this? Or if there's a better to approach to what I'm trying to do I'd love to know. Thanks.

Upvotes: 0

Views: 363

Answers (1)

usha
usha

Reputation: 29349

use update_columns instead of update_attribute. Update will directly issue update query instead of using the getter

def skey_valid?
  (Time.now - self.skey_used_at) < 7.minutes
end

def skey
  unless skey_valid?
    _skey = authenticate #external API call
    return nil unless _skey

    update_columns(:skey => _skey)
  end

  update_columns(:skey_used_at => Time.now)
  return read_attribute(:skey)
end

Upvotes: 2

Related Questions