0

I have some legacy code and completely new to Ruby. I want to change the value of a class instance in Ruby.

class CoffeeMachine
  attr_reader :water
  def initialize
    @water = 100
  end
end
machine = CoffeeMachine.new
machine.water

I now want to change machine.water to 70. I learned that these instances are protected through something called "Encapsulation". But I'm wondering if there is not any way to change this variable. Following this and this I tried changing it like so:

machine.class_eval {@water = 70}

but it doesn't work. When I print it out like so

puts machine.class_eval '@water' it shows 70 but when I use it in my program it somehow doesn't get stored.

7
  • 1
    Why not use the attr_accessor :water? Commented Feb 10, 2021 at 6:05
  • 1
    However this violates encapsulation, you can do: machine.instance_variable_set(:"@water", 70) to set the instance variable's value. Although I'd recommend using the attr_accessor as it gives you both getter and setter methods. Commented Feb 10, 2021 at 6:09
  • 1
    @Tom : I guess you mean that you want to change the value of an instance variable, and not the value of an instance. Why do you declare water explicitly as unchangeable from outside, if you then want to change it? This does not make sense. Commented Feb 10, 2021 at 8:16
  • 1
    With attr_reader, you only specify that you can read the environment variable. Basically, it generates an accessor method for this variable. Similarily, attr_writer creates a setter method for the variable. attr_accessor creates both. See here. Commented Feb 11, 2021 at 7:31
  • 1
    Alternatively, you could use machine.instance_eval { @water=70 }. Note that class_eval would allow for variables on class scope, while instance_eval, as the name implies, can be used for fiddling with instance variables. Of course, you will avoid both if possible, since their use breaks the idea of encapsulation. Commented Feb 11, 2021 at 7:35

2 Answers 2

2

In your Scenario this will be more convenient way to Handle it

class CoffeeMachine
  attr_reader :water
  def initialize(water=100)
    @water = water
  end
end
machine = CoffeeMachine.new

machine.water # 100

machine = CoffeeMachine.new(70)

machine.water # 70

Sign up to request clarification or add additional context in comments.

Comments

0

As @Surya suggested it's also possible to do:

    class CoffeeMachine
      attr_accessor :water
      def initialize
        @water = 100
      end
    end

and then do this:

   machine = CoffeeMachine.new
   machine.water #100
 
   machine.water = 70
   machine.water #70

1 Comment

we not need to use the attr_reader if we are using the attr_accessor because it work for both set and get.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.