Forum: Ruby Ruby Class question

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Peer A. (Guest)
on 2006-06-10 06:48
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
James B. (Guest)
on 2006-06-10 08:10
(Received via mailing list)
Peer A. wrote:
> 3: end
> 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 B.

http://www.ruby-doc.org       - Ruby Help & Documentation
http://www.artima.com/rubycs/ - 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
Justin C. (Guest)
on 2006-06-10 09:14
(Received via mailing list)
Peer A. wrote:
> 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
Peer A. (Guest)
on 2006-06-10 16:21
Justin C. 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
Daniel S. (Guest)
on 2006-06-10 17:08
(Received via mailing list)
Peer A. 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
James B. (Guest)
on 2006-06-10 17:50
(Received via mailing list)
Peer A. wrote:
>>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 B.

http://www.ruby-doc.org       - Ruby Help & Documentation
http://www.artima.com/rubycs/ - The Journal By & For Rubyists
http://www.rubystuff.com      - The Ruby Store for Ruby Stuff
http://www.30secondrule.com   - Building Better Tools
This topic is locked and can not be replied to.