Is it possible to extend a class by using a string as a module ? - Ruby 2.7.1 - arrays

I am doing some tests with Ruby 2.7.1 on FreeBSD 12.1. I know how to extend a class with module with for instance this :
class Myclass
def mymethod
extend Mymodule
end
end
But is it possible to obtain the same result with something that looks like this :
class Myclass
def mymethod
var = "Mymodule"
extend var
end
end
If I do this like that, I off-course obtain an error, since extend is pointing to a string and not a module.
Here are some explanations - it would be useful in the following application for instance :
Imagine you have a folder with a lots of ruby scripts, all of them are module with obvious name. For instance abcd.rb will contain the module Abcd. So I create a file list and save it in an array. Then I can load or require all these file listed in this array. Since the name of modules are predictable, I just have to do some .sub, .chop and .capitalize method to the indices of my array in order to obtain a viable result that looks just like the name of a module.
The idea would be to create a mean of extending my main class with all these modules automatically. In this idea, any modules added to the folder will be automatically loaded and ready for use.
But since the result of my array operations are not "pure" modules names but String I got stuck right here.
So, is there any way to achieve this (maybe I use a wrong path to do so) or is not possible ?
Thanks in advance !

You can't extend "arbitrary string", but you can convert that to a module first:
class Myclass
def mymethod
var = "Mymodule"
extend self.class.const_get(var)
end
end
Where const_get can easily resolve simple module names like X and X::Y.
There's also the constantize method in ActiveSupport, bundled with Rails, which does something similar:
extend var.constantize

Related

How to mock an array containing objects using mockito?

In my Mockito unit test I am trying to mock an array containing instances of the object Message. To do this I try to mock it like normal objects so like:
private var messagesMock = mock(Array<Message>::class.java)
This gives the following error/exception:
org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class [Lrobot.fsrt.robotguest.common.data.Message;
Mockito cannot mock/spy because :
- VM does not not support modification of given type
How to mock an array the right way using Mockito?
A distinct non-answer: you (almost) never mock objects that represent containers!
An array is just that: a container.
You create the container with the size you need, and then you put your mocked objects into that ordinary container, and make sure that container with your prepared content gets used by your production code.
It is as simple as that: you don't mock arrays, or lists, or maps: you create them as is, and manipulate their content!

Keeping track of class objects in Ruby

How would one go about keeping track of a classes objects by pushing the new instances to an Array, and to allow this array to be edited/popped by an object of another class.
For example;
The object 'airplane' (Plane class) is created, and pushed to an Array called 'in-flight'.
The object 'airport' (Airport class) asks it to land and pops from the array.
Is there a way to do so, with and/or without the use of class variables?
You could do this by overriding the initialize method of the Airplane class. Something like this:
class Airplane
class << self
attr_accessor :in_flight
end
self.in_flight ||= []
def initialize(*)
self.class.in_flight << self
super
end
def land!
self.class.in_flight.delete(self)
end
end
then, from anywhere else in your codebase, do something like this:
# We'll just pick a random airplane from the list of those in
# flight, but presumably you would have some sort of logic around
# it (already have an Airplane instance somehow, select one from
# the array according to some criteria, etc).
airplane = Airplane.in_flight.sample
airplane.land!
Not sure that this is the greatest application design in the world, but it will certainly do if your needs are simple.

How can I get the methods defined in a module?

I'm trying to consume an F# assembly from Fsi, but can't seem to find a way to get a list of methods defined in a module so I can call them.
Here's a sample file I'm trying to do this with. In following the "exposing methods that are cross language friendly", I've added a namespace to the top of the file and added a module to contain the let bound methods that were there previously. I'd like to avoid moving everything into static classes if possible.
Can I use reflection, or write the module in another way that helps me find the available methods and proper casing of the methods?
If I correctly understood the problem, I would proceed as follows:
1) Get the desired assembly. For example, the assembly that is currently being executed can be obtained by
System.Reflection.Assembly.GetExecutingAssembly
2) Then I would take all the types defined in the obtained assembly by calling GetTypes. If you want to filter out modules you could write something like.
let modules = Array.filter (fun x -> FSharpType.IsModule x) (assembly.GetTypes())
The documentation for the FSharpType class can be found here. It is included in the Microsoft.FSharp.Reflection namespace.
3) After, you can obtain the methods in a module by calling GetMethods method on a single module. For example, to print them all, you could write something like:
let methods = [| for t in modules do for m in t.GetMethods() -> m |]
for m in methods do
printfn "%A" m
methods is an array containing MethodInfo elements. GetMethods takes an optional parameter of type BindingFlags that can filter out some methods. Take a look at the documentation.
You can also invoke actions by calling the Invoke method on a MethodInfo object.
Hope this was useful.

How to access a main document class array from a movieclip?

I have an array in my main
public var graphArray:Array = [1,2,3,4,5,6];
And I'm trying to access it from within a MovieClip that I've put on my timeline using:
var graph1scale:Number = MovieClip(root).graphArray[0]
It looks like it would make sense to me but when I try to run it I get this error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
Am I wrong to be using MovieClip(root) to try and access it? I've only just started using external classes (this is my first project doing so) and usually I just do everything on the timeline. So MovieClip(root) is familiar to me but I guess it's not the right thing to do here.
Is there a way I can access vars from Main.as?
-----SOLVED-----
I realised MovieClip(root) did work all along but I was just calling on the array before the array was being defined in Main.as. I put a delay on calling graphArray and it worked.
Not sure how that makes sense though because the graphArray is the first thing I've defined in the whole main.as class
Try using this instead
MovieClip(this.root)
This works for me on a test that you can see here:
http://marksost.com/test/as3arrayaccess/
And the source files here:
http://marksost.com/test/as3arrayaccess/test.zip

Ruby C Extension using Singleton

I only wanted to allow one instance of my C extension class to be made, so I wanted to include the singleton module.
void Init_mousetest() {
VALUE mouseclass = rb_define_class("MyMouse",rb_cObject);
rb_require("singleton");
VALUE singletonmodule = rb_const_get(rb_cObject,rb_intern("Singleton"));
rb_include_module(mouseclass,singletonmodule);
rb_funcall(singletonmodule,rb_intern("included"),1,mouseclass);
### ^ Why do I need this line here?
rb_define_method(mouseclass,"run",method_run,0);
rb_define_method(mouseclass,"spawn",method_spawn,0);
rb_define_method(mouseclass,"stop",method_stop,0);
}
As I understand it, what that line does is the same as Singleton.included(MyMouse), but if I try to invoke that, I get
irb(main):006:0> Singleton.included(MyMouse)
NoMethodError: private method `included' called for Singleton:Module
from (irb):6
from C:/Ruby19/bin/irb:12:in `<main>'
Why does rb_include_module behave differently than I would expect it to? Also any tangential discussions/explanations or related articles are appreciated. Ruby beginner here.
Also it seems like I could have just kept my extension as simple as possible and just hack some kind of interface later on to ensure I only allow one instance. Or just put my mouse related methods into a module... Any of that make sense?
according to http://www.groupsrv.com/computers/about105620.html the rb_include_module() is actually just Module#append_features.
Apparently Module#include calls Module#append_features and Module#included. So in our C code we must also call included. Since clearly something important happens there.

Resources