Using inheritance with multiple files in Ruby - 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

Related

How to move classes into their own file

I have a structure like this in file foo.rb:
module Foo
def self.bar
Bar.new
end
class Bar
...
end
end
I want to extract the Bar class, and put it in a separate file, ideally in a folder. I'm struggling to extract the classes from the module into separate files. It is difficult to understand the difference between modules and classes, and where they should reside. I get the error uninitialized constant in my attempts.
Is there some naming convention to follow to make this work?
At the interpreter level, modules are similar to classes. Following rails conventions, you would have a separate file called bar.rb and require it at the top of module foo.
bar.rb:
class Bar
end
foo.rb:
require 'bar'
module Foo
def self.bar
Bar.new
end
end
If you want to put the bar file in a different folder, see info about require_relative which allows you to require a file from a path relative to the current file.

Require statement usage in 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.

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.

Including the same module file within itself in Ruby?

I am learning ruby and about modules and mixins..
I tried the following code. The name of the ruby file test.rb.
module Mod1
def Mod1.sayHello()
puts "Hello Mod1"
end
end
module Mod2
def Mod2.sayHello()
puts "Hello Mod2"
end
end
class TestMod
require 'file'
Mod1.sayHello
end
t = TestMod.new
I am suprised to the output:
Hello Mod1
Hello Mod1 (twice)
I am don't have an explanation for this, can somebody help?
You did not define your initialize method for your class (the constructor). You are simply executing Mod1.sayHello inside the class definition (it is even executed before creating the instance). Try to comment out your t = TestMod.new statement. The output will still stay visible.
Since you include the exact same file, this ends up being executed twice (the file does not get included another time afterwards; ruby prevents this). The class should look like this:
class TestMod
def initialize
Mod1.sayHello
end
end
Why did you include the file anyway? This does not make sense to me.
EDIT: Removed a mistake.
I would recommend to replace the Mod1 and Mod2 inside your module definitions with self. This way you wont have to change the name everywhere if it changes some time.

Rspec, mapping spec files to ruby files under test

What I want is a way of not having to 'require' the class under test in each spec file.
So hoping there is a means of setting the root of the source code under test and rspec automatically mapping my tests, or any other means of automatically mapping specs to ruby files.
In Rspec for rails this happens magically, but this is not a rails project and I can't find any useful information.
I am assuming you have a lib folder and a spec folder within your project where you have code and specs respectively. Create a spec/spec_helper.rb and add
# project_name/spec/spec_helper.rb
$: << File.join(File.dirname(__FILE__), "/../lib")
require 'spec'
require 'main_file_within_lib_folder_that_requires_other_files'
Now within your individual spec files now you just need to add the following line like rails
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
What you have to do is to redefine Object.const_missing.
Found this basic example, modify it to fit your needs (set the right path, etc.):
def Object.const_missing(name)
#looked_for ||= {}
str_name = name.to_s
raise "Class not found: #{name}" if #looked_for[str_name]
#looked_for[str_name] = 1
file = str_name.downcase
require file
klass = const_get(name)
return klass if klass
raise "Class not found: #{name}"
end

Resources