How can I inherit module in ruby script? - ruby

I have a hierarchy like
ABC(Folder) ----> abc.rb, def.rb
DEF(Folder) ----> a1.rb, b1.rb
GHI(Folder) ----> x1.rb, y1.rb
I want to inherit/include def.rb, which is a module into abc.rb and then a1 should inherit abc.rb and should be able to access all methods defined in def.rb.
Right now, I am including def.rb in every script file, but I don't want to do this. I just want to inherit vertically.

It's hard to deal with ABC-like naming system )
If you want to include 10 modules in each of your classes, you can do it this way. Let's imagine you have modules ModuleTest::Files and ModuleTest::Network:
in module_test/network.rb
module ModuleTest
module Network
def network
puts 'hello from ModuleTest::Network#network'
end
end
end
in module_test/files.rb
module ModuleTest
module Files
def files
puts 'hello from ModuleTest::Files#files'
end
end
end
You can make some ModuleTest::Base class like this:
require 'module_test/files'
require 'module_test/network'
module ModuleTest
class Base
include Files
include Network
end
end
This class includes all the functionality you have, so inherit your classes from it:
require 'module_test/base'
class Foo < ModuleTest::Base
end
foo = Foo.new
foo.network
foo.files
Output:
>ruby -I. foo.rb
hello from ModuleTest::Network#network
hello from ModuleTest::Files#files

Let my first point out that I suspect that I'm misinterpreting your question, because I can't see why you'd want to do this. So if that's the case, please point it out and I'll delete this.
The process you describe works (at least for me in Ruby 1.9.3).
module Def
def method_from_def
puts "Method from Def"
end
end
class Abc
include Abc
end
class X < Abc
end
X.new.method_from_def #=> "Method from Def"
You might need to be a little specific in your require statements, but if you're already able to 'include' the script you've already got that down. (Unless by 'include' you mean copy and paste it into the source file.)

Related

Why do some modules have inner classes?

I know how a module can be used in a class in Ruby:
module Calculator
def add(a,b)
a+b
end
end
class Watch
include Calculator
def time
Time.now
end
end
w = Watch.new()
puts w.time # 2020-03-11 22:34:01 +0000
puts w.add(3,5) # 8
But, sometimes I can see some module has a class inside. For instance, in Rails, helpers:
module MyModule
class MyClass
def foo
puts 'foo'
end
end
end
What's the point of this?
Why would I have a class inside a module?
Modules can be used that way for scoping purposes. In your example you can refer to MyClass from outside the module by MyModule::MyClass.
There are several uses for this, like grouping together related classes under a common namespace.
It's better to get more information about this from some Ruby tutorials (for examples and stuff). Check out "Ruby - Modules and Mixins" for more information.

How to require file as part of a module in Ruby?

I have a file SomethingClass.rb which looks as follows:
class SomethingClass
def initialize
puts "Hello World"
end
end
I would like to require the file SomethingClass.rb, and make SomethingClass part of the module SomethingModule without changing the file.
Also, I would like to avoid making SomethingClass part of the namespace outside of that module at all. In other words, I want to require the file and the rest of my application should not change apart from the fact that SomethingModule will be defined.
This does not work (I assume because require is executed in Kernel scope):
module SomethingModule
require './SomethingClass.rb'
end
Is this possible in Ruby?
Without changing your class file, from what I've gathered, there are only kind of hacky ways to do this - see Load Ruby gem into a user-defined namespace and How to undefine class in Ruby?.
However I think if you allow yourself to modify the class file, it is a little easier. Probably the simplest thing to do would be to set the original class name to something that will surely have no name conflict, e.g.:
class PrivateSomethingClass
def initialize
puts "Hello World"
end
end
module SomethingModule
SomethingClass = PrivateSomethingClass
end
Now you have SomethingModule::SomethingClass defined but not SomethingClass on the global namespace.
Another way to do it would be to use a factory method and anonymous class:
class SomethingClassFactory
def self.build
Class.new do
def initialize
"hello world"
end
end
end
end
module SomethingModule
SomethingClass = SomethingClassFactory.build
end

How do I import ruby classes into the main file?

I'm trying to learn how to program with Ruby and I want to create separate files for separate classes, but when I do I get the following message:
NameError: uninitialized constant Book
const_missing at org/jruby/RubyModule.java:2677
(root) at /Users/Friso/Documents/Projects/RubyApplication1/lib/main.rb:1
However, it works if I put the class directly into the main file. How can I solve this?
Main code:
book1 = Book.new("1234", "Hello", "Ruby")
book2 = Book.new("4321", "World", "Rails")
book1.to_string
book2.to_string
Class code:
class Book
def initialize(isbn,title,author)
#book_isbn=isbn
#book_title=title
#book_author=author
end
def to_string
puts "Title: ##book_title"
puts "Author: ##book_author"
puts "ISBN: ##book_isbn"
end
end
In order to include classes, modules, etc into other files you have to use require_relative or require (require_relative is more Rubyish.) For example this module:
module Format
def green(input)
puts"\e[32m#{input}[0m\e"
end
end
Now I have this file:
require_relative "format" #<= require the file
include Format #<= include the module
def example
green("this will be green") #<= call the formatting
end
The same concept goes for classes:
class Example
attr_accessor :input
def initialize(input)
#input = input
end
def prompt
print "#{#input}: "
gets.chomp
end
end
example = Example.new(ARGV[0])
And now I have the main file:
require_relative "class_example"
example.prompt
In order to call any class, or module from another file, you have to require it.
I hope this helps, and answers your question.
You need to instruct the Ruby runtime to load the file that contains your Book class. You can do this with require or require_relative.
The latter is better in this case, because it loads the file relative to the directory in which the file containing the require is specified. Since that's probably the same directory, you can just require_relative the file name, without the .rb extension by convention.
You can google 'require vs require_relative ruby' to find out more about the differences.

Ruby Variables (Extern?)

I've just started programming in Ruby and i'm trying to work on a little debug switch that works similar as to below, similar to a C extern variable. My problem is, Im not sure how to have a variable in one file in module X of one file, and access it in the same module of another file.
I'd prefer to not use global variables as they are not limited by scope - is there a scope wide variable I can do this with?
(note, this is std ruby 2.0.0 - NOT rails!)
Cheers,
Chris
#file A.rb
module foo
##myVariable = 'ruby'
##do something
end #end foo
#file B.rb
module foo
module self.bar(x)
if(##myVariable == 'ruby')
puts 'do a barrel roll'
end
end #end bar
##do something
end #end foo
undefined variable ##myVariable
In order for file A to affect the code in file B, B needs to require A.
A.rb
module Foo
##x = 1
end
B.rb
require './A'
module Foo
def self.bar
##x
end
end
p Foo.bar
# 1
Try this:
# file_a.rb
module Foo
BARREL_ROLL = true
end
# file_b.rb
require_relative 'file_a'
module Bar
if Foo::BARREL_ROLL == true
puts 'do a barrel roll'
end
end
Notes:
##myVariable is a class variable and typically not recommended to use, try to refrain from using it.
I understand you are just starting out Ruby, perhaps checking out the style guide may help you improve to a more Rubyesque way of doing things; your code seems to be influenced by your previous language's style. Following the guide will make your code more readable for most in the community and soon for yourself.

How to call or activate a class?

In my lib folder I have billede.rb:
class Billede
require 'RMagick'
#some code that creates a watermark for a image
image.write(out)
end
How do I call/activate the class? Is the only way to change it to a Rake task?
You can't call a class directly. You have to call a method on that class. For example:
class Billede
def self.foobar
# some kind of code here...
end
end
Then you can call it via Billede.foobar
Perhaps you should read some documentation on basic ruby syntax before trying to do more complex things (such as manipulating images w/ Rmagick).
Code 'inside a class' is run just like any other code. If you have a Ruby file like this:
puts "Hello from #{self}"
class Foo
puts "Hello from #{self}"
end
and you run the file (either via ruby foo.rb on the command line or require "./foo" or load "foo.rb" in a script) it then you will see the output:
Hello from main
Hello from Foo
If you want to load a utility that 'does something' that you can then invoke from a REPL like IRB or the Rails console, then do this:
module MyStuff
def self.do_it
# your code here
end
end
You can require "./mystuff" to load the code, and when you're ready to run it type MyStuff.do_it
And, as you may guess, you can also create methods that accept arguments.
If you want to define a file that can be included in others (with no immediate side effects) but which also "does its thing" whenever the file is run by itself, you can do this:
module MyStuff
def self.run!
# Go
end
end
MyStuff.run! if __FILE__==$0
Now if you require or load this file the run! method won't be invoked, but if you type ruby mystuff.rb from the command line it will.
# in /lib/billede.rb
class Billede
def self.do_something(arg)
# ...
end
def do_anotherthing(arg)
# ...
end
end
# inside a model or controller
require 'billede'
Billede::do_something("arg")
# or
billede_instance = Billede.new
billede_instance.do_anotherthing("arg")

Resources