Need help with methods within a class

Hi,
I am creating a ruby script to split out nagios configuration files. I
am trying to do it the OOP way by using classes and objects etc. Here is
the code.

#!/usr/bin/ruby
class Host
attr_accessor :name, :ipaddress

def initialize(hostfile)
@hostfile = hostfile
puts name
puts ipaddress
end

def spltter(hostfile, inme)
myfile = File.open(hostfile)
myfile.each_line do |line|
if line =~ /#{inme}/
a = line.split(/\s+/)
return a[2]
end

  end

end

def name
@name = spltter(@hostfile, “host_name*.*”)
end

def ipaddress
@ipaddress = spltter(@hostfile, “address*.*”)
end

end

Get all files in directory

Dir.foreach("./configs") do |files|
#filter out anything that isn’t a config file
if files =~ /.cfg/
hostfile = “./configs/” + files
Host.new(hostfile)

end
end

at the moment it outputs the correct information but that is coming from
the puts in the initialisation method in the Host class. What I would
like to do may not be possible, but here goes.

just after the Host.new method
I would like to use
currenthost = Host.name
currenthostip = Host.ipaddress

Currently when I do this it returns no method defined :frowning:

I am reasonably new to Ruby and OOP programming and am working through
several books on Ruby right now.
Any help would be much appreciated.

Thank you
Rob

Rob Gad wrote in post #1006046:

Hi,
What I would
like to do may not be possible, but here goes.

just after the Host.new method
I would like to use
currenthost = Host.name
currenthostip = Host.ipaddress

Currently when I do this it returns no method defined :frowning:

I am reasonably new to Ruby and OOP programming and am working through
several books on Ruby right now.
Any help would be much appreciated.

Thank you
Rob

class Dog
def initialize(name)
@name = name
end

def name
@name #same as: return @name
end

end

my_dog = Dog.new(‘Spot’)
puts my_dog.name

–output:–
Spot

my_dog.name = ‘Red’

–output:–
undefined method `name=’ for #<Dog:0x10016a048 @name=“Spot”>
(NoMethodError)

=========

class Dog
def initialize(name)
@name = name
end

def name
@name #same as: return @name
end

def name=(new_name)
@name = new_name
end
end

my_dog = Dog.new(‘Spot’)
puts my_dog.name
my_dog.name = ‘Red’
puts my_dog.name

–output:–
Spot
Red

==========

class Dog
attr_accessor :name

def initialize(name)
@name = name
end

end

my_dog = Dog.new(‘Spot’)
puts my_dog.name
my_dog.name = ‘Red’
puts my_dog.name

–output:–
Spot
Red

So writing:

attr_accessor :name

is equivalent to writing:

def name
@name #same as: return @name
end

def name=(new_name)
@name = new_name
end

In other words, you can type:

attr_accessor :name

or you can type:

def name
@name #same as: return @name
end

def name=(new_name)
@name = new_name
end

and ruby doesn’t care which. attr_accessor() is just a short cut to
save you some typing. If you are confused by attr_accessor or don’t
understand it, then don’t use it–type the methods out by hand. (You can
get just the first def by writing attr_reader :name, and you can get
just the second def by writing attr_writer :name.)

Note that you would never write:

attr_accessor :name

and then manually define a method called ‘name’ or ‘name=’, which is
what you did.

Also, when you write:

Host.new(hostfile)

that is the same as writing:

(2 + 3) * 4

in that ruby does some computations, AND THEN because you don’t assign
the result of the computations to a variable, ruby discards the result.

If you have an instance variable called @name, then a method called
‘name’:

def name
@name = spltter(@hostfile, “host_name*.*”)
end

should return the value of @name–not set it’s value. A method for
setting the value of @name would be called ‘name=’, and if it is defined
to take no arguments, then probably anything done inside the body of the
method should be done inside initialize().

7stud – wrote in post #1006052:

A method for
setting the value of @name would be called ‘name=’, and if it is defined
to take no arguments, then probably anything done inside the body of the
method should be done inside initialize().

A method called ‘name=’ should accept arguments, and then use
those arguments to set the value of @name.

Rob Gad wrote in post #1006046:

just after the Host.new method
I would like to use
currenthost = Host.name
currenthostip = Host.ipaddress

Currently when I do this it returns no method defined :frowning:

class Dog
def greet
puts ‘hello’
end
end

Dog.greet

–output:–
undefined method `greet’ for Dog:Class (NoMethodError)

A def with that syntax that appears inside a class creates an instance
method
. That means you can only call those methods with an instance,
which is an object returned by calling Dog.new.

However, you can also define a class method. A class method is called
by the class itself:

class Dog

def self.greet
puts ‘hello’
end

end

my_dog = Dog.new
my_dog.greet

–output:–
undefined method `greet’ for #Dog:0x10016a5c0 (NoMethodError)

Dog.greet

–output:–
hello

Note that you would never write:

attr_accessor :name

and then manually define a method called ‘name’ or ‘name=’,
which is what you did.

You do not have enough understanding yet about what the method
attr_accessor
does–therefore it should not appear anywhere in your code.

def ipaddress
@ipaddress = spltter(@hostfile, “address*.*”)
end

What is the purpose of the ipaddress method? Alternatively, why didn’t
you do this:

def metha
methb
end

def methb
methc
end

def methc
methd
end

def methd
@ipaddress = spltter(@hostfile, “adress*.*”)
end

Why is your method named ‘spltter’ rather than ‘splitter’ or ‘splatter’?

Dir.foreach("./configs") do |files|

Why is that variable named ‘files’ when it is one ‘file’? The name
‘files’ makes one think it is an array containing a bunch of files. And
it’s not even really a file yet–it’s just a filename, so how about
naming it ‘fname’?

Hi Everyone.
You’ve all been extremely helpful.
I have gotten my code to a point where it seems to be working now. I was
just wondering if this is the correct way to work with classes.

Have a look at my project on Github if you’re interested.

Thanks,

https://github.com/rgardam/Parentlookup/blob/master/NagParRel/parent_lookup_classy.rb

def isrouter

That should be named like this:

def is_router?

See the question mark at the end of the method name? And it should
return true or false and NOT set
any instance variables. Instance variables should be set to their
initial values in…wait for it…the method called initialize(). If
you want to provide a way for users to subsequently change an instance
variable to something different than its initial value, then provide a
method called:

def instance_variable_name=(val)
@instance_variable_name = val
end

See the equals sign at the end of the method name?

Rob Gad wrote in post #1006255:

Dir.foreach("./configs") do |files|
if files =~ /.cfg/
#filter out anything that isn’t a config file

Dir.glob("./configs/*.cfg").each do |config_file|


end

Reread this:

===
If you have an instance variable called @name, then if you define a
method called ‘name’:

def name
@name = spltter(@hostfile, “host_name*.*”)
end

it should [ONLY] return the value of @name–not set it’s value.

A method that sets an instance variable is named ‘somename=’. See the
equals sign at the end of the method name? That allows you to write:

obj.somename = 10

and 10 will be sent as an argument to the somename=() method.

However, suppose you just rename all your methods with an = sign on the
end:

def name=()
@name = spltter(@hostfile, “host_name*.*”)
end

Then you would call it like this:

obj.name=()

But because the method doesn’t take an argument, and then use the
argument to set the instance variable, you should just set the
instance variable inside initialize():

def initialize(…)

@name = spltter(@hostfile, ‘host_name’)
end

def greet?(str)
puts str
end

greet?(‘hello’)

–output:–
hello

Hi,
I have re-worked the code somewhat.
https://github.com/rgardam/Parentlookup

Firsly I would like to say thank you for all the help you have given me.
I do feel a little silly for thinking you were more than one person.

I am still a little unsure about the ? at the end of a method that is
only to return true or false. This doesn’t seem to work for me.

I have tried to conform to the rules you have set as best I can. I am
sure I can make it better.
What do you think?