Class runs when require - ruby

I have required a file with a class in it, but never created a object for required class. But when I run the 'main.rb' file the required class is started. Why ?
main.rb
require "./required_class.rb"
puts "This should be listed first"
required_class.rb
class Hello_World
puts "Hello World"
end

In ruby classes don't behave like functions, they are evaluated on execution. because of this fact your class is effectively no different from simply:
puts "Hello World"
What you're seeing is expected and if you just run in IRB:
> class Hello_World
> puts "Hello World"
> end
"Hello World"
=> nil
To stop it from running when you require the file containing it you'd need to create a constructor function like so:
class Hello_World
def initialize
puts "Hello World"
end
end
Now you won't see any output until you run Hello_World.new
If you want to be able to print your message without instantiating you could use:
class Hello_World
##hello = "Hello World"
end
Then you can get the message with puts Hello_World.hello

Because the body of the class gets evaluated when you require it. Often you'll see class definitions return nil because the last thing in the class was a method definition (from 2.1 onwards def returns the name of the method as symbol).

Related

Why does nothing happen when I execute my module in a terminal?

I tried running my code in a Ruby script from my terminal. Nothing happens when I run
ruby Main.rb.
# Main.rb
module Main
class MyClass
def initialize
puts "Hello World"
end
end
end
You need to instantiate your class first, as your puts command will not execute until you invoke MyClass#new. For example:
module Main
class MyClass
def initialize
puts "Hello World"
end
end
end
Main::MyClass.new
Hello World
=> #<Main::MyClass:0x007f9d92144308>
Because it's loading the Module and then doing nothing with it. It never gets instantiated (initialized), only defined.
You define the module like so:
module Main
class MyClass
def initialize
puts "Hello World"
end
end
end
And then initialize it by making a new MyClass object. (On the end of the same file)
test = Main::MyClass.new
Hello World
=> #<Main::MyClass:0x2979b88>
You can handle this in an even better way by only doing this when you run the file directly, not when it's loaded from another ruby file.
if __FILE__ == $0
test = Main::MyClass.new
puts test
end
This way you can do whatever you like when the code is run directly, for example, testing, but just load the module silently every other time.
When running the file directly, it will work as above, but when running this in IRB, you'll only see the following:
=> nil

execute a method in a ruby file

I have this dummy ruby class file (Bar.rb):
class Bar
foo() # execute foo()
def foo()
puts "Hello world, "
end
end
And I ran the file with:
$ ruby Bar.rb
I was expecting to see "Hello, world" in the command, but got this error:
undefined local variable or method `foo' for Bar:Class (NameError)
from bar.rb:3:in `<main>'
So how do I execute a method? Does Ruby have any main method (as in Java or C/C++)?
A couple of reasons this doesn't work as you have written it.
The method foo hasn't been declared before you attempt to call it.
The method foo, as you have declared it, is an instance method. You're not invoking it on an instance of the class.
This would work:
class Bar
def self.foo
end
foo
end
As others have said, though, you probably don't need to wrap this in a class.
You don't need any class, you can call any methods you like right from the file itself:
bar.rb:
puts "Hello, world!"
If you want to stick with your code, you are calling foo before its declaration, which obviously doesn't work.
First you define the method, then you call it.
No need for a main procedure, the first code outside a class or method will be executed first. The script itself is the main. I'm sure there are better definitions for this, but i'm sure you will underdstand.
def foo()
puts "Hello world, "
end
foo() # execute
Also no need to put this in a class, then you would have to initiate her first.
class Bar
def foo()
puts "Hello world, "
end
end
bar = Bar.new
bar.foo

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")

Why can't I call a method?

So I thought I'd learn some Ruby. I was playing with the interpreter but I wanted to make bigger programs so I downloaded Aptana, an IDE. When I try to run this code:
class HelloWorld
def h
puts "hello World!"
end
h
end
It gives me an error that says h is an undefined local variable. When I type the commands into the interpreter (without the class start and end) it calls h the way I want it to.
I'm at a loss here. what's going on?
While defining a class, the methods you define are instance methods. This means you would call them like so:
class HelloWorld
def h
puts "hello world!"
end
end
instance = HelloWorld.new
instance.h
Ruby is complaining that your method doesn't exist because, whilst defining a class body, any function calls made are to class methods (or singleton methods).
If you really wanted to do this, you would do it like so:
class HelloWorld
def self.h
puts "hello World!"
end
h
end
Your problem is that you've sent the h message whilst in class scope. (I'm sure some folks with more Ruby experience will want to correct my wording here; also, if I'm entirely wrong, accept my apologies.)
You can send h from another instance method on HelloWorld:
class HelloWorld
def h; puts "hello world!"; end
def g
h
end
end
HelloWorld.new.g
# => "hello world!"
Try this
class HelloWorld
def self.h
puts "hello World!"
end
h # you can only call h like this if it is defined as a class method above
end
HelloWorld.h # you can call the class method like this also
You need to define h as a class method to call it like that. ALternatively, you can do this
class HelloWorld
def h
puts "hello World!"
end
end
a = HelloWorld.new # instantiate a new instance of HelloWorld
a.h
Good luck!

Class from string

Let's say I have a class named Klass, and a class called Klass2. Depending on the user's input, I'd like to decide whether I'll call "hello_world" on Klass, or Klass2:
class Klass
def self.hello_world
"Hello World from Klass1!"
end
end
class Klass2
def self.hello_world
"Hello World from Klass2!"
end
end
input = gets.strip
class_to_use = input
puts class_to_use.send :hello_world
The user inputs "Klass2" and the script should say:
Hello World from Klass2!
Obviously this code doesn't work, since I'm calling #hello_world on String, but I'd like to call #hello_world on Klass2.
How do I "convert" the string into a referrence to Klass2 (or whatever the user might input), or how could I else would I achieve this behavior?
puts Object.const_get(class_to_use).hello_world
puts eval(class_to_use).hello_world
If you have ActiveSupport loaded (e.g. in a Rails app) you can also use #constantize:
class_to_use.constantize.hello_world

Resources