Ruby Class question

Hi all,

I am really starting to get into ruby and I am currently reading the
PickAxe book and the Agile Rails book, but there is one part of classes
that I don't understand and I can't seem to find any reference to it.

Here is a basic class as defined in the Pickaxe book:

1: class Song
2: attr_writer :duration
3: end

My question is, what is the whole statement on line #2? I know what it
does, it creates a attribute-setting method for the "duration" variable,
but what I don't understand is how it does it. When does that line of
code get executed?

I am used to doing classes in C++ and PHP where the only thing outside
methods and inside a class are class variable declarations. Is this a
way to make variable declarations with a method?

This seems to be a very common construct in Ruby and I want to
understand what it is and how to use it correctly. Thanks

Peer

···

--
Posted via http://www.ruby-forum.com/.

Peer Allan wrote:

Hi all,

I am really starting to get into ruby and I am currently reading the PickAxe book and the Agile Rails book, but there is one part of classes that I don't understand and I can't seem to find any reference to it.

Here is a basic class as defined in the Pickaxe book:

1: class Song
2: attr_writer :duration
3: end

My question is, what is the whole statement on line #2? I know what it does, it creates a attribute-setting method for the "duration" variable, but what I don't understand is how it does it. When does that line of code get executed?

I am used to doing classes in C++ and PHP where the only thing outside methods and inside a class are class variable declarations. Is this a way to make variable declarations with a method?

This seems to be a very common construct in Ruby and I want to understand what it is and how to use it correctly. Thanks

In Ruby, objects interact with other objects my sending messages. Messages usually (but not always) map to methods; methods in turn can manipulate instance variables.

Instance variables (the @foo things) are private, but if you want to create the appearance that an object has public properties, you can create methods that match the instance variables:

def foo
   @foo
end

def foo=( val )
   @foo=val
end

This is such a common convention that Ruby has a method that writes these methods for you:

attr_accessor :foo

This take symbol :foo and uses it to create the pair of methods that reference an instance variable of the same name.

Note that you can always create such methods by hand, and the names need not match the internal variables; such properties are just methods calls:

# Create the appearance of a "public property" called 'foo'
def foo
   @bar
end

def foo=( val )
   @bar=val
end

And you can add whatever code you like to these methods.

A few things to note:

Ruby methods usually return the value of the last expression evaluated, but methods that end with '=' do not follow this; they return the value passed to the method.

When you use attr_accessor, attr_reader, or attr_writer to create these methods, RDoc will list them as *attributes*, not as methods; they will not appear in the list of methods in the class's RDoc.

(If you create the exact same methods by hand, though, RDoc treats them as methods.)

···

--

James Britt

http://www.ruby-doc.org - Ruby Help & Documentation
Ruby Code & Style - The Journal By & For Rubyists
http://www.rubystuff.com - The Ruby Store for Ruby Stuff
http://www.jamesbritt.com - Playing with Better Toys
http://www.30secondrule.com - Building Better Tools

Peer Allan wrote:

Hi all,

I am really starting to get into ruby and I am currently reading the PickAxe book and the Agile Rails book, but there is one part of classes that I don't understand and I can't seem to find any reference to it.

Here is a basic class as defined in the Pickaxe book:

1: class Song
2: attr_writer :duration
3: end

My question is, what is the whole statement on line #2? I know what it does, it creates a attribute-setting method for the "duration" variable, but what I don't understand is how it does it. When does that line of code get executed?
  
James already answered the question pretty well, I just want to address the "when does that line get executed?" question.
It is executed when the class is 'parsed'. For example:

irb(main):001:0> class A
irb(main):002:1> puts "Hello!"
irb(main):003:1> end
Hello!
=> nil

Notice that "Hello!" appears immediately after I define the class and it gets parsed. So the attr_writer() method (it is really just a method, not special syntax) is executed while your class is being defined and adds a method to your class for you. You can execute any ol' code you wanted within the class definition, as shown above.

Also, the attr* methods DO NOT declare any variables. They only create methods to access those variables.

irb(main):001:0> class A
irb(main):002:1> attr_reader :something
irb(main):003:1> end
=> nil
irb(main):004:0> a = A.new
=> #<A:0x40223968>
irb(main):005:0> a.instance_variables
=>
irb(main):006:0> a.methods.sort
=> ["==", "===", "=~", "__id__", "__send__", "class", "clone", "display", "dup", "eql?", "equal?", "extend", "freeze", "frozen?", "hash", "id", "inspect", "instance_eval", "instance_of?", "instance_variable_get", "instance_variable_set", "instance_variables", "is_a?", "kind_of?", "method", "methods", "nil?", "object_id", "private_methods", "protected_methods", "public_methods", "respond_to?", "send", "singleton_methods", "something", "taint", "tainted?", "to_a", "to_s", "type", "untaint"]

Notice the method called "something" which was defined by attr_reader :something.

Hope that helps.

-Justin

Justin Collins wrote:

James already answered the question pretty well, I just want to address
the "when does that line get executed?" question.
It is executed when the class is 'parsed'. For example:

irb(main):001:0> class A
irb(main):002:1> puts "Hello!"
irb(main):003:1> end
Hello!
=> nil

Thanks for the explanations. This is what I was looking for. I did not
realize that the code within the class definition gets executed, rather
than just defined. Neat!

Thanks again,

Peer

···

--
Posted via http://www.ruby-forum.com/\.

Peer Allan wrote:

... I did not realize that the code within the class definition gets executed, rather than just defined. Neat!

Yes, it's actually very neat -- you can put almost anything in there:

   class Foo
     if condition? then
       def bar(arg1, arg2)
         ...
       end
     end

     [:foo, :bar, :baz].each do |name|
       define_method(name){ puts name.inspect }
     end
   end

Cheers,
Daniel

Peer Allan wrote:

Justin Collins wrote:

James already answered the question pretty well, I just want to address
the "when does that line get executed?" question.
It is executed when the class is 'parsed'. For example:

irb(main):001:0> class A
irb(main):002:1> puts "Hello!"
irb(main):003:1> end
Hello!
=> nil

Thanks for the explanations. This is what I was looking for. I did not realize that the code within the class definition gets executed, rather than just defined. Neat!

It's a subtle point, though.

For example, there have been threads here on some issues that arise when you do not control the order in which files are loaded.

You may see this idiom a lot, too:

if __FILE__ == $0
   # Some code ...
end

This checks to see if the file has been loaded directly, rather than being included in another file. It is a way to wrap stuff (such as unit tests or command line interaction) that should not execute if the source file is being used by as part of a larger application

···

--
James Britt

http://www.ruby-doc.org - Ruby Help & Documentation
Ruby Code & Style - The Journal By & For Rubyists
http://www.rubystuff.com - The Ruby Store for Ruby Stuff
http://www.30secondrule.com - Building Better Tools