Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is use of ||= begin....end block in Ruby?

What is difference in these two code snippets:

   def config
    @config ||= begin
      if config_exists?  
        @config = return some value
      else
        {}
      end
    end
  end

and

  def config
    @config ||= method
  end

  def method
    if config_exists?
      return some value
    else
      {}
    end
  end

I'm confused with the "begin ... end" block. Does it make any difference in the output? If not, then what is use of the begin ... end block here?

like image 230
Twinkalkumar Savani Avatar asked Jan 06 '16 08:01

Twinkalkumar Savani


People also ask

What is ||= in Ruby?

||= is called a conditional assignment operator. It basically works as = but with the exception that if a variable has already been assigned it will do nothing. First example: x ||= 10. Second example: x = 20 x ||= 10. In the first example x is now equal to 10.

How do you use end in Ruby?

END Designates, via code block, code to be executed just prior to program termination. END { puts "Bye!" } Every Ruby source file can declare blocks of code to be run as the file is being loaded (the BEGIN blocks) and after the program has finished executing (the END blocks).

What is begin rescue in Ruby?

Similar to PHP's try-catch, Ruby's exception handling begins with the begin-rescue block. In a nutshell, the begin-rescue is a code block that can be used to deal with raised exceptions without interrupting program execution.

Can we use rescue without begin?

The method definition itself does the work of begin , so you can omit it. You can also do this with blocks. Now, there is one more way to use the rescue keyword without begin .


2 Answers

In your case, you can even omit the begin ... end block:

@config ||=
  if config_exists?  
    return_some_value
  else
    {}
  end

or, using the ternary if:

@config ||= config_exists? ? return_some_value : {}

Does it make any difference in output?

It could make a difference, because unlike def ... end, an begin ... end block doesn't create a new variable scope.

Here's a contrived example:

def foo
  a = 456  # doesn't affect the other a
end

a = 123
b = foo

p a: a, b: b #=> {:a=>123, :b=>456}

Versus:

a = 123
b = begin
  a = 456  # overwrites a
end

p a: a, b: b #=> {:a=>456, :b=>456}
like image 138
Stefan Avatar answered Oct 20 '22 22:10

Stefan


First of all, you need to be aware that a defined method inherently includes the functionality of a begin ... end block.

In the context of exception handling, def method_name ... end is functionally equivalent to begin ... end. Both can include rescue statements for example.

The two blocks of code you have shared are actually identical, and there is no benefit in one over the other ... unless your method is needed in more than one place. In that case, you DRY up your code by putting the logic into a single method and calling it from multiple other places.

like image 40
Jon Avatar answered Oct 20 '22 21:10

Jon