# Beginner issues

**URL:** <https://www.ruby-forum.com/t/beginner-issues/80326>\
**Category:** Ruby\
**Created:** [December 24, 2006, 2:28am UTC](https://www.ruby-forum.com/t/beginner-issues/80326 "2006-12-24T02:28:56Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![animejunkie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a88e4f/32.png) [@animejunkie](https://www.ruby-forum.com/u/animejunkie)\
**Post date:** [December 24, 2006, 2:28am UTC](https://www.ruby-forum.com/t/beginner-issues/80326/1 "2006-12-24T02:28:56Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![animejunkie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a88e4f/32.png) [@animejunkie](https://www.ruby-forum.com/u/animejunkie)\
**Post date:** [December 24, 2006, 2:52am UTC](https://www.ruby-forum.com/t/beginner-issues/80326/2 "2006-12-24T02:52:35Z")

</div>

Anime Junkie wrote:

> end # End Song  
> 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
```

---

<div class="post-metadata">

**Author:** ![animejunkie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a88e4f/32.png) [@animejunkie](https://www.ruby-forum.com/u/animejunkie)\
**Post date:** [December 24, 2006, 2:48am UTC](https://www.ruby-forum.com/t/beginner-issues/80326/3 "2006-12-24T02:48:34Z")

</div>

Anime Junkie wrote:

> end # End Song  
> 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 B.

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

---

<div class="post-metadata">

**Author:** ![animejunkie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a88e4f/32.png) [@animejunkie](https://www.ruby-forum.com/u/animejunkie)\
**Post date:** [December 24, 2006, 2:56am UTC](https://www.ruby-forum.com/t/beginner-issues/80326/4 "2006-12-24T02:56:36Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![animejunkie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a88e4f/32.png) [@animejunkie](https://www.ruby-forum.com/u/animejunkie)\
**Post date:** [December 24, 2006, 3:00am UTC](https://www.ruby-forum.com/t/beginner-issues/80326/5 "2006-12-24T03:00:14Z")

</div>

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
