money-rails set custom currency - currency

I am in a rails 3.2.6 app using the gems money and money-rails.
For money-rails I have set-up an initializer with this data:
MoneyRails.configure do |config|
config.default_currency = :eur
config.register_currency = {
:id => :euc,
:priority => 1,
:iso_code => "EUR",
:name => "Euro with Comma decimal mark",
:symbol => "€",
:symbol_first => true,
:subunit => "Cent",
:subunit_to_unit => 100,
:thousands_separator => ".",
:decimal_mark => ","
}
end
Note I have created a new currency :euc, because I want to display the euro currency with the comma decimal separator,
but the problem is the money object doesn't display yet the comma, for example:
amount = Money.new(100, 'EUR')
amount.to_s
or in a view:
<%= humanized_money amount %>
it display "1.00 instead of "1,00"
where am I doing wrong?

Try using amount.format(decimal_mark: ",") for now. It seems like a bug.

Try
100.to_money('EUR')
Money.new(100) considers 100 to be in cents.

Related

How to configure decimal_mark and thousand_separator - Money Rails

I'm trying use the gem money-rails but with no success.
I live in Brazil and here the decimal mark is "," and the thousand separator is "."
So, I add the follow code in a money.rb initializer:
MoneyRails.configure do |config|
config.default_currency = :brl
config.register_currency = {
:id => :brl,
:priority => 1,
:iso_code => "BRL",
:name => "Real",
:symbol => "R$",
:symbol_first => true,
:subunit => "Cent",
:subunit_to_unit => 100,
:thousands_separator => ".",
:decimal_mark => ","
}
end
And in my model class "Produto":
class Produto < ApplicationRecord
attr_accessor :nome, :preco
monetize :preco_centavos
end
But when I try use this in Rails console I get a different behavior:
irb(main):001:0> p = Produto.new
=> #<Produto id: nil, nome: nil, preco_centavos: 0, preco_currency: "BRL", created_at: nil, updated_at: nil>
irb(main):002:0> p.preco = 1000.to_money
=> #<Money fractional:100 currency:BRL>
irb(main):003:0> p.preco.format
=> "R$1,000.00"
The format method return "R$1,000.00" when I expect "R$1.000,00".
Someone already passed for this?
PS: Sorry for my bad English
This is a bug (or at least a misleading feature) in the money-rails gem code. Set Money.use_i18n = false. Once you do this, then you won't need to do config.register_currency for the commas/decimals, at least. 1000.to_money('BRL').format yields "R$1.000,00".
See https://github.com/RubyMoney/money-rails/blob/4a35ae823843fba80c036e2332e80d6b9e06dcb5/lib/money-rails/active_model/validator.rb#L58 for why this is the case.

Can't change currency symbol on spree 3.0

I'm currently using Spree 3.0 and changed my currency to Colombian Peso (COP). Right now prices are shown like this: ₱80.000,00. I want them to look like this: $ 80.000. I have an idea on how to remove the two 0 after the comma but haven't been able to change the currency symbol for $. This is what I have so far:
in /config/initializers/spree.rb
Spree.config do |config|
config.logo = 'templo samadhi logo.png'
config.admin_interface_logo = 'templo samadhi logo.png'
country = Spree::Country.find_by_name('Colombia')
config.default_country_id = country.id if country.present?
config.checkout_zone = country.id
Money::Currency.register({
:priority => 1,
:iso_code => "COP",
:iso_numeric => country.id,
:name => "Colombia",
:symbol => "$ ",
:subunit => "Cent",
:subunit_to_unit => 100,
:separator => ".",
:delimiter => ","
})
end
This is somehow working because the ₱ symbol is getting removed but the $ is not showing up.
I appreciate if someone can help me with this.
UPDATE
I added the following and now I'm removing the two 0 after the comma but I'm also getting a $ after the price like this: 80.000 $.
So right now I don't know how to move the $ symbol before the price.
Spree::Money.class_eval do
def to_s
formatted = #money.format(#options)
formatted.gsub(/,00/, "")
formatted.symbol_position == :before
end
def to_html(options = { :html => true })
to_s
end
end
I was using this solution but found an issue when I try to process the payment through the stripe gateway, it actually needs the amount subunit to be "Cents" in order to make the currency conversion.
With the #luisjar answer you actually don't use subunits in the COP currency but they may be needed for some payment gateways like stripe. In order to use the COP currency (or any other currency) with a subunit but without showing it, you need to set the format property no_cents true. This is the way I show the amount in Colombian Peso currency like $ 10,000 COP.
Spree.config do |config|
#Change currency symbol for Colombia
country = Spree::Country.find_by_name('Colombia')
config.default_country_id = country.id if country.present?
config.checkout_zone = country.id
Spree::Money.class_eval do
def to_s
#money.format.gsub(/,00/, "")
#money.format(:symbol_position => :before, :with_currency => true, :no_cents => true)
end
def to_html(options = { :html => true })
to_s
end
end
Money::Currency.register({
:priority => 1,
:iso_code => "COP",
:iso_numeric => country.id,
:name => "Colombia",
:symbol => "$ ",
:subunit => "Cent",
:subunit_to_unit => 100,
:separator => ".",
:delimiter => ","
})
Spree::Price.update_all(currency: 'COP')
end
I hope this help to any other confused (like me) with the currencies in Spree.
You can read more about currency format in: https://github.com/RubyMoney/money/blob/master/lib/money/money/formatting.rb
With the code, you merely register another currency. Each product(-variant) has many prices, one per currency. You should make sure, probably in a migration, that all your prices on all your variants are updated to use the correct currency.
Spree::Price.update_all(currency: 'COP')
If you don't want to loose the Dollar prices, but instead want to add an additional price, you need to edit each one manually, or on a migration.
Spree::Price.find_each do |price|
Spree::Price.create(variant: price.variant, amount: price.amount * 1.337, currency: 'COP')
end
Where 1.337 is a conversion factor.
I finally found how to remove the two ceros after the comma, use the $ symbol but still use the Colombian peso Currency. This is the way I did it.
Spree.config do |config|
config.logo = 'templo samadhi logo.png'
config.admin_interface_logo = 'templo samadhi logo.png'
country = Spree::Country.find_by_name('Colombia')
config.default_country_id = country.id if country.present?
config.checkout_zone = country.id
Spree::Money.class_eval do
def to_s
#money.format.gsub(/,00/, "")
#money.format(:symbol_position => :before)
end
def to_html(options = { :html => true })
to_s
end
end
Money::Currency.register({
:priority => 1,
:iso_code => "COP",
:iso_numeric => country.id,
:name => "Colombia",
:symbol => "$ ",
:subunit => "Peso",
:subunit_to_unit => 1,
:separator => ".",
:delimiter => ","
})
end
Looking at documentation of class Currency (in gems/money_6.9.0/lib/money/currency.rb) I found better the following settings:
Money::Currency.register({
:priority => 1,
:iso_code => "COP",
:iso_numeric => country.id,
:name => "Peso",
:symbol => "$",
:html_entity => "&dollar; ",
:symbol_first => true,
:subunit => "Cent",
:subunit_to_unit => 100,
:separator => ".",
:delimiter => ","
})
The "name" attribute is the name of the currency, not the name of the country. The space between the $ and the number goes inside the "html_entity" and not in the symbol. Finally, the "symbol_first" attribute controls where to place the symbol.

Using money-rails minidollars unit instead of cents

By default, money save value in cents and create migration like price_cents:integer. I need to save and calculate values in minidollars (1/1000 of currency).
I don't register currencies myself.
I use gem google_currency for getting current currency rates.
How can i set precision 1/1000 for all money values?
* rails (4.2.1)
* money (6.5.1)
* money-rails (1.4.1)
* google_currency (3.2.0)
According to the documentation, you can register your own subunit:
curr = {
:priority => 1,
:iso_code => "USD",
:iso_numeric => "840",
:name => "United States Dollar",
:symbol => "$",
:subunit => "Minidollar",
:subunit_to_unit => 1000,
:separator => ".",
:delimiter => ","
}
Money::Currency.register(curr)
Google Currency just extends Money::Bank::VariableExchange, so now you'd do this to create a $1 item and get the value in Euros:
money = Money.new(10_00, "USD") # this is in "minidollars"
money.exchange_to(:EUR)

SpreeCommerce price format

I'm building a site for SpreeCommerce 2.1.3, and I'm stuck trying to figure out how to format the prices correctly.
The currency is DKK (Danish Kroner) and I'm looking for the following:
1000 => kr. 1.000,-
1000.50 => kr. 1.000,50
Spree formats my prices like this:
1000 => kr.1.000,00
1000.50 => kr.1.000,50
So there are two problems:
I need a space between kr. and the price.
When there arent any decimals, I would like the decimals rendered as ,- (example: 1.000,-)
How do I accomplish that?
Here's my configuration from config/initializers/spree.rb:
Spree.config do |config|
# [...]
config.currency = "DKK"
config.currency_symbol_position = "before"
config.currency_decimal_mark = ","
config.currency_thousands_separator = "."
end
Solution:
1) I added this decorator to Spree::Money (to replace ,00 with ,-):
Spree::Money.class_eval do
def to_s
formatted = #money.format(#options)
formatted.gsub(/,00$/, ",-")
end
def to_html(options = { :html => true })
to_s
end
end
2) I configured danish currency in my initializer (to add the space after kr.):
Money::Currency.register({
:priority => 1,
:iso_code => "DKK",
:iso_numeric => "208",
:name => "Danish krone",
:symbol => "kr. ",
:subunit => "Øre",
:subunit_to_unit => 100,
:separator => ".",
:delimiter => ","
})
You can customize https://github.com/spree/spree/blob/master/core/lib/spree/money.rb as you want by overriding it.

String to Array and Hash with Regexp

I would like to turn a string with opening hours like this:
"Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
Into this:
[ {:period => "Monday-Friday", :hours => "10:00-18:00"}, {:period => "Saturday", :hours => "12:00-17:00"}, {:period => "Sunday", :hours => "12:00-15:00"} ]
I'm trying it with the String.scan() method but can't figure out the Regexp.
Also if you have any suggestions of how to do it in reverse the best way (i.e. when getting the opening hours from a form.)
Update - Thank you all found perfect solutions! Right now I'm using (thanks kejadlen):
str.scan(/([\w-]+)>([\d:-]+)-([\d:]+)/).map { |(p,o,c)| {:period => p, :opens => o, :closes => c} }
But now how about reversing it =) So given:
[ {:opens=>"10:00", :closes=>"18:00", :period=>"Monday-Friday"},
{:opens=>"12:00", :closes=>"17:00", :period=>"Saturday"},
{:opens=>"12:00", :closes=>"15:00", :period=>"Sunday"} ]
I want to merge it to:
"Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
If you prefer one-liners:
s = "Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
s.split(/;/).map{|i| Hash[[[:period, :hours], i.split(/>/)].transpose]}
# or
s.split(/;/).map{|i| p, h = i.split(/>/); {:period => p, :hours => h}}
#=> [{:period=>"Monday-Friday", :hours=>"10:00-18:00"}, {:period=>"Saturday", :hours=>"12:00-17:00"}, {:period=>"Sunday", :hours=>"12:00-15:00"}]
Edit:
Regarding the reverse, this should do the job:
a.map{|i| "#{i[:period]}>#{i[:opens]}-#{i[:closes]}"}.join(';')
=> "Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
this is how I would do it
str="Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
periods = str.split(';')
#=> ["Monday-Friday>10:00-18:00", "Saturday>12:00-17:00", "Sunday>12:00-15:00"]
period_array=[]
periods.each do |period|
period_with_hours = period.split('>')
period_array << {:period => period_with_hours.first, :hours => period_with_hours.last}
end
period_array
#=> [{:period=>"Monday-Friday", :hours=>"10:00-18:00"}, {:period=>"Saturday", :hours=>"12:00-17:00"}, {:period=>"Sunday", :hours=>"12:00-15:00"}]
Try this:
String S = ([^\>]*)\>([^\;]*)\;
String T = " {:period => $1, :hours => $2}, "
originalString.replaceAll(S,T);
Might have to play with the regexp a little more but that should about do it.
Edit - Well, you asked for the answer in the context of ruby and I gave you the Java answer but the regular expression should work anyway...
This looks like it works
the_input.split(';').collect{|pair|
period, hours = pair.split('>')
{:period => period, :hours => hours}
}
=> [{:hours=>"10:00-18:00", :period=>"Monday-Friday"}, {:hours=>"12:00-17:00", :
period=>"Saturday"}, {:hours=>"12:00-15:00", :period=>"Sunday"}]
str.scan(/([\w-]+)>([\d:-]+)/).map {|(p,h)| {:period => p, :hours => h }}

Resources