Reputation: 468
I have difficulties understanding the setter and how to apply the value in use.
In the below example,
def time_string=(seconds)
@time_string = calculator(seconds)
end
How can I get the seconds' value from setter?
Thanks a lot
class Timer
def seconds
@seconds = 0
end
def time_string
@time_string
end
def seconds=(t)
@seconds = t
end
def time_string=(seconds)
@time_string = calculator(seconds)
end
def calculator(x)
array = []
sec = (x % 60).to_s
min = ((x / 60 ) % 60).to_s
hour = (x / 3600).to_s
temp = [hour, min, sec]
temp.map {|i| i.length < 2 ? array.push("0#{i}") : array.push("#{i}") }
array.join(":")
end
end
Upvotes: 0
Views: 639
Reputation: 8424
I think I get what you're trying to accomplish. First, all that calculate code...why? Why not use the methods in the Time
class? Second, there are not such thing as setters in Ruby. Everything in Ruby is a method. So technically, what you call a setter is a method that acts like a setter. In your code, both methods seconds=
and seconds
act as a setter (the first sets @seconds
to the return value of the calculator
call, and the second method sets @seconds
to 0).
You can't get the seconds value from a setter method, the purpose of a setter method is, after all, to SET something. If you want to get something, use a getter method. And it's pretty simple to create a getter method, just change your seconds
method to this:
def seconds
@seconds # we GET the value of @seconds now, we don't set it to 0
end
Ruby can create this method automatically in the background for you with just one line added inside your class, and that line is attr_reader :seconds
. Each time you see this in some Ruby code, assume that what Ruby does in the background is generate something similar to the seconds
method above. In the same fashion, if you want Ruby to also automatically generate a setter method code like this:
def seconds=(t)
@seconds = t
end
then use attr_writer :seconds
. These attr_reader and attr_writer methods exist because making setter and getter methods is so common that this shortens your program significantly, especially if you have, say, 10 instance variables (you have @seconds
and @time_string
now , but you could also have instance variables for minutes, hours, days, etc. that would be a lot of methods for getting/setting the instance variables!). In the same fashion, you could also create a getter method automatically for @time_string
as well:
def time_string
@time_string
end
But NOT a setter method because your set logic for @time_string
is kinda different than the method Ruby would create (attr_reader and attr_writer create simple getter/setter methods), if you type attr_writer :time_string
, then Ruby would create this method in the background:
def time_string=(some_value)
@time_string = some_value
end
which is not what you want. You can simplify your code a lot, here's my version:
class Timer
attr_reader :seconds, :time_string
attr_writer :seconds
def time_string=(seconds)
@time_string = calculator(seconds)
end
def calculator(x)
Time.at(x).utc.strftime("%H:%M:%S")
end
end
a = Timer.new
a.seconds = 30
p a.seconds #=> 30
a.time_string = 50
p a.time_string #=> "00:00:50"
You could also further simplify this code by using attr_accessor
for seconds, for that I recommend this excellent answer which explains more about these shortcuts.
Upvotes: 2
Reputation: 662
Not sure why do you want to return value from setters. setters are used to applying initial values to the class variables. you can use accessors to retrieve the value of your instance variables.
If you have problems understanding setters and accessors I would suggest reading the following link : Trying to learn / understand Ruby setter and getter methods
Upvotes: 1