Basic mistake?

Nia wrote:

--------------------------------------------------------
class BookStore
  @bookstore=Array.new
    def initialize(*books)
    i=0
    books.each do |x|
      #@bookstore.push(x)
      puts "(#{i})" + x.inspect
      i+=1
    end
  end
end

class Book
  def initialize(name,cost)
    @book_name=name
    @book_cost=cost
  end
    def detail
    puts "Book: #{@book_name} ($#{@book_cost})"
  end
end

b1=Book.new('Harry Potter','9.95')
b2=Book.new('The Raven','8.65')
store = BookStore.new(b1,b2)
--------------------------------------------------------------
this bit of code seems to work fine, but when i try to assign an object to my bookstore array, i'm given an error(i commented it out since it wasn't working). wierd part is that this seem to work fine outside of a class. am i missing something?, like a declaration? this isn't the first time i've encounter this problem. please help me solve it.

At least two mistakes here... move the @bookstore line
down into the initialize method. And take off the #
from that line -- that makes it a comment.

Hal

You can also consolidate part of the initialize method like so:
def initialize(*books)
   @bookstore=Array.new
   books.each_with_index do |x,i|
      @bookstore.push(x)
      puts "(#{i})" + x.inspect
   end
end

···

On Thu, 16 Nov 2006 14:21:21 +0900 Hal Fulton <hal9000@hypermetrics.com> wrote:

Nia wrote:
> --------------------------------------------------------
> class BookStore
> @bookstore=Array.new
>
> def initialize(*books)
> i=0
> books.each do |x|
> #@bookstore.push(x)
> puts "(#{i})" + x.inspect
> i+=1
> end
> end
> end
>
> class Book
> def initialize(name,cost)
> @book_name=name
> @book_cost=cost
> end
>
> def detail
> puts "Book: #{@book_name} ($#{@book_cost})"
> end
> end
>
> b1=Book.new('Harry Potter','9.95')
> b2=Book.new('The Raven','8.65')
> store = BookStore.new(b1,b2)
> --------------------------------------------------------------
> this bit of code seems to work fine, but when i try to assign an object to my bookstore
> array, i'm given an error(i commented it out since it wasn't working). wierd part is that this
> seem to work fine outside of a class. am i missing something?, like a declaration? this isn't
> the first time i've encounter this problem. please help me solve it.
>

At least two mistakes here... move the @bookstore line
down into the initialize method. And take off the #
from that line -- that makes it a comment.

Hal

Hal Fulton schrieb:

Nia wrote:

--------------------------------------------------------
class BookStore
  @bookstore=Array.new
    def initialize(*books)
    i=0
    books.each do |x|
      #@bookstore.push(x)
      puts "(#{i})" + x.inspect
      i+=1
    end
  end
end

class Book
  def initialize(name,cost)
    @book_name=name
    @book_cost=cost
  end
    def detail
    puts "Book: #{@book_name} ($#{@book_cost})"
  end
end

b1=Book.new('Harry Potter','9.95')
b2=Book.new('The Raven','8.65')
store = BookStore.new(b1,b2)
--------------------------------------------------------------
this bit of code seems to work fine, but when i try to assign an object to my bookstore array, i'm given an error(i commented it out since it wasn't working). wierd part is that this seem to work fine outside of a class. am i missing something?, like a declaration? this isn't the first time i've encounter this problem. please help me solve it.

At least two mistakes here... move the @bookstore line
down into the initialize method. And take off the #
from that line -- that makes it a comment.

Which is what (s)he intentionally did ("i commented it out since it wasn't working") :wink:

Hal

Robert

Robert Spielmann wrote:

Hal Fulton schrieb:
> Nia wrote:
>> --------------------------------------------------------
>> class BookStore
>> @bookstore=Array.new
>> def initialize(*books)
>> i=0
>> books.each do |x|
>> #@bookstore.push(x)
>> puts "(#{i})" + x.inspect
>> i+=1
>> end
>> end
>> end

...

Hal is correct, moving it into initialize solves the problem.

It appears that declaring the instance variable at the class
level makes it an instance variable of the class, rather than
of the object of the class being created when initialize is called.

In short, declare your instance attributes inside initialize.

Cheers
Chris

Hal is correct, moving it into initialize solves the problem.

It appears that declaring the instance variable at the class
level makes it an instance variable of the class, rather than
of the object of the class being created when initialize is called.

In short, declare your instance attributes inside initialize.

Cheers
Chris

hehe, i knew it was some basic mistake. thank you all very much. so is it wrong to declare a
variable outside a method? cause i usually do that a lot,

Hi --

Hal is correct, moving it into initialize solves the problem.

It appears that declaring the instance variable at the class
level makes it an instance variable of the class, rather than
of the object of the class being created when initialize is called.

In short, declare your instance attributes inside initialize.

Cheers
Chris

hehe, i knew it was some basic mistake. thank you all very much. so
is it wrong to declare a variable outside a method? cause i usually
do that a lot,

It's wrong to initialize a variable in one scope and try to use it in
another :slight_smile: Actually there are (at least) two things to keep in mind:

1. Local variables are visible in their local scope. So here:

   class C
     x = 1
     def meth
       x = 2
     end
   end

the two x's are totally unrelated.

2. Instance variables are scoped to, or associated with, "self". In
other words, an instance variable (@var) always belongs to whatever
object is "self" at that point. Here:

   class C
     @x = 1 # (a)
     def meth
       @x = 2 # (b)
     end
   end

you're dealing with two selfs (selves?). At (a), self is the class
object itself, C. At (b), self will be whatever instance of C calls
the methods "meth". So, since there are two selfs, the two @x's are
totally unrelated to each other.

David

···

On Fri, 17 Nov 2006, Nia wrote:

--
                   David A. Black | dblack@rubypal.com
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

This misunderstanding probably stems from the following type of code:

  # NOTE: no enclosing class
  @a = "foo" # (a)
  def bar
    puts @a # (b)
  end
  bar # => prints "foo"

Se *here*, the @a seems to be able to stretch across the method definition. Why?

The reason is because all "procedural" (top level scope) code is
invoked in the context of the "main" object. At (a), self is "main",
so @a belongs to the "main" object. When you define methods in context
of the "main" object those methods are actually created as instance
methods on Object, which makes them available everywhere (since every
object in Ruby is_a? Object). So the @a at (b) refers to the @a of
whoever calls bar. At (c), "main" is calling bar, so its value of @a
(set at (a)) is used.

Let's try calling bar from the context of an object that doesn't have @a set:

  @a = "foo" # belongs to "main"

  def bar
    puts(@a || "@a is empty!")
  end

  bar # => prints "foo"

  module A
    # "self" here is the module itself
    bar # => prints "@a is empty!"
  end

So, the moral? The above construct where you have @a defined at the
top level and then (tried) to use in a top level method only works by
accident. While it works in the common case where used, it's not
correct and can lead to errors when the top level method is called in
a context *other* than the top level. If you *really* need that sort
of behavior, use globals ($a). That's what they're for. But, of
course, if you find yourself needing globals you probably want to
rethink your approach. :slight_smile:

Hope that made sense...

Jacob Fugal

···

On 11/16/06, Nia <badluck105@yahoo.com> wrote:

so is it wrong to declare a
variable outside a method? cause i usually do that a lot,