Error While Trying to Load the Gem 'Devise. Activesupport: Duration Can't Be Coerced into Integer

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



Leave a reply



Submit