Get the required module names for Lua - lua

Is there a way to check what modules is required by a lua script
after I loaded it?

More of a hack than a real solution: if you control the hosting environment, you can always replace require with your version of it:
local require_original = require
function require(module)
-- do something with the module name
require_original(module)
end

Check out package.loaded table.

Related

Is there a way to call a function every time a module is required in Lua 5.1?

For example, to change the requiring file's environment? In my case, I'm creating a DSL (Domain Specific Language) for building behavior trees, and it would be nice if I could do something like this:
require "behaviortree"
return Sequence {
-- definition of tree
}
without polluting the global namespace with node names, or using a construct like
require "behaviortree".init()
because that's kinda ugly in my opinion. Simply placing a setfenv call in the module file's body doesn't do what I want because it would only call when I require the module the first time and not every time because of require's module caching.
I thought about clearing out the cache of the module every time I require it, but that would mean I need to do something like
require "behaviortrees"
local tree = Sequence {
-- definition of tree
}
create(tree)
and clear the module cache in the create function. That is also something I would like to avoid, but is a better option than calling an init function of the module.
Is there any 'clean' way of using a module to set the environment of the requiring file?
Write your own require function that loads the module using the "original" require and then calls the init function you need on it. Even though the "original" require returns the cached version, your own require function will still call the init function.

Call functions/variables/tables from a separate file in Lua

I'm currently working on a fairly detailed project in Lua, specifically using LOVE2D. I'm currently using require'file' in order to access different parts of my project, but this seems like very poor form. I've ran into the problem of overwriting tables from different files with the same name. There must be a professional, cleaner way to do this, but I haven't been able to find one. Can somebody help me?
Using require is the right way to do it.
Think of a module as a function that gets executed when it's loaded. It's return value is cached and returned on subsequent require calls. Just like you would use local variables to limit the scope in a function, you can do the same in a module.
I'm guessing your modules are implemented as global tables:
mymodule = {}
function mymodule.foo()
return 'bar'
end
And you load the module like:
require 'mymodule'
Just change the module table to a local variable and return it:
local mymodule = {}
function mymodule.foo()
return 'bar'
end
return mymodule
Then, you can load the module with any name you choose:
local mymodule = require 'mymodule'
Since you don't create global variables you don't have to worry about overwriting other modules.
The example used above is from the Module Tutorial on the lua-users.org website. Check it out for more info about creating modules. Also, How to write Lua modules in a post-module() world is also worth reading.

Requiring a Lua file that uses a function declared in the other Lua file

I have this issue in Lua where I have 2 files. FileA may look like this:
require "FileB"
local function foo(bar)
-- random stuff
end
And FileB looks like this
foo(bar)
But an error pops up, saying that foo is an invalid function. Is there any fix for this?
Normal practice would be to put the functions in the required file, not the calling code.
In any case as you have your code above, you are calling foo before you are defining it. So move the require below the definition of foo, and don't use local.
function foo(bar)
-- random stuff
end
require "FileB"

How do i define a second environment.rb file in rails?

My default environment.rb is overflowing, and i would like to have a separate file that works exactly the same way. How can I do so?
You're likely adding things to the environment file that should be in an initializer. Check the config/initializers directory for some examples of what to put in there. That should allow you to break things up and make everything more organized.
Rails actually uses eval to load the special environment files such as config/environments/development.rb. This is the code it uses:
eval(IO.read(configuration.environment_path), binding, configuration.environment_path)
You could define a method such as load_more_environment like this:
def load_more_environment(path)
eval(IO.read(path), binding, path)
end
The first argument to eval is just the code you want to load and it will be executed within the current binding. The third argument will be used to report syntax errors in the file.

What does the "$" character mean in Ruby?

Been playing with Ruby on Rails for awhile and decided to take a look through the actual source. Grabbed the repo from GitHub and started looking around. Came across some code that I am not sure what it does or what it references.
I saw this code in actionmailer/test/abstract_unit.rb
root = File.expand_path('../../..', __FILE__)
begin
require "#{root}/vendor/gems/environment"
rescue LoadError
$:.unshift("#{root}/activesupport/lib")
$:.unshift("#{root}/actionpack/lib")
end
lib = File.expand_path("#{File.dirname(__FILE__)}/../lib")
$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
require 'rubygems'
require 'test/unit'
require 'action_mailer'
require 'action_mailer/test_case'
Can someone tell me what the $: (a.k.a. "the bling") is referencing?
$ identifies a global variable, as opposed to a local variable, #instance variable, or ##class variable.
Among the language-supplied global variables are $:, which is also identified by $LOAD_PATH
$: is the global variable used for looking up external files.
From http://www.zenspider.com/Languages/Ruby/QuickRef.html#18
$: Load path for scripts and binary modules by load or require.
I wanna note something weird about Ruby!
$ does indeed mean load path. And ; means "end line". But!
$; means field separator. Try running $;.to_s in your REPL and you'll see it return ",". That's not all! $ with other suffixes can mean many other things.
Why? Well, Perl of course!
To quote the Ruby Forum:
ruby comes with a set of predefined variables
$: = default search path (array of paths)
__FILE__ = current sourcefile
if i get it right (not 100% sure) this adds the lib path to this array
of search paths by going over the current file. which is not exactly the
best way, i would simply start with RAILS_ROOT (at least for a rails
project)
$:.unshift
is the same as
$LOAD_PATH.unshift
. You can also say:
$: <<
$LOAD_PATH <<
They are pretty common Ruby idioms to set a load path.

Resources