Error while trying to load the gem 'devise. ActiveSupport: Duration can't be coerced into Integer
I faced this yesterday while getting rails 3.2 and ruby 2.4 working together. I fixed it by monkey patching the activesupport library which is where the problem lies.
solution: switch the order of multiplication, put Duration first
Include the following code in your rails initializers:
# pulled from https://github.com/rails/rails/blob/v3.2.22.5/activesupport/lib/active_support/core_ext/numeric/time.rb
class Numeric
def days
ActiveSupport::Duration.new(24.hours * self, [[:days, self]])
end
alias :day :days
def weeks
ActiveSupport::Duration.new(7.days * self, [[:days, self * 7]])
end
alias :week :weeks
def fortnights
ActiveSupport::Duration.new(2.weeks * self, [[:days, self * 14]])
end
alias :fortnight :fortnights
end
# pulled from https://github.com/rails/rails/blob/v3.2.22.5/activesupport/lib/active_support/core_ext/integer/time.rb
class Integer
def months
ActiveSupport::Duration.new(30.days * self, [[:months, self]])
end
alias :month :months
def years
ActiveSupport::Duration.new(365.25.days * self, [[:years, self]])
end
alias :year :years
end
ruby on rails 3.0 TimeWithZone add hours can't be coerced into Fixnum
I found the problem...
this does not work:
purchase.duration.hours + purchase.created_at
but this does:
purchase.created_at + purchase.duration.hours
How to conditionally avoid 'nil can't be coerced into Integer' error
Because some of the account
records have nil
amount, you can convert them to integer
by calling to_i
or to float by to_f
, here account.amount
is returning nil somewhere, do this
account_total += account.amount.to_i
It will resolve the error. But since amount
is a numeric column, you should better set the default value as 0 in migrations at DB level.
or, use sum
account_total = @user.accounts.sum(:amount)
It avoids nil
values and runs a SQL sum
ActiveSupport::Duration incorrectly calculates interval?
ActiveSupport::Duration calculates its value using the following constants and algorithm (I have added the explanation on what it's doing below but here is a link to the source). As you can see below, the SECONDS_PER_YEAR
constant is the average number of seconds in the gregorian calendar (which is then used to define SECONDS_PER_MONTH
). It is because of this, "average definition" of SECONDS_PER_YEAR and SECONDS_PER_MONTH that you are getting the unexpected hours, minutes and seconds. It is defined as an average because a month and year is not a standard fixed amount of time.
SECONDS_PER_MINUTE = 60
SECONDS_PER_HOUR = 3600
SECONDS_PER_DAY = 86400
SECONDS_PER_WEEK = 604800
SECONDS_PER_MONTH = 2629746 # This is 1/12 of a Gregorian year
SECONDS_PER_YEAR = 31556952 # The length of a Gregorian year = 365.2425 days
# You pass ActiveSupport::Duration the number of seconds (b-a) = 9255600.0 seconds
remainder_seconds = 9255600.0
# Figure out how many years fit into the seconds using integer division.
years = (remainder_seconds/SECONDS_PER_YEAR).to_i # => 0
# Subtract the amount of years from the remaining_seconds
remainder_seconds -= years * SECONDS_PER_YEAR # => 9255600.0
months = (remainder_seconds/SECONDS_PER_MONTH).to_i # => 3
remainder_seconds -= months * SECONDS_PER_MONTH # => 1366362.0
weeks = (remainder_seconds/SECONDS_PER_WEEK).to_i # => 2
remainder_seconds -= weeks * SECONDS_PER_WEEK # => 156762.0
days = (remainder_seconds/SECONDS_PER_DAY).to_i # => 1
remainder_seconds -= days * SECONDS_PER_DAY # => 70362.0
hours = (remainder_seconds/SECONDS_PER_HOUR).to_i # => 19
remainder_seconds -= hours * SECONDS_PER_HOUR # => 1962.0
minutes = (remainder_seconds/SECONDS_PER_MINUTE).to_i # => 32
remainder_seconds -= minutes * SECONDS_PER_MINUTE # => 42
seconds = remainder_seconds # => 42
puts "#{years} years, #{months} months, #{weeks} weeks, #{days} days, #{hours} hours, #{minutes} minutes, #{seconds} seconds"
# 0 years, 3 months, 2 weeks, 1 days, 19 hours, 32 minutes, 42.0 seconds
To avoid the issue you are having, I would suggest to just represent the time in week, days, hours, minutes and seconds (basically anything excluding month & year).
The number of seconds in a month is complicated if you don't use an average since you will need to account for 28, 29, 30 and 31 days for each separate month. Similarly, for the year, you will need to account for leap/non-leap if you don't use the average.
I am not sure of any gems around which do this for you, however I can provide a function which can help you calculate the duration in days, hours, minutes and seconds below.
def duration_in_whms(seconds)
parts_and_seconds_in_part = {:weeks => 604800, :days => 86400, :hours => 3600, :minutes => 60}
result = {}
remainder = seconds
parts_and_seconds_in_part.each do |k, v|
result[k] = (remainder/v).to_i
remainder -= result[k]*v
end
result.merge(seconds: remainder)
end
duration_in_whms(9255600) => # {:weeks=>15, :days=>2, :hours=>3, :minutes=>0, :seconds=>0.0}
How to recover an integer from an ActiveSupport::Duration object
You can use the parts
accessor like this. The first element is what you call the duration_type
and the last one the integer value:
2.day.parts
=> [:days, 2]
Simple Rails App: Error Cannot visit Integer
The version of Ruby you're using (2.4.1) is not compatible with the version of Rails you're using (3.2.22.5). That version of Ruby requires at least Rails 5. Try downgrading to Ruby 2.3 or lower. You can use a Ruby version manager (i.e. rvm
, rbenv
or chruby
) to control which Ruby is used when launching your application.
Edit
Just noticed you're already using rbenv
from your stack trace. Add a .ruby-version
file to your application's directory containing the following line:
2.3.4
Once you re-enter that directory, confirm the version via:
$> ruby -v
ruby 2.3.4p301 (2017-03-30 revision 58214) [x86_64-darwin16]
(or similar version) before launching rails.
How do I resolve this error that keeps me from starting rails server?
Im not sure if that's the issue, since what you are seeing is just a warning. That warning appears because you are using ruby 2.4.0.
This version introduced this change: Unify Fixnum and Bignum into Integer
See here for the announcement: https://www.ruby-lang.org/en/news/2016/12/25/ruby-2-4-0-released/Z
The warnings come from the activesupport gem which is part of rails, and they will fix it soon.
Try downgrading your Ruby Version to 2.1 and try again.
Source
Mismatched ruby version after downgrade from 2.4.1 to 2.3.3 while running bundle install
Gem installation is specific to ruby version, so the bundler
you're using is likely installed to your old ruby. Try installing bundler
again:
gem install bundler
That should fix your problem.
Related Topics
Error Running '_Rvm_Make Install'
Shorten Long Numbers to Include K/M/B/T
Prepend a Single Line to File with Ruby
Establish a Connection to Another Database Only in a Block
Is There a Way Rails 3.0.X Can Default to Using Thin
Rmagick Remove White Background from Image and Make It Transparent
Rails "Undefined Method for Activerecord_Associations_Collectionproxy"
What Ide to Use for Developing in Ruby on Rails on Windows
Regex Match Everything Up to First Period
Redis or Mongo for Determining If a Number Falls Within Ranges
Overriding the == Operator in Ruby
Creating a Thread-Safe Temporary File Name
Suppressing the Output of a Command Run Using 'System' Method While Running It in a Ruby Script