How can I mimic Node.js's require function in Ruby?

143 Views Asked by At

In node.js you can write:

var lib = require('lib');

but in Ruby the require function simply runs the code in the file and true is returned.

Currently, I'm using a very dirty solution:

main.rb:

$stuff = []
require './file1.rb'
require './file2.rb'
# and so on

file1.rb:

$stuff << something

and so on.

How can I eliminate the use of a global variable?

eg:

main.rb:

$stuff = []
$stuff << cool_require './file1.rb'
# etc

file1.rb:

exports.what = something
2

There are 2 best solutions below

3
On

One of the biggest errors when working with a language, is trying to make the language working like a different one.

Ruby is not NodeJs, there are features built-in into each language that are unique to the language and cannot be reproduced easily.

In other words, there is no way to implement the NodeJS require behavior in Ruby because in Ruby there is no notion of export. When you require a file, every method/class included in the required file are made available to the scope.

In Ruby there are objects and method visibility. The way you have to make a method visible or not is to declare it as public or private/protected.

0
On

Well, first consider that Ruby is not Node.js. As Simone Carletti said, there are some features that are unique to each language. Sometimes it's good to take from other language but sometimes it's bad.

There are few things that you must keep in mind:

  • meth is method invocation, to pass method you use method method: method(:meth) or package it into module/class

  • you can use class/module by assigning it to some 2nd variable:

    class A; def self.aa; puts 'aa'; end; end; New_a = A; New_a.aa # aa;

  • eval is dangerous method(you can evaluate unknown code)

Method:

Here is one way you can do. It is not idiot-proof tough. It is not 100% safe(eval). :

file1.rb:

Module.new do
  def self.meth1
   42
  end
  def self.meth2
    'meth2'
  end
end
  • This file contain module with 2 methods.
  • I am using Module.new because it returns object that you want. You can assign it later into variable/constant.
  • I am using self.meth* so you don't have to include but run instantly it like this: module_name.meth1()

req.rb:

def cool_require name
  eval(File.read name)
end

Some_variable = cool_require('req.rb') 

puts Some_variable.meth1 # 42
puts Some_variable.meth2 # meth2
  • cool_require reads filename(argument name) and evaluate it(it is just like you would type it in irb/pry)
  • Some_variable is constant. It won't disappear that easily.
  • 2 last line is how it works. As fair I remember, that's how node.js' require works.