箱のプログラミング日記。

えんじにあ奮闘記

NoMethodError: undefined method `new' for BigDecimal:Class と言われた時

f:id:y_hakoiri:20191102121915j:plain

Rubyのバージョンを2.7.0にあげてrake taskを実行したら見たことないエラーが出たので対処法をメモ。

  • Ruby...2.7.0

  • Rails...5.1.5

発生したエラー

NoMethodError: undefined method `new' for BigDecimal:Class

下記の記事によると、decimal型のカラムがあるインスタンスを取得しようとした時に発生するらしい。

RailsアプリをRuby 2.7.0で動かして分かったこと – PSYENCE:MEDIA

確かに今回取得使用しようとしたplayersテーブルを見ると、batting_averageカラムにdecimal型を使っている。

↓schema.rb

create_table "players", force: :cascade,  do |t|
  t.integer "status", null: false
  t.decimal "batting_average", precision: 5, scale: 2
end

decimal型

可変長浮動小数点の値。

  t.decimal "batting_average", precision: 5, scale: 2

この場合、有効桁数が5桁、少数点数が2桁。

pry(main)> Integer(2)
=> 2
pry(main)> BigDecimal(2)
=> 0.2e1
pry(main)> BigDecimal(2).to_i
=> 2

正確な演算処理が必要な場合はdecimal型を使う。

class BigDecimal (Ruby 2.7.0 リファレンスマニュアル)

MySQL :: MySQL 5.6 リファレンスマニュアル :: 11.2.2 固定小数点型 (真数値) - DECIMAL、NUMERIC

対処法

gem 'bigdecimal'をインストールする

後からちゃんと調べて分かったのだけど、bigdecimalライブラリはRuby標準なので本来はgemを入れなくても使えるが、Ruby2.7以降でエラーが発生してしまうからgemでバージョンを明示的にしてあげる必要がある、ということかな?多分。

試したこと

とりあえずgemを入れてみる

いくつかの記事でバージョンを指定せよと書いてあったが、とりあえず一旦何も指定せずインストールして解決しないかを試してみた

↓Gemfile

gem 'bigdecimal'
$ bundle install

↓Gemfile.lock

bigdecimal (2.0.0)

最新のバージョンがインストールされた。

この状態だとまだ同じエラーが発生してしまうようだった。やはりバージョンを指定して(下げて)あげないといけないぽい。

↓Gemfile

gem 'bigdecimal', 1.4.2
$ bundle install

↓Gemfile.lock

bigdecimal (1.4.2)

これでrake実行したところ、今度はエラーが解消されました。

参考

GitHub - ruby/bigdecimal: Arbitrary-precision decimal floating-point number library for Ruby

active support cannot load bigdecimal - gets an undefined symbol error · Issue #127 · ruby/bigdecimal · GitHub

Rails NoMethodError: undefined method new for BigDecimal:Class - Stack Overflow

undefined method `new' for BigDecimal:Class, Ruby 2.7 · Issue #321 · slack-ruby/slack-ruby-client · GitHub