Use a class instance inside a module - ruby

I'm trying to do this:
example_module.rb
module ExampleModule
def example_method
...
ExampleClass.new.do_something(arg_one, arg_two)
end
end
example_class.rb
class ExampleClass
def initialize()
...
end
def do_something(arg_first, arg_second)
...
end
end
#>> Runtime error - uninitialized constant ExampleModule::ExampleClass
Is it possible to use a class instance inside a module? I found examples that do the opposite; they use a module to extend a class. What am I missing? Is there an article that explains this better?

Add this on top of your example_module.rb file.
require ./example_class'

Related

A function that injects a class level function

I write the same function repeatedly in my classes. Is there a way to declare a function once, and just reference the function declaration in each relevant class to have it become part of the class? I want to do something like:
def add_func
expand self.new_func
puts "hello"
end
end
class A
import "add_func"
end
A.new_func
# >> hello world
I'm looking to make a class method, not an instance method, but I'd be interested in knowing how to do both. What is the Ruby construct I am looking for?
You can extend the methods like this:
module SomeModule
def foo
true
end
end
class SomeClass
extend SomeModule
end
SomeClass.foo
You cann package individual methods into their own modules and extend them:
module MyModule
module NewFunc
def new_func
puts "hello"
end
end
end
class A
extend MyModule::NewFunc
end
A.new_func
With some metaprogramming / monkeypatching you could make a way to extend only certain methods of a module, but I think the approach I have shown works good enough.
If you wanted to make it so individual methods can be imported, or you can import all of them, you can do it like so:
module MyModule
module NewFunc
def new_func
puts "hello"
end
end
module NewFunc2
def new_func2
puts "hello2"
end
end
include NewFunc, NewFunc2 # this adds them to MyModule directly
end
class A
extend MyModule
end
A.new_func
A.new_func2

How could I access global method from class method both are in the same module

I got this error
NoMethodError (undefined method `get_routes' for
How could I access get_routes from Sample.run
module FlightUtil
extend ActiveSupport::Concern
def get_routes(from="TAIPEI", to="OSAKA")
~~~
end
class Sample
def run
get_routes("A", "B")
end
end
end
You need to include the module FlightUtil in the Sample class.
module FlightUtil
extend ActiveSupport::Concern
def get_routes(from="TAIPEI", to="OSAKA")
~~~
end
class Sample
include FlightUtil
def run
get_routes("A", "B")
end
end
end
A Module is a collection of methods and constants. Classes nested inside of modules are used to namespace the classes. You have to include a module in order to access the module's contents (methods or constants).

Get all classes defined in module ruby

Is it possible to know all the classes defined inside a module in ruby.
module A
class Klass
end
class Klass1
end
end
Is there any ruby introspection method to get all the classes defined in module A?
Here is one way
module A
class Klass
end
X = 10
module B;end
end
# Just to list the class(s) defined inside A
A.constants.select { |k| A.const_get(k).instance_of? Class } # => [:Klass]
Nice post to do the same in recursively.

How can I refer to a module method without referring to the entire namespace?

I have a module defined as:
module MyApp
module Utility
def Utility.my_method
I want to use that method in several other classes. But I don't want to have to call:
MyApp::Utility.my_method
I would rather just call:
Utility.my_method
Is that reasonable? I've tried include MyApp::Utility and include MyApp to no avail.
Well, just assign any alias you want, e.g.:
ShortNameGoesHere = MyApp::Utility
ShortNameGoesHere.my_method
Here is an example of mixing in my_method to a class:
#myapp.rb
module MyApp
module Utility
def my_method
"called my_method"
end
end
end
#test.rb
require './myapp'
class MyClass
include MyApp::Utility
end
if __FILE__ == $0 then
m = MyClass.new
puts m.my_method
end
It sounds like you want to maintain the namespace of the module on the mixed-in method. I have seen attempts to do so (https://stackoverflow.com/a/7575460/149212) but it seems pretty messy.
If you need my_method to be namespaced, you could simply include a module identifier in the method name:
module MyApp
module Utility
def util_my_method
"called my_method"
end
end
end

Unable to invoke mixin module method in spec

I have the following module:
# lib/translator/sms_command.rb
module Translator
module SmsCommand
def self.included(klass)
puts "SmsCommand initialized in #{klass}"
end
def alias_command(name)
end
end
end
And the following spec:
# spec/translator/sms_command_spec.rb
require 'spec_helper'
class ExampleCommand
include Translator::SmsCommand
alias_command :x
end
module Translator
describe SmsCommand do
describe "#alias_command" do
it "registers the class with the command registry" do
Translator::SmsCommand.command_registry.should include_key :x
end
end
end
end
Yes #alias_command does nothing at this stage but that's because I'm in the midst of developing it. However, when I run my spec I am seeing...
SmsCommand initialized in ExampleCommand
so the module is certainly being mixed in, however the spec barfs on the alias_command :x line in the ExampleCommand as if the alias_command method is never becoming available.
/spec/translator/sms_command_spec.rb:5:in `<class:ExampleCommand>': undefined method `alias_command' for ExampleCommand:Class (NoMethodError)
I could solve this problem through inheritance though I'd prefer the mixin module. What am I missing?
It's because it's not an include but an extend to access alias_command in your Class method
class ExampleCommand
extend Translator::SmsCommand
alias_command :x
end
You want to define a class method called alias_command, don't you?
In this case you need to extend the class with the module, a simple include will turn the included method into an instance method!
You can do it in a widely accepted way as follows:
module Translator
module SmsCommand
def self.included(klass)
puts "SmsCommand initialized in #{klass}"
klass.extend ClassMethods
end
module ClassMethods
def alias_command(name)
end
end
end
end
This way when you include the module, it will automatically extend the target class with the class methods!

Resources