From: Eric Christopherson Date: 2011-10-29T16:00:46+09:00 Subject: Re: Newbie Ruby Softball On Fri, Oct 28, 2011 at 9:47 PM, mike lev wrote: > I'm new to ruby but trying to learn. I've been trying to figure out some > things about a book example and having the darndest time of it. I've > been trying to google and look up the api and use a book reference but > I'm left with some questions. That's where I was hoping a kind soul from > this forum could come in. Answers directly below, code on bottom. > > I understand that @varname is essentially defining how open the variable > "varname" is, but I don't understand why "@children = children" is > needed, couldn't the code just use "children"? See below. > > children and node_name reference attr_accessor. Am I right to think that > the names of these two objects are inconsequential? What are we doing > here? I'm guessing making instances of attr_accessor and naming them > "children" and "node_name"? > > Does children have the "each" parameter by virtue of inheriting from > attr_accessor? Is each something I can do on each and every object then? > > thanks for bearing with me! > > > > class Tree >  attr_accessor :children,  :node_name attr_accessor is a method, not a class; and :children and :node_name are parameters passed to it; not instances of it. Since they start with colons, they are symbols -- which are like strings in many ways. Usually they are used in Ruby to refer to something in a literal way; here we're not trying to get the value of variables or methods called children and node_name -- we're trying to use the literal names. attr_accessor, then, takes one or more names (which can be symbols or strings) and generates methods from them on the fly. These methods are accessors -- they allow outside code to access instance variables. The names are only consequential in that you have to refer to them by the names you give them. > >  def initialize (name, children=[]) >    @children = children >    @node_name = name >  end Here, name and children (without the @) are parameters to the method initialize; when they come into the method they become local variables. So nothing outside of the initialize method can see them. When we assign them to @-prefixed variables, those are instance variables, which can be accessed anywhere in the class (and, since we defined accessors for them, outside of the class too). Note that the name of the instance variable doesn't have to be exactly the name of the parameter but with @ prefixed -- here the instance variable @node_name corresponds to the parameter name, instead of node_name. > >  def visit_all(&block) >    visit &block >    children.each {|c| c.visit_all &block} >  end children here should be @children; just plain children is a local variable, which isn't defined in visit_all. @children supports the each method because it's an array -- or at least it's expected to be. Since Ruby is dynamically typed, you could make @children any sort of object. Mainly collection-like types (e.g. arrays, hashes, etc.; or user-defined collection types) support the each method. > > >  def visit(&block) >    block.call self >  end > end > > ruby_tree = Tree.new( "Ruby", [Tree.new("Reia"), Tree.new("MacRuby")]) > > puts "Visiting a node" > ruby_tree.visit {|node| puts node.node_name} > puts > > puts "Visiting entire tree" > ruby_tree.visit_all {|node| puts node.node_name}