Rails使用PostgreSQL Money类型时显示0.0而非真实数值
Hey there! Let's troubleshoot why those calculated Money fields in your Orders table are stuck showing 0.0 instead of their actual values. I’ve dealt with similar gotchas when using database triggers alongside Rails’ ActiveRecord, so here are the most common fixes to walk through:
1. Rails is using cached values instead of fresh database data
Since your triggers update the fields directly in the database, ActiveRecord might still hold onto the old (initial 0.0) values it loaded when the order object was first fetched. Try these quick checks:
- In your Rails console, fetch an order and call
reloadon it before accessing the fields:order = Order.find(your_order_id) puts order.subtotal # Might show 0.0 order.reload puts order.subtotal # Should now show the real value if the database has it - If that works, make sure to add
reloadin your controller before serializing the order for the API response:def show @order = Order.find(params[:id]).reload render json: @order end
2. Your Money type configuration is mismatched with the trigger’s target field
If you’re using the money-rails gem (super common for Money types in Rails), double-check your Orders model setup:
- By default,
money-railsstores monetary values as integer*_centsfields (e.g.,subtotal_cents) and creates a virtual Money object for thesubtotalattribute. If your trigger is updating thesubtotaldecimal field instead ofsubtotal_cents, Rails won’t pick up the change. - Verify your model has the correct
monetizecalls:class Order < ApplicationRecord # If your trigger updates subtotal_cents (integer) monetize :subtotal_cents, :fee_cents, :total_cents # OR if your trigger updates subtotal (decimal) monetize :subtotal, :fee, :total, as: :money end - Cross-check your database schema to confirm which fields the trigger is modifying (run
rails db:migrate:statusor look at your migration files).
3. The trigger itself isn’t working correctly
Before blaming Rails, confirm the trigger is actually writing the right values to the database:
- Run a direct SQL query in your database console to check the raw values:
SELECT subtotal, fee, total FROM orders WHERE id = your_order_id; - If the query returns 0.0 here, your trigger logic is the issue. Double-check the trigger’s calculation rules (e.g., is it referencing the right columns from join tables, or is there a typo in the arithmetic?).
4. Your API serializer is mishandling the Money object
If the values look correct in the Rails console but show 0.0 in the API response, your serializer might not be properly converting the Money object to a numeric value:
- If using ActiveModel::Serializers, adjust your serializer to explicitly convert the Money field:
class OrderSerializer < ActiveModel::Serializer attributes :id, :subtotal, :fee, :total def subtotal object.subtotal.to_f # or to_s if you want a formatted string end # Repeat for fee and total end - For FastJSONAPI, use a custom attribute block to handle the conversion similarly.
Start with the first check (reloading the object) since it’s the quickest win, then work your way down based on what you find.
内容的提问来源于stack exchange,提问作者Ricardo Villagrana

