In Ruby, I'd like to be able to do something like this:
days_of_week = %i(Sunday Monday Tuesday Wednesday Thursday Friday Saturday)
today = :Sunday
today = today 1
if today > :Saturday
today = :Sunday
end
This gives me
'undefined method ' ' for :Sunday:Symbol (NoMethodError)
Can I define a method somehow?
I've looked at various stack overflow questions on enums, and didn't see what I'm looking for, but it's a large volume of information to sort through.
CodePudding user response:
This code, as it is, does not work in ruby (as you noticed). Symbol :Sunday
does not know that it's placed in an array, so adding a 1
to it does not make any sense.
You can compare symbols like that, but the results will surprise you. :Wednesday
is greater than :Thursday
, for example.
Why not just operate on indexes in the array. With integer indexes you can increment them and compare with expected results. Could look like this, for example:
today = days_of_week.index(:Friday)
puts "tomorrow is #{days_of_week[today 1]}" # >> tomorrow is Saturday
CodePudding user response:
I think I would create an index with as many entries as necessary to describe what you are trying to do.
Here is a hash of hashes to hold the index and next/prev logical day:
days_of_week = %i(Sunday Monday Tuesday Wednesday Thursday Friday Saturday)
idx=Hash.new {|h, k| h[k] = {} }
days_of_week.each_with_index{ |e,i|
idx[e][:idx]=i
idx[e][:next_day]=
(i 1)==days_of_week.length ? days_of_week[0] : days_of_week[i 1]
idx[e][:prev_day]=
i==0 ? days_of_week[-1] : days_of_week[i-1]
}
# {:Sunday=>{:idx=>0, :next_day=>:Monday, :prev_day=>:Saturday}, :Monday=>{:idx=>1, :next_day=>:Tuesday, :prev_day=>:Sunday}, :Tuesday=>{:idx=>2, :next_day=>:Wednesday, :prev_day=>:Monday}, :Wednesday=>{:idx=>3, :next_day=>:Thursday, :prev_day=>:Tuesday}, :Thursday=>{:idx=>4, :next_day=>:Friday, :prev_day=>:Wednesday}, :Friday=>{:idx=>5, :next_day=>:Saturday, :prev_day=>:Thursday}, :Saturday=>{:idx=>6, :next_day=>:Sunday, :prev_day=>:Friday}}
Then you can get the next day or previous day:
idx[:Tuesday][:next_day]
# Wednesday
idx[:Saturday][:next_day]
# Wraps around to Sunday
You can create a compare:
def cmp(x,y, idx)
idx[x][:idx]<=>idx[y][:idx]
end
So that :Wednesday
is properly less than :Thursday
cmp(:Wednesday, :Thursday, idx)
-1
Or sort another array of symbols into the order of the index:
%i(Saturday Sunday Tuesday Thursday Wednesday Friday Monday).
sort_by{ |day| idx[day][:idx] }
# [:Sunday, :Monday, :Tuesday, :Wednesday, :Thursday, :Friday, :Saturday]
Those types of function can be added to a class to represent the type of symbols you want to deal with.