Helpful Information
 
 
Category: Ruby & Ruby On Rails
Ruby Newbie

Hi, I'm a Ruby newbie and I'm really having trouble getting to grips with its syntax.

I practiced by setting up a really basic class, which seems to work:
class Man
attr_accessor :name, :age, :address

def initialize(name, age, address)
@name = name
@age = age
@address = address
end
end


I then wanted to go a step further and have an array as an attribute, so that each new Man I create has an empty array that can be filled up with friends (or Man objects).

This is what I have tried, but I'm not sure what I'm doing wrong? Am I declaring the array in the right way? Do I need the attr_accessor part?

Any help or advice would really appreciated:




class Man
attr_accessor :name, :age, :address, friend_list

def initialize(name, age, address, friend_list)
@name = name
@age = age
@address = address
friend_list = []
end
end



Thank you!

Tom Jones

attr_accessor is a mechanism that determines the access level of instance variables. Specifically, it makes them both readable and writable from outside the class. I explained a bit about it and its friends attr_reader and attr_writer in this post. (http://codingforums.com/showpost.php?p=601634&postcount=2)

If you do want to add the friend_list variable to public roster you want to prefix it with a colon (:) in the attr_accessor line as is done in your example for name, age, and address. This makes friend_list refer to the internal symbol corresponding to the variable and not the variable itself. If that sounds a little confusing don't worry about it-- just recognize that it needs to be used with the accessors, as it's otherwise not a huge part of the language.

What your initialize method is doing now is valid but is probably not what you intend. It accepts a parameter called friend_list, which creates the implicit local variable friend_list, which you then overwrite with an empty array. The method ends, along with friend_list's local scope, so it's garbage collected and never heard from again.

You say you want each instance to have its own list, so to make the variable belong to the instance instead of to the method, prefix it in the function body with an @ in the same manner as the other variables.

Solving the problem of overwriting the data passed as friend_list depends on your intent. If you want to enforce an initial friendless state, simply take the friend_list variable out of the arguments list:



def initialize(name, age, address)
@name = name
@age = age
@address = address
@friend_list = []
end


If you'd like to allow client code to pass in an initial array of friends and just be sure in any event that you at least end up with an initialized array in that slot you can provide a default value in the arguments list:



def initialize(name, age, address, friend_list = [])
@name = name
@age = age
@address = address
@friend_list = friend_list
end


Using this code you can pass in a name, age, address and friend list and the instance will bind to all their values, or you can pass just the name, age, and address and friend_list will fall back to the empty set. Some danger creeps in with this method in that you can also pass in anything else you want for friend_list, including a number or a string, so it may be appropriate to insert some sanity checks as you build up the class.

Thank you for helping me! I've found Ruby quite tricky to get used to, but I think that's because I've only used c# before :)

I'm gradually getting the hang of its syntax - I think it will take much practice!

Thanks for taking the time to explain things so clearly - very helpful indeed - and much appreciated!!

Tom










privacy (GDPR)