Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditionally defining functions in Ruby

I have some code that is run in one of a few different locations: as a command line tool with debug output, as part of a larger program that doesn't take any output, and in a rails environment.

There are occasions where I need to make slight changes to the code based on its location, and I realized the following style seems to work:

print "Testing nested functions defined\n"
CLI = true

if CLI
def test_print
    print "Command Line Version\n"
end
else 
def test_print
    print "Release Version\n"
end
end

test_print()

This results in:

Testing nested functions defined
Command Line Version

I've never come across functions that are defined conditionally in Ruby. Is this safe to do?

This isn't how I'm structuring most of my code, but there are a few functions that require complete rewrites per-system.

like image 298
Chris Kinniburgh Avatar asked Sep 14 '15 21:09

Chris Kinniburgh


People also ask

What is then in Ruby?

then is a delimiter to help Ruby identify the condition and the true-part of the expression. if condition then true-part else false-part end. then is optional unless you want to write an if expression in one line.


2 Answers

I don't think that is a clean way.

My suggestion is to define the same sets of methods (with different definition bodies) in different modules, and conditionally include the relevant module into the class/module you are going to call the methods from.

module CLI
  def test_print
    ... # definition for CLI
  end
end

module SomeOtherMode
  def test_print
    ... # definition for some other mode
  end
end

class Foo
  include some_condition ? CLI : SomeOtherMode
end

Foo.new.test_print

If you are only going to use only one mode per run, and think that it is a waste to define the modules that end up not being used, then you can take a further step; define respective modules (CLI, SomeOtherMode, ...) in separate files, and use autoload.

autoload :CLI, "path/to/CLI"
autoload :SomeOtherMode, "path/to/SomeOtherMode"
like image 119
sawa Avatar answered Nov 03 '22 04:11

sawa


It's a form of meta-programming and is generally safe. The real risk is not if it will work as expected, but in testing all the variations you create.

The example you've given here makes it impossible to execute the alternate version. To properly exercise both methods you need a way to force the injection of one or the other.

like image 34
tadman Avatar answered Nov 03 '22 03:11

tadman