Yulia
Yulia

Reputation: 1585

How to pass variable between methods in Ruby?

Newbie ruby question.

I have a class

class ReportPage < Page

def badge_item(item_int)
  case item_int
  when 1..50   then @item= 1
  when 50..100  then @item= 50
end

def check_completed_items_badge  
  badge_item(50)
  puts @item
end
end

Sure enough, it puts nil. And here comes my question - how can I use @item variable inside of the other method of the class?

Thank you a lot!

Upvotes: 1

Views: 4018

Answers (4)

Dan Bradbury
Dan Bradbury

Reputation: 2116

I know an answer has already been accepted but I wanted to present a more general answer to the question about how instance variables get tossed around.

Straight from ruby-lang you get the following:

Ruby needs no variable declarations. It uses simple naming conventions to denote the scope of variables.

  • var could be a local variable.
  • @var is an instance variable.
  • $var is a global variable.

These sigils enhance readability by allowing the programmer to easily identify the roles of each variable. It also becomes unnecessary to use a tiresome self. prepended to every instance member

It is important to understand the distinction between these different types of variables. To do this I whipped up a small example that should help give anyone with navigates here a good starting point on how these behave.

class Scoping
  @unreachable = "but found it. trololol"
  $instance = "and found it. swag swag"
  def initialize( int )
    trial = @unreachable ? @unreachable : " but failed to find."
    puts "reaching for the unreachable . . ." + trial
    @int = int
  end
end

puts $instance
Scoping.new 10
trial = @int ? @int : " but failed to find."
puts "Reaching for instance from class . . ." + trial
trial = $instance ? $instance : " but failed to find."
puts "Reaching for global variable . . ." + trial

Upvotes: 0

Boris Stitnicky
Boris Stitnicky

Reputation: 12588

The correct approach in your case is to use the OOP:

class ReportPage < Page
  class BadgeItem
    def initialize( int )
      fail "Badge item integer should be in the range 0..99!" unless 0..99 === int
      @int = int
    end
    def classify
      case @int
      when 0...50 then 1
      when 50..99 then 50
      end
    end
  end

  def check_completed_items_badge
    badge_item = BadgeItem.new 50
    puts badge_item.classify
  end
end

Upvotes: 0

taiansu
taiansu

Reputation: 2785

The thing is you miss end keyword for your case. And there is another problem in this program. when(1..50) contain all cases between 1 to 50, and when(50..100) covers 50 to 100, this will lead confusion cause badge_item(50) will go into the first line, set @item to 1 and quit the case ... end block. So at the end it will print 1 on the screen.

To make your intent more clearly, you should use

def badge_item(item_int)
  @item = case item_int
  when 1..49 then 1 #two dots, cover 1 to 49
  when 50..100 then 50
  end
end

OR

def badge_item(item_int)
  @item = case
  when 1...50 then 1 #three dots between, cover 1 to 49
  when 50..100 then 50
  end
end

Upvotes: 5

DanneManne
DanneManne

Reputation: 21180

The problem is not with the variable assignment but instead with your usage of the case/when syntax. When you give case an argument it uses exact matching to compare the different scenarios. A better way in your case would probably be to use something like this instead:

def badge_item(item_int)
  case
    when (1..50).include?(item_int) then @item = 1
    when (50..100).include?(item_int) then @item = 50
  end
end

Edit

Corrections from Tumtu:

case uses === method to compare values. i.e.: (1..50) === 50

Upvotes: 3

Related Questions