8

精度8とスケール2の小数を含む移行を定義するRailsアプリケーションがあります。セットアップしたデータベースはPostgreSQL9.1データベースです。

class CreateMyModels < ActiveRecord::Migration
    def change
        create_table :my_models do |t|
            t.decimal :multiplier, precison: 8, scale: 2
            t.timestamps
        end
    end
end

を実行するrake db:migrateと、移行は正常に実行されますが、を実行しようとしたときにエラーが発生しましたMyModel.find_or_create_by_multiplier。次のコマンドを2回実行すると、オブジェクトが2回作成されます。

MyModel.find_or_create_by_multiplier(multiplier: 0.07)

これにより、最初の呼び出しでオブジェクトが作成され、2番目の呼び出しでオブジェクトが見つかると想定しています。残念ながら、これは乗数を0.07に設定した場合には発生しないようです。

これは、上記のコマンドでスローした他のすべての番号に対して期待どおりに機能します次のコマンドは期待どおりに機能します(最初の呼び出しでオブジェクトを作成し、2番目の呼び出しでオブジェクトを検索します)。

MyModel.find_or_create_by_multiplier(multiplier: 1.0)

MyModel.find_or_create_by_multiplier(multiplier: 0.05)

MyModel.find_or_create_by_multiplier(multiplier: 0.071)

MyModelテーブルのPostgreSQLデータベースの説明を表示すると、テーブルに数値列の制限がないことがわかります。

   Column    |            Type             |                         Modifiers
-------------+-----------------------------+-------------------------------------------------------
 id          | integer                     | not null default nextval('my_models_id_seq'::regclass)
 multiplier  | numeric                     | 
 created_at  | timestamp without time zone | not null
 updated_at  | timestamp without time zone | not null

私のdb/schema.rbファイルにも、精度とスケールが記載されていません。

ActiveRecord::Schema.define(:version => 20121206202800) do

...
    create_table "my_models", :force => true do |t|
        t.decimal  "multiplier"
        t.datetime "created_at",                   :null => false
        t.datetime "updated_at",                   :null => false
    end
...

だから私の最初の質問は、移行するときにPostgreSQLに精度とスケールが押し下げられないのはなぜですか?ドキュメントには、サポートする必要があると記載されています

私の2番目の質問は、なぜ0.07がMyModel.find_or_create_by_multiplier(multiplier: 0.07)コマンドを使用して正しく比較されないのですか?(これについて別の質問を開く必要がある場合は、そうします)。

4

3 に答える 3

12

これは恥ずかしいです...

精度のつづりが間違っています。

移行を次のように変更します。

t.decimal :multiplier, precision: 8, scale: 2

すべてを修正しました。

于 2013-01-11T03:57:05.077 に答える
2

PostgreSQL 9.1では、これらの方法のいずれかで列を宣言できます。

column_name decimal
column_name numeric
column_name decimal(8, 2)
column_name numeric(8, 2)

たとえば、pgAdminIIIを使用してその列を見ると、その列がどのように作成されたかが正確にわかります。あなた(またはRails)が列をとして作成した場合numeric、「数値」と表示されます。あなた(またはRails)が列をとして作成した場合decimal(8, 2)、「decimal(8,2)」と表示されます。

したがって、RailsがPostgreSQLに精度とスケールを渡していないように見えます。代わりに、「numeric」タイプの列を作成するようにPostgreSQLに指示しているだけです。Railsのドキュメントでは、そうすべきではないと示唆しています。

そのリンクの構文例は、あなたのものとは異なります。

td.column(:bill_gates_money, :decimal, :precision => 15, :scale => 2)
于 2013-01-11T03:51:03.967 に答える
0

最初は使って:numericいました。ActiveRecord:decimalは私のためにそれを変更しましたが、両方とも:precision無視:scaleされました。

# 202001010000000_add_my_col_to_my_table.rb
add_column :my_table, :my_col :numeric, percision: 3, scale: 2, comment: 'Foobar'

# schema.rb
t.decimal "my_col", comment: 'Foobar'

:decimal移行ファイルでに変更するだけで修正されました。

# 202001010000000_add_my_col_to_my_table.rb
add_column :my_table, :my_col :decimal, percision: 3, scale: 2, comment: 'Foobar'

# schema.rb
t.decimal "my_col", precision: 3, scale: 2, comment: 'Foobar'
于 2021-03-19T04:00:13.813 に答える