20

It is really nice to be able to write out

@foo ||= "bar_default"

or

@foo ||= myobject.bar(args)

but I have been looking to see if there is a way to write something like

@foo ||= do
  myobject.attr = new_val
  myobject.other_attr = other_new_val
  myobject.bar(args)
end

roughly equivalent in actually functional code to something like

@foo = if !@foo.nil?
         @foo
       else
         myobject.attr = new_val
         myobject.other_attr = other_new_val
         myobject.bar(args)
       end

And I suppose I could write my own global method like "getblock" to wrap and return the result of any general block, but I'm wondering if there is already a built-in way to do this.

BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
Misterparker
  • 596
  • 5
  • 16

3 Answers3

44

You can use begin..end:

@foo ||= begin
  # any statements here
end

or perhaps consider factoring the contents of the block into a separate method.

jacknagel
  • 1,301
  • 1
  • 10
  • 8
4

I usually write it like this:

@foo ||= (
  myobject.attr = new_val
  myobject.other_attr = other_new_val
  myobject.bar(args)
)
tothemario
  • 5,851
  • 3
  • 44
  • 39
  • For everyone who wanted to go this way, keep in mind that this style is not rubocop-compliant: `Style/MultilineMemoization: Wrap multiline memoization blocks in begin and end.` – BinaryButterfly May 09 '22 at 17:13
-2
@foo ||= unless @foo
  myobject.attr = new_val
  myobject.other_attr = other_new_val
  myobject.bar(args)
end
dteoh
  • 5,794
  • 3
  • 27
  • 35