Require statement usage in ruby - ruby

Is there any difference between these two sample Ruby programs? It seems the same. require just includes the Ruby program on memory.
require_sample1.rb
class Klass
require "./effective_module"
include Mod
end
require_sample2.rb
require "./effective_module"
class Klass
include Mod
end
effective_module.rb
module Mod
end

With the sample code you've given, the behavior is effectively the same. However, it won't always be the same. For example, take the following code:
effective_module.rb
module Foo; end
require_sample.rb
require "./effective_module"
class Foo
end
When you run ruby require_sample.rb you'll get the following error:
require_sample.rb:2:in `<main>': Foo is not a class (TypeError)
This demonstrates to us that on line 2, when class Foo is reached, Foo has already been defined (by effective_module.rb) as a module, and Ruby won't let you redefine a module as a class.
Now suppose we make the following change:
require_sample.rb
class Foo
require "./effective_module"
end
Now when you run ruby require_sample.rb, you get a different error:
.../effective_module.rb:1:in `<top (required)>': Foo is not a module (TypeError)
This time Foo is already defined as a class when the require is reached. Ruby won't let you redefine a module as a class.
Obviously this isn't the kind of code you'd write in the real world, but hopefully it helps demonstrate that where you put your requires does matter.

Related

How do I require a file without defining it's constants on Object in Ruby?

I would like to require a file in Ruby without defining that file's constants on Object. Instead I would like to include them only in a module in the requiring file. For instance if I have a file foo.rb that looks like this:
module Foo
def self.hello_world
puts 'Hello, World.'
end
end
A representation of the result I hope to achieve looks something like this:
module Bar
require_relative './foo.rb'
end
Foo.hello_world
# NameError: uninitialized constant Foo
Bar::Foo.hello_world
# Hello, World.
It seems like the way things are required in Ruby, anything defined at the top level of another file will be defined as a constant on Object and thus globally available. I'm having a problem because I need something from a file that conflicts with a constant in the global namespace.
I recognize that this problem may be fundamental to Ruby, but is it possible there's some metaprogramming technique to overcome this issue?
It looks like the following snippet works for what I'm trying to do:
module Bar
class_eval File.open('./foo.rb').read
end
It may be that I'm still missing something though.
If you don't need to access the ancestor, what you're looking for is extend
module Foo
def hello_world
puts 'Hello, World.'
end
end
module Bar
extend Foo
end
Bar.hello_world

Ruby: Can I 'require' a file which contains only a class?

I have a file /project/lib/invaccessor.rb with the following content
class InvAccessor
def initialize
#browser = "browser"
end
end
and a spec file project/spec/invaccessor_spec.rb which requires it
require_relative '../lib/invaccessor'
describe Invaccessor do
it {expect(2).to be_even}
end
When I run rspec spec/invaccessor.rb I get an uninitialized constant error for Invaccessor. Do I have to put all file contents in a module in order to access them?
I'm using Ruby 2.2.2.
Yes, you can.
Try this inside the directory where your classfile.rb lies:
>> require './classfile'
=> true
>> A
=> A
You definitely don't have to put a class into a module to require it.

How to execute local functions using code from external file in ruby?

Can a require execute a locally defined function? I guess the easiest way to describe what I need is to show an example.
I'm using ruby 1.9.3, but solutions for 1.8 and 2.0 are also welcome.
I have a file main.rb as the following:
class Stuff
def self.do_stuff(x)
puts x
end
require_relative('./custom.rb')
do_stuff("y")
end
And also have a file custom.rb in the same folder, with the following content:
do_stuff("x")
Running main.rb, I have following output:
/home/fotanus/custom.rb:1:in `<top (required)>': undefined method `do_stuff' for main:Object (NoMethodError)
from main.rb:5:in `require_relative'
from main.rb:5:in `<class:Stuff>'
from main.rb:1:in `<main>'
Note that without the require, the output is y.
I'm not sure if it is the best solution but using eval should do the trick.
class Stuff
def self.do_stuff(x)
puts x
end
eval(File.read('./custom.rb'))
do_stuff("y")
end
The output will be:
pigueiras#pigueiras$ ruby stuff.rb
x
y
In C, #include literally drops the code as-is into the file. require in Ruby is different: it actually runs the code in the required file in its own scope. This is good, since otherwise we could break required code by redefining things before the require.
If you want to read in the contents of a script and evaluate it in the current context, there are methods for doing just that: File.read and eval.

Load a Ruby TestCase Without Running It

I'm trying to write a custom tool that runs ruby unit tests with my customizations.
What I need it to do is to load a certain TestCase from given file(through require or whatever), and then run it after doing some calculations and initializations.
Problem is, the moment I require "test/unit" and a test case, it runs immediately.
What can I do with this?
Thanks.
Since you're running 1.9 and test/unit in 1.9 is merely a wrapper for MiniTest, the following approach should work:
implement your own custom Runner
set MiniTest's runner to your custom runner
Something like (shameless plug from EndOfLine Custom Test Runner, adjusted to Ruby 1.9):
fastfailrunner.rb:
require 'test/unit'
class FastFailRunner19 < MiniTest::Unit
def _run args = []
puts "fast fail runner"
end
end
~
example_test.rb:
require 'test/unit'
class ExampleTest < Test::Unit::TestCase
def test_assert_equal
assert_equal 1, 1
end
def test_lies
assert false
end
def test_exceptions
raise Exception, 'Beware the Jubjub bird, and shun the frumious Bandersnatch!'
end
def test_truth
assert true
end
end
run.rb:
require_relative 'fast_fail_runner'
require_relative 'example_test'
MiniTest::Unit.runner= FastFailRunner19.new
If you run this with
ruby run.rb
the custom FastFailRunner19 will be used, which does nothing.
What about reading file content as a regular text file and doing eval on its content after you initialize/calculate things you say? It may not be sufficient for your needs and may require manual setup and execution of testing framework.
Like that (I put heredoc instead of reading file). Basically content is just a string containing your test case code.
content = <<TEST_CASE
class YourTestCase
def hello
puts 'Hello from eval'
end
end
YourTestCase.new.hello
TEST_CASE
eval content
Note: Altough I'd rather not use eval if there is another way. One should be extra careful when evaling code from string manually in any language.
You could collect the test cases you want to deferred its executions and store them in an array. Afterwards you would create a block execution code. For instance:
test_files = ['test/unit/first_test.rb'] #=> Testcases you want to run
test_block = Proc.new {spec_files.each {|f|load f} } #=> block storing the actual execution of those tests.
Once you're ready to call those testcases you just do test_block.call.
To generalize a bit, when thinking about deferring or delaying code executions, closures are a very elegant and flexible alternative.

Using inheritance with multiple files in Ruby

I am new to Ruby . I have a question with respect to using Inheritence in Ruby .
I have a class called as Doggy inside a file named Doggy.rb
class Doggy
def bark
puts "Vicky is barking"
end
end
I have written another class named Puppy in another file named puppy.rb
class Puppy < Doggy
end
puts Doggy.new.bark
I am getting this Error:
Puppy.rb:1:in `<main>': uninitialized constant Doggy (NameError)
Is it mandatory to have these classes (Doggy and Puppy ) inside a single file only?
Edited
As per the suggestions , i have tried using require and require_relative as shown , but still i am getting below Error
Puppy.rb:1:in `<main>': uninitialized constant Doggy (NameError)
class Puppy < Doggy
end
require_relative 'Doggy.rb'
puts Doggy.new.bark
Changes to be done in puppy.rb file
Assuming both files are in the same directory, you're expected to require the file in the following way:
doggy.rb
class Doggy
def bark
puts "Vicky is barking"
end
end
puppy.rb
require File.expand_path('../doggy.rb', __FILE__)
class Puppy < Doggy
end
puts Doggy.new.bark
You should require file with Doggy class in it from file where Puppy is. Put
require './doggy'
or, if you are on ruby-1.9:
require_relative 'doggy'
in puppy.rb (assuming file names are doggy.rb and puppy.rb).
Also, in addition to what everyone else has said, puts Dog.new.bark will always fail, because your class is not called Dog, it's Doggy. Beware.
Not necessary, you have to require the file where Doggy is declared. You can use require or require_relative.
Then, anyway make sure you use the name you declared: Doggy and not Dog.
You are loading the file containing the definition of Doggy, after you inherit from Doggy. Of course, that cannot possibly work. How can you inherit from Doggy on line 1 if you only load the file containing the definition of Doggy on line 3?
You have to include Doggy.rb in you Puppy class

Resources