PostgreSQLにmoney型というのがあるそうですよという話 - アクトインディ開発者ブログ

アクトインディ開発者ブログ

子供とお出かけ情報「いこーよ」を運営する、アクトインディ株式会社の開発者ブログです

PostgreSQLにmoney型というのがあるそうですよという話

こんにちは。kanekoです。 私はいこーよの中でもWEBチケット販売に関するプロダクトのチームにいます。社内での呼び方はいくつかありますがここではプロダクトをticket、チームをチケットチームとします。

この記事の結論

結論を述べますとDBがPostgreSQLのrailsアプリでmoney型のカラムをもつテーブルを作成してあれこれ試してみたところよく分からないこともあったが楽しかった。という感じです。(ざっくり)

money型との出会い

ticketではDBにPostgreSQLを採用しています。

チケットチームは今年動き始めたチームで、アクトインディでは初のECサービスの開発をしています。 私自身も初めてなことがたくさんあり毎日が勉強です。そんな中「DBのお金(料金、手数料ect)の扱いって何が正解なのかしら??」とふと検索したことがきっかけで、つい最近money型があると知りました。

www.postgresql.jp

これってRailsで使えるのかな?とRuby on Rails APIで検索するとありました!

api.rubyonrails.org

お試し

なんだかドキュメントを読んでもわかるような?わからないような?という感触だったので、サンプルアプリで試してみることにしました。アプリの名前はshopで、itemsテーブルを作成します。 itemの持つpriceをmoney型にします。

$ rails new shop -d postgresql
$ rails db:create
$ rails db:migrate
$ rails g scaffold Item name price:money
$ rails db:migrate

これでitemを扱うshopアプリが完成しました!

money型の値

生成されたschema.rbを見てみるとこのようになっていました。

  create_table "items", force: :cascade do |t|
    t.string "name"
    t.money "price", scale: 2
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

たしかにpriceはmoney型です。scale: 2とあるので小数点以下2桁まで桁数を持っています。

画面で入力してitemを作ってみます(画像左)。すると小数点以下2桁あるので、ここでは画像右のように表示されます。

f:id:neko314:20191114181630p:plain:w200 f:id:neko314:20191114182231p:plain:w200

DBで確認

これだけだとただの数値との違いがよくわからないのでDBで確認してみることにしました。rails dbを起動します。

# Select * FROM Items;
 id |  name  |  price  |         created_at         |        updated_at         
----+--------+---------+----------------------------+---------------------------
  2 | pencil | $200.00 | 2019-11-14 09:07:43.859319 | 2019-11-14 09:08:25.83563

$付きでpriceが表示されています!

でもticketでは全商品JPYで商品を扱っています。$扱いだとちょっと悲しい。 PostgreSQLのドキュメントには出力形式は通常は"典型的な"通貨書式となりますが、ロケールによって異なります。とあるので、まず試しにapplication.rbにjaを指定しました。

# application.rb
config.i18n.default_locale = :ja

その後railsを再起動しrails dbでもう一度確認してみます。

# Select * FROM Items;
 id |  name  |  price  |         created_at         |        updated_at         
----+--------+---------+----------------------------+---------------------------
  2 | pencil | $200.00 | 2019-11-14 09:07:43.859319 | 2019-11-14 09:08:25.83563

何も変わってない!!!!(そうは思っていました)

PostgeSQLのロケールとは

あまり考えたことがなかったのですが、そういえばどうなっているのでしょう?検索した結果以下のページを参照してみました。

lets.postgresql.jp

www.postgresql.jp

設定の確認方法の項目にあるコマンドで設定を確認してみます。するとen_USとなっていました。

# SELECT name, setting, context FROM pg_settings WHERE name LIKE 'lc%';
    name     |   setting   |  context  
-------------+-------------+-----------
 lc_collate  | en_US.UTF-8 | internal
 lc_ctype    | en_US.UTF-8 | internal
 lc_messages | en_US.UTF-8 | superuser
 lc_monetary | en_US.UTF-8 | user
 lc_numeric  | en_US.UTF-8 | user
 lc_time     | en_US.UTF-8 | user

lc_monetary 通貨の書式です。money 型の出力方式や解釈に影響します。

とのことなので、ここを日本に指定したら良さそうです。

# set lc_monetary="ja_JP.UTF-8";
SET
#  SELECT name, setting, context FROM pg_settings WHERE name LIKE 'lc%';
    name     |   setting   |  context  
-------------+-------------+-----------
 lc_collate  | en_US.UTF-8 | internal
 lc_ctype    | en_US.UTF-8 | internal
 lc_messages | en_US.UTF-8 | superuser
 lc_monetary | ja_JP.UTF-8 | user
 lc_numeric  | en_US.UTF-8 | user
 lc_time     | en_US.UTF-8 | user
# Select * FROM Items;
 id |  name  |  price  |         created_at         |        updated_at         
----+--------+---------+----------------------------+---------------------------
  2 | pencil | ¥20,000 | 2019-11-14 09:07:43.859319 | 2019-11-14 09:08:25.83563

¥になりました!!!

ただ、このコマンドだとセッション中の値の更新をしているだけなので根本的にはconfigファイルを更新する必要がありそうです。

よく見たら20,000円というめちゃくちゃ高級な鉛筆になってます! PostgreSQL上で表示の際に為替が考慮されいるようなのですが、追い切れなかったので割愛・・・

おまけ

railsには便利メソッドがたくさんありますが、number_to_currencyを使うと引数やアプリケーションの設定で指定したロケールの通貨で表示できてとても便利!

 -<%= @item.price %>
 +<%= number_to_currency(@item.price) %>

f:id:neko314:20191115122414p:plain:w200

感想

上述してないものもありますが、わかったことと感想を列挙します。

  • 使ったことのない型を試してみるのは純粋に楽しかったです。
  • PostgreSQL上で$200が¥20,000と表示されるのを¥200と表示されるように設定できたら、DBでデータ検索したい時にはわかりやすくて良さそうだと感じました。
  • DBのロケールは1つしか指定できないので、複数のロケールの対応は無理なようです。色々な貨幣通貨が混在する可能性がある時はこの型は使わない方が良いかもしれません。
  • DBのできることをもっと知っていきたいと思いました。私は飲み込みが遅い方なので何度ももやっていくうちに少しずつわかっていくタイプなのですが、少しずつでもいいので「こういう時にはこうやってデータを扱うといい」というのを血肉として身につけていきたいです。

最後に

以上、kanekoが業務から湧いた趣味と興味でやってみたという記事でした。最後まで読んでくださってありがとうございました。

アクトインディでは一緒に働くエンジニアを大募集しています。興味のある方はいつでもご連絡ください。 actindi.net