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 }}
Related
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 => "$ ",
: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.
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.
I have totally nine buttons in rails. I have input the data into the database by manually typing the #button_1.save function.
My question is:
How can i have the #button_i.save function in rails? I have finished the things in the for loop, what is left is the button save functions.
Many thanks!
button_number = params[:button_number]
for i in (1..button_number)
instance_variable_set("#button#{i}",
Button.new(:title => params["button_title_#{i}".to_sym],
:order => i,
:icon_url => params["button_icon_#{i}".to_sym],
:navigation_id => #navigation.id,
:next_navigation => params["selected_navigation_#{i}".to_sym].to_i,
:next_page => params["selected_page_#{i}".to_sym].to_i))
instance_variable_set("#button#{i}")
end
#button1.save
#button2.save
#button3.save
#button4.save
#button5.save
#button6.save
for i in ...
eval("#button#{i}.save")
end
The opposite of instance_variable_set is instance_variable_get, which I think will lead you to the correct answer:
1.upto(params[:button_number].to_i) do |i|
instance_variable_set("#button#{i}",
Button.new(
:title => params["button_title_#{i}".to_sym],
:order => i,
:icon_url => params["button_icon_#{i}".to_sym],
:navigation_id => #navigation.id,
:next_navigation => params["selected_navigation_#{i}".to_sym].to_i,
:next_page => params["selected_page_#{i}".to_sym].to_i
)
)
instance_variable_get("#button#{i}").save
end
Try by using constantize ruby function because I think your function call statement is in string.
button_number = params[:button_number]
for i in (1..button_number)
instance_variable_set("#button#{i}",
Button.new(:title => params["button_title_#{i}".to_sym],
:order => i,
:icon_url => params["button_icon_#{i}".to_sym],
:navigation_id => #navigation.id,
:next_navigation => params["selected_navigation_#{i}".to_sym].to_i,
:next_page => params["selected_page_#{i}".to_sym].to_i))
"#button#{i}".constantize.save();
end
May be this that you want -
button_number = params[:button_number].to_i
for i in (1..button_number)
instance_variable_set("#button#{i}",
Button.new(:title => params["button_title_#{i}".to_sym],
:order => i,
:icon_url => params["button_icon_#{i}".to_sym],
:navigation_id => #navigation.id,
:next_navigation => params["selected_navigation_#{i}".to_sym].to_i,
:next_page => params["selected_page_#{i}".to_sym].to_i))
instance_variable_set("#button#{i}")
"#button#{i}".save
end
I have a donations table where I'm trying to calculate the total amount for each month. For months without without any donations, I'd like the result to return 0.
Here's my current query:
Donation.calculate(:sum, :amount, :conditions => {
:created_at => (Time.now.prev_year.all_year) },
:order => "EXTRACT(month FROM created_at)",
:group => ["EXTRACT(month FROM created_at)"])
which returns:
{7=>220392, 8=>334210, 9=>475188, 10=>323661, 11=>307689, 12=>439889}
Any ideas how to grab the empty months?
Normally you'd left join to a calendar table (or generate_series in PostgreSQL) to get the missing months but the easiest thing with Rails would be to merge your results into a Hash of zeroes; something like this:
class Donation
def self.by_month
h = Donation.calculate(:sum, :amount, :conditions => {
:created_at => (Time.now.prev_year.all_year) },
:order => "EXTRACT(month FROM created_at)",
:group => ["EXTRACT(month FROM created_at)"])
Hash[(1..12).map { |month| [ month, 0 ] }].merge(h)
end
end
then just call the class method, h = Donation.by_month, to get your results.
In addition to mu is too short answer, in Rails 3.2.12 did not work for me, ActiveRecord returns the keys as strings:
h = Donation.calculate(:sum, :amount, :conditions => {
:created_at => (Time.now.prev_year.all_year) },
:order => "EXTRACT(month FROM created_at)",
:group => ["EXTRACT(month FROM created_at)"])
Which returns:
{"7"=>220392, "8"=>334210, "9"=>475188, "10"=>323661, "11"=>307689, "12"=>439889}
So when I merge the hash with zeros:
{1=>0, 2=>0, 3=>0, 4=>0, 5=>0, 6=>0, 7=>0, 8=>0, 9=>0, 10=>0, 11=>0, 12=>0, "7"=>220392, "8"=>334210, "9"=>475188, "10"=>323661, "11"=>307689, "12"=>439889}
The little fix (to_s):
Hash[(1..12).map { |month| [ month.to_s, 0 ] }].merge(h)
I have the following:
#array.inspect
["x1", "x2", "adad"]
I would like to be able to format that to:
client.send_message(s, m, {:id => "x1", :id => "x2", :id => "adad" })
client.send_message(s, m, ???????)
How can I have the #array output in the ??????? space as a ids?
Thanks
{:id => "x1", :id => "x2", :id => "adad" } is not a valid hash since you have a key collision
it should look like:
{
"ids": ["x1", "x2", "x3"]
}
Update:
#a = ["x1", "x2", "adad"]
#b = #a.map { |e| {:id => e} }
Then you can do b.to_json, assuming you have done require "json" already
Well ordinarily you could do something like this:
Hash[#array.collect{|i| [:id, i]}]
But that will result in {:id => "adad"} because the first element will punch all the rest: hashes in ruby have unique keys. So I don't think there's a super awesome way to do this offhand.