Beginner issues

A

Anime Junkie

Hello all,

I'm not much of a developer but will be supporting RoR in the near
future and thought I would familiarize myself with Ruby a bit. I'm
using the "Programming Ruby" book and find that a lot of the examples
don't work. They use too much pseudo code in my opinion. Anyhow, could
anyone explain why the following doesn't work? I've put comments in
where I thought necessary.

class Song

attr_reader :duration

def initialize(duration)
@duration = duration
end

def duration_in_mins=(new_duration)
@duration = (new_duration*60).to_i
end

end # End Song

song = Song.new(360)

puts song.duration # this prints 360

song.duration_in_mins = 2

puts song.duration # this prints out 120

puts song.duration_in_mins # I assumed that this would print 2 but
produces the error "undefined method `duration_in_mins'"

//I know that duration_in_mins is a virtual attribute but if I can use
it for assigning value shouldn't I be able to print that?

Any help is much appreciated.

Regards,

Seth
 
J

James Britt

Anime said:
Hello all,

I'm not much of a developer but will be supporting RoR in the near
future and thought I would familiarize myself with Ruby a bit. I'm
using the "Programming Ruby" book and find that a lot of the examples
don't work. They use too much pseudo code in my opinion. Anyhow, could
anyone explain why the following doesn't work? I've put comments in
where I thought necessary.

class Song

attr_reader :duration

def initialize(duration)
@duration = duration
end

def duration_in_mins=(new_duration)
@duration = (new_duration*60).to_i
end

end # End Song

song = Song.new(360)

puts song.duration # this prints 360

song.duration_in_mins = 2

puts song.duration # this prints out 120

puts song.duration_in_mins # I assumed that this would print 2 but
produces the error "undefined method `duration_in_mins'"

//I know that duration_in_mins is a virtual attribute but if I can use
it for assigning value shouldn't I be able to print that?


The notion of "virtual attribute" is confusing at best.

In Ruby, communication with objects is done via messages (usually these
map to methods). Object data are stored in instance variables, which
are private to the instance,

duration_in_mins=(arg) is a method. It assigns a value to the instance
variable @duration.

To get at the value of an instance variable, from outside of that
instance, you need a method that returns that value.

The call

attr_reader :duration

defines such a method for you. It's a bit of Ruby metaprogramming that
generates a method at runtime.

But the code (so far) has no definition for the method
'duration_in_mins', so you get an exception.



--
James Britt

http://www.ruby-doc.org - Ruby Help & Documentation
http://www.rubystuff.com - The Ruby Store for Ruby Stuff
http://beginningruby.com - Beginning Ruby: The Online Book
 
V

Vincent Fourmond

Anime said:
Hello all,

I'm not much of a developer but will be supporting RoR in the near
future and thought I would familiarize myself with Ruby a bit. I'm
using the "Programming Ruby" book and find that a lot of the examples
don't work. They use too much pseudo code in my opinion. Anyhow, could
anyone explain why the following doesn't work? I've put comments in
where I thought necessary.

class Song

attr_reader :duration

def initialize(duration)
@duration = duration
end

def duration_in_mins=(new_duration)
@duration = (new_duration*60).to_i
end

end # End Song

song = Song.new(360)

puts song.duration # this prints 360

song.duration_in_mins = 2

puts song.duration # this prints out 120

puts song.duration_in_mins # I assumed that this would print 2 but
produces the error "undefined method `duration_in_mins'"

In the code, you define the method duration_in_mins=, which handles
the assignment of @duration. However, you don't define a method
duration_in_mins to return its value in minutes. Adding

def duration_in_mins
@duration/60.0
end

should do it.

Cheers,

Vince
 
G

gga

Anime Junkie ha escrito:
I'm using the "Programming Ruby" book and find that a lot of the examples
don't work. They use too much pseudo code in my opinion.

That's funny. There is no pseudo-code AT ALL in Programming Ruby.
What you see IS actual running Ruby code.
It is a testament to how easy ruby is that it LOOKS like pseudo code.
def duration_in_mins=(new_duration)
@duration = (new_duration*60).to_i
end

This is a function that takes a duration in minutes and converts
(internally) into seconds.
Its use is:

# To specify a 3.2min song
song.duration_in_mins = 3.2
puts song.duration # returns the song in seconds
puts song.duration_in_mins # I assumed that this would print 2 but
produces the error "undefined method `duration_in_mins'"

And that's correct. There's no duration_in_mins function.
You just defined a function duration_in_mins= (notice the EQUAL sign).
That's a setter function, not a getter.

//I know that duration_in_mins is a virtual attribute but if I can use
it for assigning value shouldn't I be able to print that?

No. Setters and Getters are two different functions. You need to
specify both yourself, just like in any other language.
Note, also, that in that example the actual setter never stores the
result in minutes into the class. Thus, you can never get the result
back as minutes, without an additional calculation.

Now... if you add...(you can do this from irb):

class Song
def duration_in_mins
@duration / 60.0
end
end

You'll get what you want. Hope that helps.

---

Adding setters and getters can be rather tedious.
Thus, for simple attributes that don't do any calculation, Ruby
provides attr_accessor, attr_reader and attr_writer functions, that
just add a getter/setter, just a getter or just a setter function
automatically. Thus, your duration attribute can also be written as:

class NewSong
attr_accessor :duration
attr_writer :another
end

song = NewSong.new
song.duration = 20
puts song.duration
song.another = 40
puts song.another ## fails, no reader, just a writer
 
A

Anime Junkie

Thanks to all. I see my mistakes now. Actually my biggest mistake was
missing a a typo so to makes things more simple, I removed several lines
including the following

def duration_in_mins
@duration / 60.0
end

This then led to more confusion. Thanks for the prompt and thorough
responses.

Regards,

Seth
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top