Topic: beginning ruby questions

Hi everyone,

I am going through some tutorials and books on Ruby, and I found somethings a little unclear, and was hoping that I might be able to get some guidance here.

Within a class body you can define class methods and instance methods. Pre-
fixing a method name with self. (as we do on line 5) makes it a class method:
it can be called on the class generally.

Line 1 class Order < ActiveRecord::Base 

has_many :line_items 

def self.find_all_unpaid
find(:all, 'paid = 0')
end

def total
sum = 0
line_items.each {|li| sum += li.total}
end
end


Class definitions start with the keyword class followed by the class name (which
must start with an uppercase letter). This Order class is defined to be a sub-
class of the class Base within the ActiveRecord module.

Rails makes heavy use of class-level declarations. Here has_many is a method
that

Re: beginning ruby questions

So...  I read this several times, and I am unclear as to what this really means.  My thought originally was, ok with a .self class method, you can call it anywhere.. which means it doesn't have to have anything to do with the class?  yet their example is referencing the class Order...  which confuses me, and so I don't understand what the uniqueness of .self is in this context?

You can use a class method anywhere but it does have something to do with the class; it is defined there.  To call the method you have to tell the compiler which class it is in.  Hence the "Order.find_all_unpaid".  You would not be able to write only "find_all_unpaid".  It would make no sense.

To use an instance method you have to have an instance of the class and the method operates on the values of that instance.  So to use the total instance method you would do something like this:

@an_order = Order.new
total = @an_order.total

You can call an instance method from within the class without the instance name prefix.  I can add a total2 method that calls the total method.

Line 1 class Order < ActiveRecord::Base
 
has_many :line_items 
 
def self.find_all_unpaid
find(:all, 'paid = 0')
end
 
def total
sum = 0
line_items.each {|li| sum += li.total}
end

def total2
sum = 0
d = total*2             # call to total method above
end


ok my first question is..  the "g1 = Greeter.new("Fred")" -- am I correct to assume that .new is somehow connected to "def initialize" ?

Yes.  When you call "new" it runs the initialize method when it creates the new instance.

2nd question would be:  When do you know when to use a method class vs. an instance class?  I would have thought, instance classes are for "instances" -- meaning one time things..  Methods would be for things being used multiple times.  But in this example, they are recalling the same things repeatedly with different names..  Maybe this is just for example purposes?  But it's just not clear, why to use one over the other, and when.

There is no such thing as an "instance class".  There are classes and there are instances of classes.  A square class is a figure with 4 equal length sides (that doesn't actual exist - think of it as the definition of a square).  An instance of a square is a square with 3 meter sides.  There is only one square class - there can be many instances of a square.

is just simply returning @name ? is that correct?  Why would you do what they are doing in the example?  Wouldnt it be smarter to just do:
g = Greeter.new("Barney")

I'm not sure that code would return the name to "g".  You could do this

g = Greeter.new("Barney").name

which is the "approved" way to do it and uses the name "getter" method.  You could also do it like this:

g = Greeter.new("Barney").instance_variable_get("@name")

but this is less correct than the first and uses a Ruby built in method.

4th question.. I am complete lost as to why there is a 2nd def name-- but that it's def name=(new_name).. but I guess I see what's happening..  They are saying, that you can call this by saying
g.name="x"
and that will call the def where name = new_name...  but.. why would you do this?

Correct.  You call the "name=new_name" to set the instance variable "name" to a new value.  How else would you do this?  For example:

a_square = Square.new(5)      # new square with 5 meter sides.
a_square.size = 10            # the square now has 10 meter sides.

Re: beginning ruby questions

Ok.  Thanks for your reply...  I am still plugging along, reading books and various web tutorials, trying to get familiar with all this stuff.

My next question I have is:

h = {"apple" => "red", "banana" => "yellow", "orange" => "orange"}
h.each_key {|k|} puts "The next key is #{key}." }
h.each_value {|v| puts "The next value is #{value}."}

this makes absolutely no sense to me...  Well, wait-- it makes perfect sense in theory-- but what I don't get is how we are doing an "each" assigning it to k, and then printing KEY.. Shouldn't it be puts "the next key is #{k}", and puts "The next value is #{v}." ??  or-- since we are doing h.each_key.. and not h.each_k...  Shouldn't it be h.each_key {|key| puts "the next key is #{key}" ?

That's all for now.

-patrick

Re: beginning ruby questions

Yes, you are correct.  The "key" and "value" should be "k" and "v".

Additionally there is an extra "}" in line 2.

By the way, you can play with Ruby interactively with the irb command.

Re: beginning ruby questions

A more concise way would be this:

h = {"apple" => "red", "banana" => "yellow", "orange" => "orange"}
h.each { |k,v| puts "The next key is #{k}"; puts "The next value is #{v}" }

Although, it will list as key, value, key, value... instead of key, key,..., value, value,...

Calling each will give you both the key and value passed in as block parameters.

And yes, what you said is right.  It should be #{k}, not #{key}.  Where did you see this tutorial?

Last edited by Firanide (2007-05-12 16:12:23)

Re: beginning ruby questions

Ah, ok thank you...

This example came from the Ruby for Rails book by David A. Black...  Must just be a misprint?

so in your example:

h.each { |k,v| puts "The next key is #{k}"; puts "The next value is #{v}" }

How does each know k=key and v=value, if it's not defined anywhere?  Or is k and v defined in "each"'s method?  I'm used to living in a world where I'd have to say somewhere: k=key and v=value...

-patrick

Last edited by patrick99e99 (2007-05-13 04:16:38)

Re: beginning ruby questions

the each method calls the block once for each key in the hash.  The parameters to the call are the key and value.

Re: beginning ruby questions

got it..  k and v, can be anything. a,b.. x,y... the first value it brings back is a key, and the 2nd is a value...

-p

Re: beginning ruby questions

Yessir.

k, v / key, value / foo, bar

All they are is "placeholder" variables for the block.  Their names don't matter (unless there's another variable outside the block with the same name, but that gets pretty complicated. wink)

Posts [ 9 ]

Pages 1