Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby Ruby Modules Store Inventory Using Modules Creating an In Stock Report

Sergio Cruz
Sergio Cruz
15,550 Points

Why is it that in the in_stock? method the stock_count is defined without an @?

I've been playing around with it and I know it doesn't work if you add the @ sign. So just a bit confused about this. If someone could shed some light as to why this is I'd appreciate it. Thanks!

3 Answers

Erik Nuber
Erik Nuber
20,629 Points

Given this code...

  def in_stock_report
      puts "#{self.to_s} In Stock Report"
      reportable = instances.select do |instance| 
           puts instance.stock_count   #added this in and changed to a do/end
           puts instance.inspect #also added this
           instance.in_stock? 
      end
      reportable.each do |item|
        line = []
        line.push("Item: #{item.attributes[:name]}")
        line.push("Stock: #{item.stock_count}")
        if item.attributes.include?(:size)
          line.push("Size: #{item.attributes[:size]}")
        end
        puts line.join("\t")
      end
      puts "\n"
    end

instance is one portion of the instances array. If you log out to screen the instance.stock_count like I did, you will see it is a number. If you inspect it , you will get back the class, location of the item in memory, the @attributes and @stock_count figure.

  def stock_count
    @stock_count ||= 0
  end

  def stock_count=(number)
    @stock_count = number
  end

  def in_stock?
    stock_count > 0
  end

So in calling the in_stock? method, this checks the |instance| stock_count located at instance.stock_count and sends back true or false.

Confusing but hope that helps.

Jesse James
Jesse James
3,020 Points

Sergio-

While I don't have an active account anymore so I can't see the particular video/example you're referencing the reason why adding the @ in front of stock_count doesn't work is that because @stock_count and stock_count are different types of variables. variables with @ in front of them are considered instance variables and whatever value they have is available anywhere within that particular instance of the class. Variables without this decoration like stock_count are local in scope and whatever value they are assigned is only available within that method/block.

Examples:

class Foo
  @bar = "bar"

  def fizz_buzz 
    buzz = "buzz"
  end

  def snafu
    buzz
  end

  def fubar
    @bar
  end

end

In the above example, the method fubar would work because @bar is available to any method in this instance of Foo. However, snafu wouldn't work (and would return an undefined local variable/method error) because the variable buzz is local to the fizz_buzz method.

Let me know if that helps, if not I'd be happy to try and explain it another way.

I think the reason that the stock_count variable in 'in_stock?' doesn't have an @ in front of it is because this...

def stock_count=(number)
@stock_count = number
end

...is used. This defines the method stock_count to either show what's in the instances variable @stock_count or (with the stock_count=(number)) to optionally assign it a number outside of its own class/module body. Thus the above method works exactly like an attr_accessor method you often put at the top of your class definitions. Try putting...

module Inventoryable
  attr_accessor :stock_count

...at the top of the Inventoryable module and you'll still get everything working the same. So the reason this method...

def in_stock?
  stock_count > 0
end

which just returns a boolean (true or false), doesn't need the @ in front of stock_count is because it is already associated to the @stock_count instance variable by the first method I posted above.

So here's where it gets a little confusing: if you use Eric Nuber's code to actually log out the instance.stock_count number inside of Nuber's instances.select method and make the stock_count local variable inside of the in_stock? method an instance variable like this...

def in_stock?
  @stock_count > 0
end

...it actually makes the rest of the code work. Just putsing in the instances.stock_count in Nuber's expanded .select method calls the stock_count method and thus implicitly brings in the @stock_count instance variable instead of just using the original stock_count (sans @) method. Why putsing it in like that does this I have no idea, but if you wanted to use the @stock_count inside of the in_stock? method you would have to write your reportable line like this...

reportable = instances.select { |instance|
  instance.stock_count
  instance.in_stock?
}

...for it to still have the same function as the original line of code from the lesson.

I still don't think this fully explains the lack of an @ on the stock_count inside of the in_stock? method, and perhaps Nuber's code explains it more eloquently than I, but I think this does give (at least me) some understanding into how the .select enumerable works when used as a class method. Ruby always gets a little tricky to me when it comes to class methods so I wrote this answer to help me out as well and I'm not even sure I got all of it... Oh well. EDIT

Note, if my theory is correct, the only way to replace the stock_count=(number) method is to use the attr_accessor at the top of the Inventoryable module before anything else. Why this is the case, I'm not quite sure. But it will work if you do so.