I have a model named Widget
that has a single monetized attribute named advance
.
Each instance of a Widget
may have an advance
attribute that stores a unique currency and amount.
Despite setting up everything based on the gem documentation, and having the ability to switch between the default currency USD
and switching to other currencies, such as JPY
, CSD
, CNY
, switching to EUR
throws errors and prevents updating the advance_currency
and advance_cents
values.
Gem File
ruby "3.1.2"
gem "rails", "7.0.2.3"
gem "money-rails", "1.15.0"
Initializer File
Money.locale_backend = :currency
MoneyRails.configure do |config|
config.default_currency = :usd
config.include_validations = true
config.rounding_mode = BigDecimal::ROUND_HALF_UP
end
Migration Setup
create_table :widgets, force: :cascade do |t|
...
t.monetize :advance, amount: { limit: 8 }
end
Schema
create_table "widgets", force: :cascade do |t|
...
t.bigint "advance_cents", default: 0, null: false
t.string "advance_currency", default: "USD", null: false
...
end
Model Setup
class Widget < ApplicationRecord
...
monetize :advance_cents, with_model_currency: :advance_currency
...
end
Edit Form View Snippet
<div >
<%= select_tag("advance_currency", options_for_select(CurrencyTypes.options_for_select, @instance.advance_currency), prompt: "Select a currency", class: "form-select") %>
<label for="advance_currency" >Advance Currency</label>
</div>
<div >
<input type="number" step="any" id="advance" name="advance" value="<%= number_to_currency(@instance.advance, unit: "", separator: ".") %>">
<label for="advance" >Advance Amount</label>
</div>
Controller Update Action
def update
instance = controller_class.find(params[:id])
instance.update(update_params)
...
end
private
def update_params
params.permit(
...
:advance,
:advance_currency,
...
)
end
Messages Switching to Yen (Works)
Params Check
#<ActionController::Parameters {
...
"advance_currency"=>"JPY",
"advance"=>"987.65",
} permitted: false>
Debugging Update
> instance.update(update_params)
> instance.save
true
Debugging Errors
> instance.errors
#<ActiveModel::Errors []>
Error Message(s) Switching to Euro (Doesn't Work)
Params Check
#<ActionController::Parameters {
...
"advance_currency"=>"EUR",
"advance"=>"123.45",
} permitted: false>
Debugging Update
> instance.update(update_params)
> instance.save
false
Debugging Errors
> instance.errors
#<ActiveModel::Errors [#<ActiveModel::Error attribute=advance, type=invalid_currency, options={:thousands=>".", :decimal=>",", :currency=>"123.45", :attribute=>"Advance"}>]>
What doesn't make any sense is that when switching to Euro as the currency, the advance amount seems to be entered into the currency
value instead of EUR
.
I have no idea why one currency throws off the money-rails gem operations while the others work correctly.
CodePudding user response:
It seems like the use of the number
type input is the problem.
You can only submit values in Euro with the 123.456,78
format instead of 123,456.78
for the other currencies.
Since a comma is not allowed in the number
input type, you must switch to a type of text
Not Working
<div >
<input type="number" id="advance" name="advance" value="<%= @instance.advance %>">
<label for="advance" >Advance Amount</label>
</div>
Working
<div >
<input type="text" id="advance" name="advance" value="<%= @instance.advance %>">
<label for="advance" >Advance Amount</label>
</div>