-2

I have some instance methods in a class that must be called in a sequence. The failure of any method in a sequence will require the previous method to be re-called. I'm storing the result of each successful method call in a class variable:

class User
  @@auth_hash = {}
  def get_auth_token
    result = MyApi.get_new_auth_token(self) if @@auth_hash[self]['auth_token'].blank?
    if result['Errors']
      raise Exception, "You must reauthorize against the external application."
    else
      @@auth_hash[self]['auth_token'] = result['auth_token']
    end
    @@auth_hash[self]['auth_token']
  end
  def get_session_id
    result = MyApi.get_new_session_id if @@auth_hash[self]['session_id'].blank?
    if result['Errors']
      get_auth_token
      # Recursion
      get_session_id
    else
      @@auth_hash[self]['session_id'] = result['session_id']
    end
    @@auth_hash[self]['session_id']
  end
end

I would like to get rid of those conditionals, but don't know how to perform the block only if there are errors present in the returned hash.

RubyRedGrapefruit
  • 12,066
  • 16
  • 92
  • 193
  • 1
    It looks like the first line of `get_session_id` will generate an infinite recursion if your condition is met - is that how it's actually written? – Zach Kemp Oct 10 '13 at 19:33
  • I just cobbled this together to simulate what I really have, but that conditional will not execute if result['Errors'] is nil. – RubyRedGrapefruit Oct 10 '13 at 19:42
  • 2
    What is `@@auth_hash` all about? Using class variables is usually a sign something's very wrong with your design. Are you using it as some kind of cache here? That's usually counter-productive, the cache only applies in one process, of which there are usually many, and you have no invalidation code here. – tadman Oct 10 '13 at 19:47
  • I'm trying to use it as some kind of cache from AR. This all runs from one background process. I would love to know a better way, believe me. I've got writer's block after looking at this too long. – RubyRedGrapefruit Oct 10 '13 at 19:49
  • @tadman I am against "Using class variables is usually a sign something's very wrong with your design", but in the OPs case, it does smell wrong because the OP has not shown it used in any class method. – sawa Oct 10 '13 at 19:50
  • 1
    @AKWF Have you considered Zach Kemp's comment? That infinite recursion seems useless. – sawa Oct 10 '13 at 19:54
  • Yeah, that's actually a mistake. – RubyRedGrapefruit Oct 10 '13 at 19:56
  • @sawa Virtually every time someone's using class instance variables directly, they should be using class methods that access them and act as a thin abstraction layer. Your class should not have its state manipulated by instance methods themselves, it just makes things messy and too inter-dependent. – tadman Oct 10 '13 at 19:58
  • 1
    `result => nil` when `if @@auth_hash[self]['session_id'].blank? => false`. Do you want that? If not, fix that and we may be able to help. – Cary Swoveland Oct 10 '13 at 20:17

1 Answers1

1

This whole method requires a rewrite...but to answer your question, why wouldn't the following work?

my_proc = ->(){ fill_me_with_something }
my_var ||= my_proc.call

raise StandardError if my_var.nil?

Editing my answer to better answer the question...The syntax:

 my_proc  =   ->(a,b){ a + b } 

Is another way to express a block, for all intents and purposes:

 my_proc(1, 5)   #=> 6

You can also express Procs in this format:

 my_proc = Proc.new{ |a, b| a + b }

The advantage of using a Proc is that you can set your block-like behavior to some variable, and then invoke call on that proc whenever you want, which, in your case, is when some other variable is blank.

dancow
  • 3,228
  • 2
  • 26
  • 28
  • Thanks Dan! There are things on that first line I don't recognize: If you had to write that first line in English, how would you say it? I understand the assignment and the block, but the "->()" is a mystery to me. – RubyRedGrapefruit Oct 10 '13 at 21:21
  • That's short hand for a Proc...so another way to write it is: my_proc = Proc.new{|val| puts val} (eh screw it, just going to edit my answer) – dancow Oct 10 '13 at 21:46
  • I love this. I never knew that shorthand, thanks a whole lot! – RubyRedGrapefruit Oct 11 '13 at 14:32