Stop execution of code when requiring another file in Ruby - ruby

I have a file foo.rb that has the following:
class Foo
def do_stuff
puts "Doing stuff"
end
def do_other_stuff
puts "Doing other stuff"
end
end
f = Foo.new
f.do_stuff
I want require this file in another file bar.rb and access to the methods in the Foo class without executing the instructions in foo.rb.
Expecting to output just:
Doing other stuff
I tried the following in bar.rb:
require 'foo'
f = Foo.new
f.do_other_stuff
However, requiring the file executes the code of foo.rb, and my output is this:
Doing stuff
Doing other stuff
Is there a good way to get around this execution?

requiring a file will execute the code. I think its a bad design, what you are trying to achieve. However you can still circumvent it by putting the code in if __FILE__ == $0 block:
if __FILE__ == $0
f = Foo.new
f.do_stuff
end
if __FILE__ == $0 will make sure the code inside the block is executed only when run directly and not when required, as in your example.

If you just want to block the outputs, do something like this:
stdout_old = $stdout.dup
stderr_old = $stderr.dup
$stderr.reopen(IO::NULL)
$stdout.reopen(IO::NULL)
require "foo"
$stdout.flush
$stderr.flush
$stdout.reopen(stdout_old)
$stderr.reopen(stderr_old)

I want require this file in another file bar.rb and access to the methods in the Foo class without executing the instructions in foo.rb.
Since the methods in the Foo class are defined by executing the instructions in foo.rb, this is obviously non-sensical and impossible: either you want Foo, then you have to execute the instructions, or you don't execute the instructions, but then you don't get Foo.

Related

Execute ruby method from command-line

I have the following class in Ruby in the file test_class.rb:
class TestClass
def test_verify_one
# DO SOME
end
def test_verify_two
# DO SOME
end
end
To execute this class I send two parameters to the terminal, ENVIRONMENT and LANGUAGE.
So... to call from terminal I use:
ruby test_class.rb ENVIRONMENT LANGUAGE
This executes both methods.
I want to execute only one.
I tried the following:
ruby -r "test_class.rb" -e "TestClass.test_verify_one" ENVIRONMENT LANGUAGE
but it is not working.
Can you help me?
Within the same folder as test_class.rb, run the ruby command with the following command syntax:
ruby -I . -r "test_class" -e "TestClass.test_verify_one" arg1 arg2
Breaking this command down we get:
-I . Include current directory in $LOAD_PATH so we can use require
-r Require a file named test_class within the $LOAD_PATH. This is possible because we included the current directory in our load path above (.rb extension is optional here).
-e Same as you've provided, evaluates the following code.
Now, if we call ARGV within that method we should get arg1 and arg2 on separate lines:
#...
def self.test_verify_one
puts ARGV
end
#...
If you want your first method to take the variables you're passing to it you need to define your first method to take two variables, like so:
class TestClass
def test_verify_one (var1, var2)
# DO SOME
end
def test_verify_two
# DO SOME
end
end
You will then need to put a condition into your second which causes it to only execute under the conditions you want it to... or just comment it out if you don't need it at the moment. So, for example, if you only wanted test 2 to fire when variables were not passed in, your code would look something like this:
class TestClass
def test_verify_one (var1, var2)
# DO SOME
end
def test_verify_two (var1, var2)
if (var1 and var2) defined? nil
# DO SOME
end
end

Return the last evaluated object from a file

Is it possible to return the last evaluated object from a Ruby file?
Suppose I have a file like:
# app.rb
def foo
"Hello, world!"
end
foo
Then, I would expect something like this behavior:
# other_file.rb
require_relative!('foo') # => "Hello, world!"
Instead of the require_relative's true returned value, we fetch the last evaluated object of the required file.
Is there a way to have a require_relative!-like behavior?
It sounds like a bad practice. Ruby files are storages of ruby code, not data.
Idiomatically you should create a Ruby file with class or module, require it and call some function from it.
# foo.rb
module Foo
extend self
def foo
"bar"
end
end
# irb
require 'foo'
Foo.foo
#=> bar
Otherwise, as #sawa mentioned, you should read file as a string and eval it. Which is idiomatically wrong.

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

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