diaojiulishifei
diaojiulishifei

Reputation: 55

Failed to pass the value of an instance variable to another from within the same class (Ruby)

this is my code.

class Dog

    attr_accessor :name
    attr_reader :breed, :age

    def initialize(name, breed, age)
        @name = name
        @breed = breed
        @age = age
        @distance_in_kms = []
    end

    def walk(distance_in_kms)
        @distance_in_kms << {distance: distance_in_kms}
    end

    def walked_distance 
       @walked_distance = @distance_in_kms.inject(0) {|sum, hash| sum + hash[:distance]}
    end

    def display_walks
        puts "#{@name} has had #{@distance_in_kms.length} walks and walked #{@walked_distance} kms today:"
        @distance_in_kms.each do |each_walk|
            puts "#{each_walk[:distance]} km"
        end
    end 

    #overriding to_s to print a meaningful representation of a class
    def to_s
        return "Dog: breed-#{@breed} name-#{@name}"
    end
end

doggo = Dog.new("Roy", "Labrador", 8)
doggo.walk(3)
doggo.walk(5)
doggo.walk(1)

puts doggo.name = "Dang"
puts doggo.breed
doggo.display_walks

The result I have is this

Dang
Labrador
Dang has had 3 walks and walked  kms today:
3 km
5 km
1 km

The expected value before kms should be 9, the sum of each walk in a day. Obviously, I have done something wrong with the walked_distance method. I was trying to pass the value of array @distance_in_kms into @walked_distance, but it didn't work, the return value was nil.But what can I do to fix the problem and get expected results? Thank you!!

Upvotes: 0

Views: 78

Answers (3)

diaojiulishifei
diaojiulishifei

Reputation: 55

I could've done this right at the beginning too:

class Dog

    attr_accessor :name
    attr_reader :breed, :age

    def initialize(name, breed, age)
        @name = name
        @breed = breed
        @age = age
        @distance_in_kms = []
        @walked_distance = []
    end

    def walk(distance_in_kms)
        @distance_in_kms << {distance: distance_in_kms}
        @walked_distance = @distance_in_kms.inject(0) {|sum, hash| sum + hash[:distance]}
    end

    def display_walks
        puts "#{@name} has had #{@distance_in_kms.length} walks and walked #{@walked_distance} kms today:"
        @distance_in_kms.each do |each_walk|
            puts "#{each_walk[:distance]} km"
        end
    end 

    #overriding to_s to print a meaningful representation of a class
    def to_s
        return "Dog: breed-#{@breed} name-#{@name}"
    end
end

doggo = Dog.new("Roy", "Labrador", 8)
doggo.walk(3)
doggo.walk(5)
doggo.walk(1)

puts doggo.name = "Dang"
puts doggo.breed
doggo.display_walks

or use class methods to create a counter then try to link it to the instances(It's a very long way though)

Indeed, understanding variable scope is a real struggle for a beginner. Anyway, much appreciation for anyone who answered my question. Thank you!

Upvotes: 0

iGian
iGian

Reputation: 11183

You must call the method to update the @walked_distance, for example:

def display_walks
    walked_distance # <------ This line
    puts "#{@name} has had #{@distance_in_kms.length} walks and walked #{@walked_distance} kms today:"
    @distance_in_kms.each do |each_walk|
        puts "#{each_walk[:distance]} km"
    end
end

Or change the walked_distance method and call it directly from the string interpolation:

def walked_distance 
   @distance_in_kms.inject(0) {|sum, hash| sum + hash[:distance]}
end

def display_walks
    puts "#{@name} has had #{@distance_in_kms.length} walks and walked #{walked_distance} kms today:"
    @distance_in_kms.each do |each_walk|
        puts "#{each_walk[:distance]} km"
    end
end

Off topic, just a small change to evaluate:
@walked_distance = @distance_in_kms.values.sum

Upvotes: 1

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230286

puts "#{@name} has had #{@distance_in_kms.length} walks and walked #{@walked_distance} kms today:"

But you never call the code to calculate @walked_distance. Either update it when you add a new walk or calculate total distance here (by calling walked_distance, for example)

Upvotes: 1

Related Questions