Forum: Ruby Begin else pattern question

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Fb1a6916e06f221b5b53a6665f9858eb?d=identicon&s=25 Mikel Lindsaar (Guest)
on 2008-11-26 00:24
(Received via mailing list)
What is the cleanest way of doing:
def initialize(value)
  begin
    if value == 'blah'
      a_action
    else
      b_action
    end
  rescue
    b_action
  end
end

That is.  If a is needed and doing a throws an exception, do b instead.
 Otherwise, if a is not needed do b.

Or is that the cleanest way?

By cleanest, I mean l don't like calling b_action twice in the method if
I
don't have to, but it's a trade off on readability... and I don't _like_
the
way the code looks now :)

Any other simpler way to do this pattern?

Mikel
B09f99b655b96fd4130aafd04531f6f1?d=identicon&s=25 Eric I. (Guest)
on 2008-11-26 01:15
(Received via mailing list)
On Nov 25, 6:19 pm, Mikel Lindsaar <raasd...@gmail.com> wrote:
> Any other simpler way to do this pattern?

Hi Mikel,

One simplification would be to remove the "begin" and the
corresponding "end" since they're not needed in this situation.

An extreme approach would be to put the basic logic structure into a
method.  But then you'd have to pass in three Procs -- one for the
boolean expression, and one each for a_action and b_action.

If you just want to avoid repeating the b_action, you could raise an
exception in your else to force yourself into the rescue clause and do
the b_action there.

Hope there's something in there that you find helpful!

Eric

====

Interested in hands-on, on-site Ruby or Ruby on Rails
training?  See http://LearnRuby.com for information about a
well-reviewed courses.
Edfcfb783260609029d57cd4e1c39d65?d=identicon&s=25 Alan Johnson (Guest)
on 2008-11-26 01:16
(Received via mailing list)
On Tue, Nov 25, 2008 at 3:19 PM, Mikel Lindsaar <raasdnil@gmail.com>
wrote:
>  end
>
> Any other simpler way to do this pattern?
>
> Mikel
>

A device that turns exceptions into a return value might assist.
Perhaps something like this:

def succeeded
    begin
        yield
        true
    rescue
        false
    end
end

def a_action(succeed)
    raise "failed" if !succeed
    print "a_action\n"
end

def b_action
    print "b_action\n"
end

def action(value, succeed)
    b_action if !(value == "blah" && succeeded { a_action(succeed) })
end


action "blah", true
action "blah", false
action "not blah", true
action "not blah", false
Fb1a6916e06f221b5b53a6665f9858eb?d=identicon&s=25 Mikel Lindsaar (Guest)
on 2008-11-26 02:07
(Received via mailing list)
On Wed, Nov 26, 2008 at 11:10 AM, Eric I. <rubytraining@gmail.com>
wrote:

> On Nov 25, 6:19 pm, Mikel Lindsaar <raasd...@gmail.com> wrote:
> > Any other simpler way to do this pattern?
> One simplification would be to remove the "begin" and the
> corresponding "end" since they're not needed in this situation.
>

Actually... that cleans it up enough and makes it nice and readable.
    def initialize(raw_field)
      if a
        a_action
      else
        b_action
      end
    rescue
      b_action
    end


Why aren't the begin and end blocks needed?  Is it because it is already
encapsulated within a method any way and if it hits rescue, the rescue
block
is terminated by the method end in any case?

What I am trying to ask is "where did you learn when the begin and end
are
needed and when not?" :)
B09f99b655b96fd4130aafd04531f6f1?d=identicon&s=25 Eric I. (Guest)
on 2008-11-26 04:10
(Received via mailing list)
On Nov 25, 8:02 pm, Mikel Lindsaar <raasd...@gmail.com> wrote:
> Why aren't the begin and end blocks needed?  Is it because it is already
> encapsulated within a method any way and if it hits rescue, the rescue block
> is terminated by the method end in any case?
>
> What I am trying to ask is "where did you learn when the begin and end are
> needed and when not?" :)

Hi Mikel,

It's in the reference section of the "pickaxe" book (in my edition
it's p. 346).

Basically there are three cases when you can use a rescue:

1. Directly within a begin/end block.
2. At the top-level of a method.
3. Attached to a single statement.

Hope that helps,

Eric

====

Interested in hands-on, on-site Ruby or Ruby on Rails
training?  See http://LearnRuby.com for information about a
well-reviewed courses.
6087a044557d6b59ab52e7dd20f94da8?d=identicon&s=25 Peña, Botp (Guest)
on 2008-11-26 04:25
(Received via mailing list)
From: Mikel Lindsaar [mailto:raasdnil@gmail.com]
# def initialize(value)
#   begin
#     if value == 'blah'
#       a_action
#     else
#       b_action
#     end
#   rescue
#     b_action
#   end
# end
#
# That is.  If a is needed and doing a throws an exception, do
# b instead.  Otherwise, if a is not needed do b.

and what if b_action throws, rescue it also w b_action ??


maybe, something like,


def initialize(value)
  if value == 'blah'
     begin
       a_action
     rescue
       b_action
     end
  else
    b_action
  end
end

or, if you like a flag and ensure

def initialize(value)
  a_action if flag = (value == 'blah')
rescue
  flag = false
ensure
  b_action unless flag
end
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2008-11-26 13:09
Here's another option for removing the duplication of b_action:

def initialize(value)
  begin
    if value == 'blah'
      a_action
      return
    end
  rescue
  end
  b_action
end

This is not identical to your original code, which would call b_action
twice if an exception occurred during the first invocation of b_action.

If a_action is short you could fold the first four lines to

    return a_action if value == 'blah'

Note that a bare 'rescue' is the same as 'rescue StandardError'. Certain
exceptions, typically due to lack of system resources, are not caught.
Often that is what you want, but to catch absolutely everything do

    rescue Exception

Finally, there is the expression version of rescue, which I believe
catches StandardError:

def initialize(value)
  (return a_action if value == 'blah') rescue nil
  b_action
end

Regards,

Brian.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2008-11-27 19:23
(Received via mailing list)
2008/11/26 Mikel Lindsaar <raasdnil@gmail.com>:
>  end
>
> Any other simpler way to do this pattern?

def initialize(value)
  if value == 'blah'
    a_action rescue b_action
  else
    b_action
  end
end

Or if you _really_ want to get rid of the second call:

def initialize(value)
  raise "do b!" if value != 'blah'
  a_action
rescue Exception
  b_action
end

Cheers

robert
This topic is locked and can not be replied to.